From 19273210cc0935f79300ccf7b6c7b0432dafdd03 Mon Sep 17 00:00:00 2001 From: "yanjin.li" Date: Mon, 24 Mar 2025 10:56:29 +0800 Subject: [PATCH 001/221] Change Java Transfrom class from final to normal to implement Android auto outside --- .../main/java/org/maplibre/android/maps/Transform.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/Transform.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/Transform.java index 4c7cf8910ed0..3efc3c254df7 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/Transform.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/Transform.java @@ -26,7 +26,7 @@ * Responsible for synchronising {@link CameraPosition} state and notifying camera change listeners. *

*/ -public final class Transform implements MapView.OnCameraDidChangeListener { +public class Transform implements MapView.OnCameraDidChangeListener { private static final String TAG = "Mbgl-Transform"; @@ -73,7 +73,7 @@ void initialise(@NonNull MapLibreMap maplibreMap, @NonNull MapLibreMapOptions op @Nullable @UiThread - public final CameraPosition getCameraPosition() { + public CameraPosition getCameraPosition() { if (cameraPosition == null) { cameraPosition = invalidateCameraPosition(); } @@ -106,7 +106,7 @@ public void run() { * Internal use. */ @UiThread - public final void moveCamera(@NonNull MapLibreMap maplibreMap, CameraUpdate update, + public void moveCamera(@NonNull MapLibreMap maplibreMap, CameraUpdate update, @Nullable final MapLibreMap.CancelableCallback callback) { CameraPosition cameraPosition = update.getCameraPosition(maplibreMap); if (isValidCameraPosition(cameraPosition)) { @@ -130,7 +130,7 @@ public void run() { } @UiThread - final void easeCamera(@NonNull MapLibreMap maplibreMap, CameraUpdate update, int durationMs, + void easeCamera(@NonNull MapLibreMap maplibreMap, CameraUpdate update, int durationMs, boolean easingInterpolator, @Nullable final MapLibreMap.CancelableCallback callback) { CameraPosition cameraPosition = update.getCameraPosition(maplibreMap); @@ -153,7 +153,7 @@ final void easeCamera(@NonNull MapLibreMap maplibreMap, CameraUpdate update, int * Internal use. */ @UiThread - public final void animateCamera(@NonNull MapLibreMap maplibreMap, CameraUpdate update, int durationMs, + public void animateCamera(@NonNull MapLibreMap maplibreMap, CameraUpdate update, int durationMs, @Nullable final MapLibreMap.CancelableCallback callback) { CameraPosition cameraPosition = update.getCameraPosition(maplibreMap); if (isValidCameraPosition(cameraPosition)) { From db851a8295b099c560a8a8d25051d0b5d7894e32 Mon Sep 17 00:00:00 2001 From: springmeyer Date: Tue, 25 Mar 2025 16:14:28 -0700 Subject: [PATCH 002/221] Disable icon scaling if offset is applied Draft native version of https://github.com/maplibre/maplibre-gl-js/pull/5625 --- .../mbgl/shaders/gl/drawable_symbol_icon.hpp | 5 +++- .../mbgl/shaders/gl/drawable_symbol_sdf.hpp | 5 +++- include/mbgl/shaders/gl/symbol_icon.hpp | 6 +++-- include/mbgl/shaders/gl/symbol_sdf_icon.hpp | 5 +++- include/mbgl/shaders/gl/symbol_sdf_text.hpp | 5 +++- .../mbgl/shaders/gl/symbol_text_and_icon.hpp | 6 ++++- include/mbgl/shaders/mtl/symbol.hpp | 19 ++++++++----- include/mbgl/shaders/symbol_layer_ubo.hpp | 5 ++-- include/mbgl/shaders/vulkan/symbol.hpp | 15 ++++++++--- shaders/drawable.symbol_icon.vertex.glsl | 5 +++- shaders/drawable.symbol_sdf.vertex.glsl | 5 +++- .../drawable.symbol_text_and_icon.vertex.glsl | 5 +++- shaders/symbol_icon.vertex.glsl | 5 +++- shaders/symbol_sdf.vertex.glsl | 5 +++- shaders/symbol_text_and_icon.vertex.glsl | 5 +++- src/mbgl/gfx/symbol_drawable_data.hpp | 7 +++-- src/mbgl/programs/symbol_program.cpp | 11 ++++++-- src/mbgl/programs/symbol_program.hpp | 10 +++++-- .../renderer/layers/render_symbol_layer.cpp | 27 +++++++++++++++---- .../renderer/layers/symbol_layer_tweaker.cpp | 1 + 20 files changed, 122 insertions(+), 35 deletions(-) diff --git a/include/mbgl/shaders/gl/drawable_symbol_icon.hpp b/include/mbgl/shaders/gl/drawable_symbol_icon.hpp index 9ac73b34aa43..ad943cec607e 100644 --- a/include/mbgl/shaders/gl/drawable_symbol_icon.hpp +++ b/include/mbgl/shaders/gl/drawable_symbol_icon.hpp @@ -49,6 +49,7 @@ layout (std140) uniform SymbolDrawableUBO { highp float u_opacity_t; highp float u_halo_width_t; highp float u_halo_blur_t; + bool u_is_offset; }; layout (std140) uniform SymbolEvaluatedPropsUBO { @@ -115,7 +116,9 @@ lowp float opacity = u_opacity; 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles 4.0); - size *= perspective_ratio; + if (!u_is_offset) { + size *= perspective_ratio; + } float fontScale = u_is_text_prop ? size / 24.0 : size; diff --git a/include/mbgl/shaders/gl/drawable_symbol_sdf.hpp b/include/mbgl/shaders/gl/drawable_symbol_sdf.hpp index 12d88136a7cb..3613454a0487 100644 --- a/include/mbgl/shaders/gl/drawable_symbol_sdf.hpp +++ b/include/mbgl/shaders/gl/drawable_symbol_sdf.hpp @@ -57,6 +57,7 @@ layout (std140) uniform SymbolDrawableUBO { highp float u_opacity_t; highp float u_halo_width_t; highp float u_halo_blur_t; + bool u_is_offset; }; layout (std140) uniform SymbolEvaluatedPropsUBO { @@ -167,7 +168,9 @@ lowp float halo_blur = u_halo_blur; 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles 4.0); - size *= perspective_ratio; + if (!u_is_offset) { + size *= perspective_ratio; + } float fontScale = u_is_text_prop ? size / 24.0 : size; diff --git a/include/mbgl/shaders/gl/symbol_icon.hpp b/include/mbgl/shaders/gl/symbol_icon.hpp index bf96c3952d40..8afbda822046 100644 --- a/include/mbgl/shaders/gl/symbol_icon.hpp +++ b/include/mbgl/shaders/gl/symbol_icon.hpp @@ -32,6 +32,7 @@ uniform bool u_is_text; uniform bool u_pitch_with_map; uniform vec2 u_texsize; +uniform bool u_is_offset; out vec2 v_tex; out float v_fade_opacity; @@ -83,8 +84,9 @@ lowp float opacity = u_opacity; 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles 4.0); - size *= perspective_ratio; - + if (!u_is_offset) { + size *= perspective_ratio; + } float fontScale = u_is_text ? size / 24.0 : size; highp float symbol_rotation = 0.0; diff --git a/include/mbgl/shaders/gl/symbol_sdf_icon.hpp b/include/mbgl/shaders/gl/symbol_sdf_icon.hpp index 6094108c8635..cf7858b6b4a3 100644 --- a/include/mbgl/shaders/gl/symbol_sdf_icon.hpp +++ b/include/mbgl/shaders/gl/symbol_sdf_icon.hpp @@ -36,6 +36,7 @@ uniform highp float u_aspect_ratio; uniform highp float u_camera_to_center_distance; uniform float u_fade_change; uniform vec2 u_texsize; +uniform bool u_is_offset; out vec2 v_data0; out vec3 v_data1; @@ -139,7 +140,9 @@ lowp float halo_blur = u_halo_blur; 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles 4.0); - size *= perspective_ratio; + if (!u_is_offset) { + size *= perspective_ratio; + } float fontScale = u_is_text ? size / 24.0 : size; diff --git a/include/mbgl/shaders/gl/symbol_sdf_text.hpp b/include/mbgl/shaders/gl/symbol_sdf_text.hpp index eecf6ff6be0e..af0ddab61ae4 100644 --- a/include/mbgl/shaders/gl/symbol_sdf_text.hpp +++ b/include/mbgl/shaders/gl/symbol_sdf_text.hpp @@ -36,6 +36,7 @@ uniform highp float u_aspect_ratio; uniform highp float u_camera_to_center_distance; uniform float u_fade_change; uniform vec2 u_texsize; +uniform bool u_is_offset; out vec2 v_data0; out vec3 v_data1; @@ -139,7 +140,9 @@ lowp float halo_blur = u_halo_blur; 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles 4.0); - size *= perspective_ratio; + if (!u_is_offset) { + size *= perspective_ratio; + } float fontScale = u_is_text ? size / 24.0 : size; diff --git a/include/mbgl/shaders/gl/symbol_text_and_icon.hpp b/include/mbgl/shaders/gl/symbol_text_and_icon.hpp index 6cb8f109f3ad..eea4cd6fa2e2 100644 --- a/include/mbgl/shaders/gl/symbol_text_and_icon.hpp +++ b/include/mbgl/shaders/gl/symbol_text_and_icon.hpp @@ -36,6 +36,7 @@ uniform highp float u_camera_to_center_distance; uniform float u_fade_change; uniform vec2 u_texsize; uniform vec2 u_texsize_icon; +uniform bool u_is_offset; out vec4 v_data0; out vec4 v_data1; @@ -139,7 +140,10 @@ lowp float halo_blur = u_halo_blur; 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles 4.0); - size *= perspective_ratio; + if (!u_is_offset) { + size *= perspective_ratio; + } + float fontScale = size / 24.0; diff --git a/include/mbgl/shaders/mtl/symbol.hpp b/include/mbgl/shaders/mtl/symbol.hpp index 997f569b0a89..b72cdbbacdc6 100644 --- a/include/mbgl/shaders/mtl/symbol.hpp +++ b/include/mbgl/shaders/mtl/symbol.hpp @@ -39,9 +39,10 @@ struct alignas(16) SymbolDrawableUBO { /* 244 */ float opacity_t; /* 248 */ float halo_width_t; /* 252 */ float halo_blur_t; - /* 256 */ + /* 256 */ bool is_offset; + /* 260 */ }; -static_assert(sizeof(SymbolDrawableUBO) == 16 * 16, "wrong size"); +static_assert(sizeof(SymbolDrawableUBO) == 17 * 16, "wrong size"); struct alignas(16) SymbolTilePropsUBO { /* 0 */ /*bool*/ int is_text; @@ -149,8 +150,10 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]], 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles 4.0); - size *= perspective_ratio; - + if (!drawable.is_offset) { + size *= perspective_ratio; + } + const float fontScale = drawable.is_text_prop ? size / 24.0 : size; float symbol_rotation = 0.0; @@ -316,7 +319,9 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]], 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles 4.0); - size *= perspective_ratio; + if (!drawable.is_offset) { + size *= perspective_ratio; + } const float fontScale = drawable.is_text_prop ? size / 24.0 : size; @@ -529,7 +534,9 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]], 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles 4.0); - size *= perspective_ratio; + if (!drawable.is_offset) { + size *= perspective_ratio; + } const float fontScale = size / 24.0; diff --git a/include/mbgl/shaders/symbol_layer_ubo.hpp b/include/mbgl/shaders/symbol_layer_ubo.hpp index 84f176d0dc63..c35b4e29b462 100644 --- a/include/mbgl/shaders/symbol_layer_ubo.hpp +++ b/include/mbgl/shaders/symbol_layer_ubo.hpp @@ -28,9 +28,10 @@ struct alignas(16) SymbolDrawableUBO { /* 244 */ float opacity_t; /* 248 */ float halo_width_t; /* 252 */ float halo_blur_t; - /* 256 */ + /* 256 */ bool is_offset; + /* 260 */ }; -static_assert(sizeof(SymbolDrawableUBO) == 16 * 16); +static_assert(sizeof(SymbolDrawableUBO) == 17 * 16); struct alignas(16) SymbolTilePropsUBO { /* 0 */ /*bool*/ int is_text; diff --git a/include/mbgl/shaders/vulkan/symbol.hpp b/include/mbgl/shaders/vulkan/symbol.hpp index 75be0c266ca7..d959e12ddaf1 100644 --- a/include/mbgl/shaders/vulkan/symbol.hpp +++ b/include/mbgl/shaders/vulkan/symbol.hpp @@ -62,6 +62,7 @@ struct SymbolDrawableUBO { float opacity_t; float halo_width_t; float halo_blur_t; + bool is_offset; }; layout(std140, set = LAYER_SET_INDEX, binding = idSymbolDrawableUBO) readonly buffer SymbolDrawableUBOVector { @@ -106,7 +107,9 @@ void main() { 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles 4.0); - size *= perspective_ratio; + if (!drawable.is_offset) { + size *= perspective_ratio; + } const float fontScale = drawable.is_text_prop ? size / 24.0 : size; @@ -266,6 +269,7 @@ struct SymbolDrawableUBO { float opacity_t; float halo_width_t; float halo_blur_t; + bool is_offset; }; layout(std140, set = LAYER_SET_INDEX, binding = idSymbolDrawableUBO) readonly buffer SymbolDrawableUBOVector { @@ -335,7 +339,9 @@ void main() { 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles 4.0); - size *= perspective_ratio; + if (!drawable.is_offset) { + size *= perspective_ratio; + } const float fontScale = drawable.is_text_prop ? size / 24.0 : size; @@ -563,6 +569,7 @@ struct SymbolDrawableUBO { float opacity_t; float halo_width_t; float halo_blur_t; + bool is_offset; }; layout(std140, set = LAYER_SET_INDEX, binding = idSymbolDrawableUBO) readonly buffer SymbolDrawableUBOVector { @@ -634,7 +641,9 @@ void main() { 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles 4.0); - size *= perspective_ratio; + if (!drawable.is_offset) { + size *= perspective_ratio; + } const float fontScale = size / 24.0; diff --git a/shaders/drawable.symbol_icon.vertex.glsl b/shaders/drawable.symbol_icon.vertex.glsl index 678f3323b74f..567fccfc9a3c 100644 --- a/shaders/drawable.symbol_icon.vertex.glsl +++ b/shaders/drawable.symbol_icon.vertex.glsl @@ -39,6 +39,7 @@ layout (std140) uniform SymbolDrawableUBO { highp float u_opacity_t; highp float u_halo_width_t; highp float u_halo_blur_t; + bool u_is_offset; }; layout (std140) uniform SymbolEvaluatedPropsUBO { @@ -98,7 +99,9 @@ void main() { 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles 4.0); - size *= perspective_ratio; + if (!u_is_offset) { + size *= perspective_ratio; + } float fontScale = u_is_text_prop ? size / 24.0 : size; diff --git a/shaders/drawable.symbol_sdf.vertex.glsl b/shaders/drawable.symbol_sdf.vertex.glsl index 6c94980d7afe..1892e90a35be 100644 --- a/shaders/drawable.symbol_sdf.vertex.glsl +++ b/shaders/drawable.symbol_sdf.vertex.glsl @@ -47,6 +47,7 @@ layout (std140) uniform SymbolDrawableUBO { highp float u_opacity_t; highp float u_halo_width_t; highp float u_halo_blur_t; + bool u_is_offset; }; layout (std140) uniform SymbolEvaluatedPropsUBO { @@ -122,7 +123,9 @@ void main() { 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles 4.0); - size *= perspective_ratio; + if (!u_is_offset) { + size *= perspective_ratio; + } float fontScale = u_is_text_prop ? size / 24.0 : size; diff --git a/shaders/drawable.symbol_text_and_icon.vertex.glsl b/shaders/drawable.symbol_text_and_icon.vertex.glsl index 6035d4512770..2b1fe3f8811c 100644 --- a/shaders/drawable.symbol_text_and_icon.vertex.glsl +++ b/shaders/drawable.symbol_text_and_icon.vertex.glsl @@ -46,6 +46,7 @@ layout (std140) uniform SymbolDrawableUBO { highp float u_opacity_t; highp float u_halo_width_t; highp float u_halo_blur_t; + bool u_is_offset; }; layout (std140) uniform SymbolEvaluatedPropsUBO { @@ -121,7 +122,9 @@ void main() { 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles 4.0); - size *= perspective_ratio; + if (!u_is_offset) { + size *= perspective_ratio; + } float fontScale = size / 24.0; diff --git a/shaders/symbol_icon.vertex.glsl b/shaders/symbol_icon.vertex.glsl index 22142319583a..119071170f4b 100644 --- a/shaders/symbol_icon.vertex.glsl +++ b/shaders/symbol_icon.vertex.glsl @@ -22,6 +22,7 @@ uniform bool u_is_text; uniform bool u_pitch_with_map; uniform vec2 u_texsize; +uniform bool u_is_offset; out vec2 v_tex; out float v_fade_opacity; @@ -63,7 +64,9 @@ void main() { 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles 4.0); - size *= perspective_ratio; + if (!u_is_offset) { + size *= perspective_ratio; + } float fontScale = u_is_text ? size / 24.0 : size; diff --git a/shaders/symbol_sdf.vertex.glsl b/shaders/symbol_sdf.vertex.glsl index 2141399de272..1085ecffe6c8 100644 --- a/shaders/symbol_sdf.vertex.glsl +++ b/shaders/symbol_sdf.vertex.glsl @@ -26,6 +26,7 @@ uniform highp float u_aspect_ratio; uniform highp float u_camera_to_center_distance; uniform float u_fade_change; uniform vec2 u_texsize; +uniform bool u_is_offset; out vec2 v_data0; out vec3 v_data1; @@ -79,7 +80,9 @@ void main() { 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles 4.0); - size *= perspective_ratio; + if (!u_is_offset) { + size *= perspective_ratio; + } float fontScale = u_is_text ? size / 24.0 : size; diff --git a/shaders/symbol_text_and_icon.vertex.glsl b/shaders/symbol_text_and_icon.vertex.glsl index f4812aacc63c..189eb230dd6b 100644 --- a/shaders/symbol_text_and_icon.vertex.glsl +++ b/shaders/symbol_text_and_icon.vertex.glsl @@ -26,6 +26,7 @@ uniform highp float u_camera_to_center_distance; uniform float u_fade_change; uniform vec2 u_texsize; uniform vec2 u_texsize_icon; +uniform bool u_is_offset; out vec4 v_data0; out vec4 v_data1; @@ -79,7 +80,9 @@ void main() { 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles 4.0); - size *= perspective_ratio; + if (!u_is_offset) { + size *= perspective_ratio; + } float fontScale = size / 24.0; diff --git a/src/mbgl/gfx/symbol_drawable_data.hpp b/src/mbgl/gfx/symbol_drawable_data.hpp index 6688b39ecaa1..fd7e3be04724 100644 --- a/src/mbgl/gfx/symbol_drawable_data.hpp +++ b/src/mbgl/gfx/symbol_drawable_data.hpp @@ -19,14 +19,16 @@ struct SymbolDrawableData : public DrawableData { const style::AlignmentType pitchAlignment_, const style::AlignmentType rotationAlignment_, const style::SymbolPlacementType placement_, - const style::IconTextFitType textFit_) + const style::IconTextFitType textFit_, + const bool isOffset_) : isHalo(isHalo_), bucketVariablePlacement(bucketVariablePlacement_), symbolType(symbolType_), pitchAlignment(pitchAlignment_), rotationAlignment(rotationAlignment_), placement(placement_), - textFit(textFit_) {} + textFit(textFit_), + isOffset(isOffset_) {} ~SymbolDrawableData() override = default; const bool isHalo; @@ -36,6 +38,7 @@ struct SymbolDrawableData : public DrawableData { const style::AlignmentType rotationAlignment; const style::SymbolPlacementType placement; const style::IconTextFitType textFit; + const bool isOffset; }; using UniqueSymbolDrawableData = std::unique_ptr; diff --git a/src/mbgl/programs/symbol_program.cpp b/src/mbgl/programs/symbol_program.cpp index 52037f8c01c3..3c610f941de4 100644 --- a/src/mbgl/programs/symbol_program.cpp +++ b/src/mbgl/programs/symbol_program.cpp @@ -44,6 +44,7 @@ Values makeValues(const bool isText, const RenderTile& tile, const TransformState& state, const float symbolFadeChange, + const bool isOffset, Args&&... args) { std::array extrudeScale; @@ -88,6 +89,7 @@ Values makeValues(const bool isText, uniforms::pitch_with_map::Value(pitchWithMap), uniforms::rotate_symbol::Value(rotateInShader), uniforms::aspect_ratio::Value(state.getSize().aspectRatio()), + uniforms::is_offset::Value(isOffset), std::forward(args)...}; } @@ -100,9 +102,10 @@ SymbolIconProgram::LayoutUniformValues SymbolIconProgram::layoutUniformValues( const bool alongLine, const RenderTile& tile, const TransformState& state, - const float symbolFadeChange) { + const float symbolFadeChange, + const bool isOffset) { return makeValues( - isText, hasVariablePacement, values, texsize, pixelsToGLUnits, alongLine, tile, state, symbolFadeChange); + isText, hasVariablePacement, values, texsize, pixelsToGLUnits, alongLine, tile, state, symbolFadeChange, isOffset); } template @@ -117,6 +120,7 @@ SymbolSDFProgram::layoutUniformValues(const const RenderTile& tile, const TransformState& state, const float symbolFadeChange, + const bool isOffset, const SymbolSDFPart part) { const float gammaScale = (values.pitchAlignment == AlignmentType::Map ? static_cast(std::cos(state.getPitch())) * state.getCameraToCenterDistance() @@ -132,6 +136,7 @@ SymbolSDFProgram::layoutUniformValues(const tile, state, symbolFadeChange, + isOffset, uniforms::gamma_scale::Value(gammaScale), uniforms::device_pixel_ratio::Value(pixelRatio), uniforms::is_halo::Value(part == SymbolSDFPart::Halo)); @@ -148,6 +153,7 @@ SymbolTextAndIconProgram::LayoutUniformValues SymbolTextAndIconProgram::layoutUn const RenderTile& tile, const TransformState& state, const float symbolFadeChange, + const bool isOffset, const SymbolSDFPart part) { return {SymbolSDFProgram(uniforms::texsize::Value(texsize_icon)))}; } diff --git a/src/mbgl/programs/symbol_program.hpp b/src/mbgl/programs/symbol_program.hpp index 4aadbbc1bf92..477609db418c 100644 --- a/src/mbgl/programs/symbol_program.hpp +++ b/src/mbgl/programs/symbol_program.hpp @@ -48,6 +48,7 @@ MBGL_DEFINE_UNIFORM_SCALAR(float, size_t); MBGL_DEFINE_UNIFORM_SCALAR(float, size); MBGL_DEFINE_UNIFORM_SCALAR(bool, rotate_symbol); MBGL_DEFINE_UNIFORM_SCALAR(float, aspect_ratio); +MBGL_DEFINE_UNIFORM_SCALAR(bool, is_offset); } // namespace uniforms using SymbolLayoutAttributes = TypeList, attributes::pixeloffset>; @@ -409,7 +410,8 @@ class SymbolIconProgram final : public SymbolProgram, + uniforms::aspect_ratio, + uniforms::is_offset>, TypeList, style::IconPaintProperties> { public: @@ -426,7 +428,8 @@ class SymbolIconProgram final : public SymbolProgram; @@ -482,6 +486,7 @@ class SymbolSDFProgram : public SymbolProgram(*renderData.bucket); const auto& evaluated = getEvaluated(renderData.layerProperties); @@ -180,6 +181,7 @@ void drawIcon(const RenderSymbolLayer::Programs& programs, tile, parameters.state, parameters.symbolFadeChange, + isOffset, SymbolSDFPart::Halo), bucket.sdfIcon, iconSegments, @@ -202,6 +204,7 @@ void drawIcon(const RenderSymbolLayer::Programs& programs, tile, parameters.state, parameters.symbolFadeChange, + isOffset, SymbolSDFPart::Fill), bucket.sdfIcon, iconSegments, @@ -221,7 +224,8 @@ void drawIcon(const RenderSymbolLayer::Programs& programs, alongLine, tile, parameters.state, - parameters.symbolFadeChange), + parameters.symbolFadeChange, + isOffset), bucket.icon, iconSegments, bucket.iconSizeBinder, @@ -239,7 +243,8 @@ void drawText(const RenderSymbolLayer::Programs& programs, const LayerRenderData& renderData, SegmentsWrapper textSegments, const SymbolBucket::PaintProperties& bucketPaintProperties, - const PaintParameters& parameters) { + const PaintParameters& parameters, + const bool isOffset) { const auto& bucket = static_cast(*renderData.bucket); const auto& evaluated = getEvaluated(renderData.layerProperties); const auto& layout = *bucket.layout; @@ -285,6 +290,7 @@ void drawText(const RenderSymbolLayer::Programs& programs, tile, parameters.state, parameters.symbolFadeChange, + isOffset, SymbolSDFPart::Halo), SymbolTextAndIconProgram::TextureBindings{glyphTextureBinding, iconTextureBinding}, SymbolSDFPart::Halo); @@ -302,6 +308,7 @@ void drawText(const RenderSymbolLayer::Programs& programs, tile, parameters.state, parameters.symbolFadeChange, + isOffset, SymbolSDFPart::Fill), SymbolTextAndIconProgram::TextureBindings{glyphTextureBinding, iconTextureBinding}, SymbolSDFPart::Fill); @@ -319,6 +326,7 @@ void drawText(const RenderSymbolLayer::Programs& programs, tile, parameters.state, parameters.symbolFadeChange, + isOffset, SymbolSDFPart::Halo), SymbolSDFTextProgram::TextureBindings{glyphTextureBinding}, SymbolSDFPart::Halo); @@ -336,6 +344,7 @@ void drawText(const RenderSymbolLayer::Programs& programs, tile, parameters.state, parameters.symbolFadeChange, + isOffset, SymbolSDFPart::Fill), SymbolSDFTextProgram::TextureBindings{glyphTextureBinding}, SymbolSDFPart::Fill); @@ -425,6 +434,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters) { const bool sortFeaturesByKey = !impl_cast(baseImpl).layout.get().isUndefined(); std::multiset renderableSegments; + const bool isOffset = !impl_cast(baseImpl).layout.get().isUndefined(); const auto draw = [¶meters, this](auto& programInstance, const auto& uniformValues, @@ -521,6 +531,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters) { std::cref(bucket.icon.segments), bucketPaintProperties, parameters, + isOffset, false /*sdfIcon*/ ); } @@ -537,6 +548,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters) { std::cref(bucket.sdfIcon.segments), bucketPaintProperties, parameters, + isOffset, true /*sdfIcon*/ ); } @@ -552,7 +564,8 @@ void RenderSymbolLayer::render(PaintParameters& parameters) { *renderData, std::cref(bucket.text.segments), bucketPaintProperties, - parameters); + parameters, + isOffset); } } @@ -643,7 +656,8 @@ void RenderSymbolLayer::render(PaintParameters& parameters) { renderable.renderData, renderable.segment, renderable.bucketPaintProperties, - parameters); + parameters, + isOffset); } else { drawIcon(programs, draw, @@ -652,6 +666,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters) { renderable.segment, renderable.bucketPaintProperties, parameters, + isOffset, renderable.type == SymbolType::IconSDF); } } @@ -980,6 +995,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, const bool sortFeaturesByKey = !impl_cast(baseImpl).layout.get().isUndefined(); std::multiset renderableSegments; std::unique_ptr builder; + const bool isOffset = !impl_cast(baseImpl).layout.get().isUndefined(); const auto currentZoom = static_cast(state.getZoom()); const auto layerPrefix = getID() + "/"; @@ -1283,7 +1299,8 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, /*.pitchAlignment=*/values.pitchAlignment, /*.rotationAlignment=*/values.rotationAlignment, /*.placement=*/layout.get(), - /*.textFit=*/layout.get())); + /*.textFit=*/layout.get(), + /*.isOffset=*/isOffset)); tileLayerGroup->addDrawable(passes, tileID, std::move(drawable)); ++stats.drawablesAdded; diff --git a/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp b/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp index 2553b8241530..62c6f8f91bc1 100644 --- a/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp @@ -178,6 +178,7 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParamete .opacity_t = getInterpFactor(paintProperties, isText, zoom), .halo_width_t = getInterpFactor(paintProperties, isText, zoom), .halo_blur_t = getInterpFactor(paintProperties, isText, zoom), + .is_offset = symbolData.isOffset, }; #if MLN_UBO_CONSOLIDATION From 2468615cdc5e8db2981c6697d10e78c588737757 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 25 Mar 2025 23:21:31 +0000 Subject: [PATCH 003/221] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- include/mbgl/shaders/mtl/symbol.hpp | 2 +- src/mbgl/programs/symbol_program.cpp | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/mbgl/shaders/mtl/symbol.hpp b/include/mbgl/shaders/mtl/symbol.hpp index b72cdbbacdc6..ebf50ab2b42f 100644 --- a/include/mbgl/shaders/mtl/symbol.hpp +++ b/include/mbgl/shaders/mtl/symbol.hpp @@ -153,7 +153,7 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]], if (!drawable.is_offset) { size *= perspective_ratio; } - + const float fontScale = drawable.is_text_prop ? size / 24.0 : size; float symbol_rotation = 0.0; diff --git a/src/mbgl/programs/symbol_program.cpp b/src/mbgl/programs/symbol_program.cpp index 3c610f941de4..920debcea173 100644 --- a/src/mbgl/programs/symbol_program.cpp +++ b/src/mbgl/programs/symbol_program.cpp @@ -104,8 +104,16 @@ SymbolIconProgram::LayoutUniformValues SymbolIconProgram::layoutUniformValues( const TransformState& state, const float symbolFadeChange, const bool isOffset) { - return makeValues( - isText, hasVariablePacement, values, texsize, pixelsToGLUnits, alongLine, tile, state, symbolFadeChange, isOffset); + return makeValues(isText, + hasVariablePacement, + values, + texsize, + pixelsToGLUnits, + alongLine, + tile, + state, + symbolFadeChange, + isOffset); } template From 7e5e0593fcc892c52c168623da974bf623e72bc4 Mon Sep 17 00:00:00 2001 From: springmeyer Date: Fri, 28 Mar 2025 11:36:06 -0700 Subject: [PATCH 004/221] update another shader --- include/mbgl/shaders/gl/drawable_symbol_text_and_icon.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/mbgl/shaders/gl/drawable_symbol_text_and_icon.hpp b/include/mbgl/shaders/gl/drawable_symbol_text_and_icon.hpp index 4b55116f1297..4b641fb6c115 100644 --- a/include/mbgl/shaders/gl/drawable_symbol_text_and_icon.hpp +++ b/include/mbgl/shaders/gl/drawable_symbol_text_and_icon.hpp @@ -56,6 +56,7 @@ layout (std140) uniform SymbolDrawableUBO { highp float u_opacity_t; highp float u_halo_width_t; highp float u_halo_blur_t; + bool u_is_offset; }; layout (std140) uniform SymbolEvaluatedPropsUBO { @@ -166,7 +167,9 @@ lowp float halo_blur = u_halo_blur; 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles 4.0); - size *= perspective_ratio; + if (!u_is_offset) { + size *= perspective_ratio; + } float fontScale = size / 24.0; From 7fbeb252ea81d8851bc899bfa05399860fdb6e4b Mon Sep 17 00:00:00 2001 From: springmeyer Date: Fri, 28 Mar 2025 14:31:29 -0700 Subject: [PATCH 005/221] DRY up the code + put temporary debug logs to help figure out what is wrong on vulkan --- .../renderer/layers/render_symbol_layer.cpp | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index 4d74d3b5dccf..de06f8a0e572 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #if MLN_DRAWABLE_RENDERER #include @@ -433,9 +434,10 @@ void RenderSymbolLayer::render(PaintParameters& parameters) { if (!parameters.shaders.getLegacyGroup().populate(programs.collisionBoxProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(programs.collisionCircleProgram)) return; - const bool sortFeaturesByKey = !impl_cast(baseImpl).layout.get().isUndefined(); + const auto& layout = impl_cast(baseImpl).layout; + const bool sortFeaturesByKey = !layout.get().isUndefined(); std::multiset renderableSegments; - const bool isOffset = !impl_cast(baseImpl).layout.get().isUndefined(); + const bool isOffset = !layout.get().isUndefined(); const auto draw = [¶meters, this](auto& programInstance, const auto& uniformValues, @@ -993,10 +995,12 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, }); } - const bool sortFeaturesByKey = !impl_cast(baseImpl).layout.get().isUndefined(); + const auto& layout = impl_cast(baseImpl).layout; + const bool sortFeaturesByKey = !layout.get().isUndefined(); std::multiset renderableSegments; std::unique_ptr builder; - const bool isOffset = !impl_cast(baseImpl).layout.get().isUndefined(); + const bool isOffset = !layout.get().isUndefined(); + std::clog << " isOffset " << isOffset << std::endl; const auto currentZoom = static_cast(state.getZoom()); const auto layerPrefix = getID() + "/"; @@ -1042,8 +1046,8 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, return; } - const auto& layout = *bucket.layout; - const auto values = isText ? textPropertyValues(evaluated, layout) : iconPropertyValues(evaluated, layout); + const auto& bucketLayout = *bucket.layout; + const auto values = isText ? textPropertyValues(evaluated, bucketLayout) : iconPropertyValues(evaluated, bucketLayout); const std::string suffix = isText ? "text/" : "icon/"; const auto addVertices = [&collisionBuilder](const auto& vertices) { @@ -1188,8 +1192,8 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, const auto& evaluated = getEvaluated(renderable.renderData.layerProperties); auto& bucketPaintProperties = bucket.paintProperties.at(getID()); - const auto& layout = *bucket.layout; - const auto values = isText ? textPropertyValues(evaluated, layout) : iconPropertyValues(evaluated, layout); + const auto& bucketLayout = *bucket.layout; + const auto values = isText ? textPropertyValues(evaluated, bucketLayout) : iconPropertyValues(evaluated, bucketLayout); const auto& atlases = tile.getAtlasTextures(); if (!atlases) { @@ -1239,7 +1243,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, textSizeIsZoomConstant); } if (!isText && !tileInfo.iconTweaker) { - const bool iconScaled = layout.get().constantOr(1.0) != 1.0 || bucket.iconsNeedLinear; + const bool iconScaled = bucketLayout.get().constantOr(1.0) != 1.0 || bucket.iconsNeedLinear; tileInfo.iconTweaker = std::make_shared(atlases, idSymbolImageIconTexture, idSymbolImageTexture, @@ -1299,8 +1303,8 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, /*.symbolType=*/renderable.type, /*.pitchAlignment=*/values.pitchAlignment, /*.rotationAlignment=*/values.rotationAlignment, - /*.placement=*/layout.get(), - /*.textFit=*/layout.get(), + /*.placement=*/bucketLayout.get(), + /*.textFit=*/bucketLayout.get(), /*.isOffset=*/isOffset)); tileLayerGroup->addDrawable(passes, tileID, std::move(drawable)); From d41e375cd2208e6875375299ab4ad3927c5616c5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 28 Mar 2025 21:34:08 +0000 Subject: [PATCH 006/221] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/mbgl/renderer/layers/render_symbol_layer.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index de06f8a0e572..ed399cd85fe9 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -1047,7 +1047,8 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, } const auto& bucketLayout = *bucket.layout; - const auto values = isText ? textPropertyValues(evaluated, bucketLayout) : iconPropertyValues(evaluated, bucketLayout); + const auto values = isText ? textPropertyValues(evaluated, bucketLayout) + : iconPropertyValues(evaluated, bucketLayout); const std::string suffix = isText ? "text/" : "icon/"; const auto addVertices = [&collisionBuilder](const auto& vertices) { @@ -1193,7 +1194,8 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, auto& bucketPaintProperties = bucket.paintProperties.at(getID()); const auto& bucketLayout = *bucket.layout; - const auto values = isText ? textPropertyValues(evaluated, bucketLayout) : iconPropertyValues(evaluated, bucketLayout); + const auto values = isText ? textPropertyValues(evaluated, bucketLayout) + : iconPropertyValues(evaluated, bucketLayout); const auto& atlases = tile.getAtlasTextures(); if (!atlases) { From 8f8915f6a640a41f248e0fc1c7e5bb691088c197 Mon Sep 17 00:00:00 2001 From: springmeyer Date: Fri, 28 Mar 2025 14:50:37 -0700 Subject: [PATCH 007/221] fix variable shadowing issue --- .../renderer/layers/render_symbol_layer.cpp | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index ed399cd85fe9..e9771217c1ba 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -152,14 +152,14 @@ void drawIcon(const RenderSymbolLayer::Programs& programs, const bool sdfIcons) { auto& bucket = static_cast(*renderData.bucket); const auto& evaluated = getEvaluated(renderData.layerProperties); - const auto& layout = *bucket.layout; - auto values = iconPropertyValues(evaluated, layout); + const auto& bucketLayout = *bucket.layout; + auto values = iconPropertyValues(evaluated, bucketLayout); const auto& paintPropertyValues = RenderSymbolLayer::iconPaintProperties(evaluated); - const bool alongLine = layout.get() != SymbolPlacementType::Point && - layout.get() == AlignmentType::Map; + const bool alongLine = bucketLayout.get() != SymbolPlacementType::Point && + bucketLayout.get() == AlignmentType::Map; - const bool iconScaled = layout.get().constantOr(1.0) != 1.0 || bucket.iconsNeedLinear; + const bool iconScaled = bucketLayout.get().constantOr(1.0) != 1.0 || bucket.iconsNeedLinear; const bool iconTransformed = values.rotationAlignment == AlignmentType::Map || parameters.state.getPitch() != 0; const bool linear = sdfIcons || parameters.state.isChanging() || iconScaled || iconTransformed; @@ -167,7 +167,7 @@ void drawIcon(const RenderSymbolLayer::Programs& programs, const gfx::TextureBinding textureBinding = tile.getIconAtlasTextureBinding(filterType); const Size& iconSize = tile.getIconAtlasTexture()->getSize(); - const bool variablePlacedIcon = bucket.hasVariablePlacement && layout.get() != IconTextFitType::None; + const bool variablePlacedIcon = bucket.hasVariablePlacement && bucketLayout.get() != IconTextFitType::None; if (sdfIcons) { if (values.hasHalo) { @@ -248,12 +248,12 @@ void drawText(const RenderSymbolLayer::Programs& programs, const bool isOffset) { const auto& bucket = static_cast(*renderData.bucket); const auto& evaluated = getEvaluated(renderData.layerProperties); - const auto& layout = *bucket.layout; + const auto& bucketLayout = *bucket.layout; - const auto values = textPropertyValues(evaluated, layout); + const auto values = textPropertyValues(evaluated, bucketLayout); const auto& paintPropertyValues = RenderSymbolLayer::textPaintProperties(evaluated); - const bool alongLine = layout.get() != SymbolPlacementType::Point && + const bool alongLine = bucketLayout.get() != SymbolPlacementType::Point && values.rotationAlignment == AlignmentType::Map; const Size& glyphTexSize = tile.getGlyphAtlasTexture()->getSize(); @@ -585,8 +585,8 @@ void RenderSymbolLayer::render(PaintParameters& parameters) { std::array extrudeScale = {{parameters.pixelsToGLUnits[0] / (pixelRatio * scale), parameters.pixelsToGLUnits[1] / (pixelRatio * scale)}}; const auto& evaluated = getEvaluated(renderData->layerProperties); - const auto& layout = *bucket.layout; - const auto values = isText ? textPropertyValues(evaluated, layout) : iconPropertyValues(evaluated, layout); + const auto& bucketLayout = *bucket.layout; + const auto values = isText ? textPropertyValues(evaluated, bucketLayout) : iconPropertyValues(evaluated, bucketLayout); const bool needTranslate = values.translate[0] != 0 || values.translate[1] != 0; if (hasCollisionBox) { From 67743c43d3c108b05b63cc7e78eaa8abfdcf71f2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 28 Mar 2025 21:51:26 +0000 Subject: [PATCH 008/221] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../renderer/layers/render_symbol_layer.cpp | 151 +++++++++--------- 1 file changed, 76 insertions(+), 75 deletions(-) diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index e9771217c1ba..fde6c2317259 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -167,7 +167,8 @@ void drawIcon(const RenderSymbolLayer::Programs& programs, const gfx::TextureBinding textureBinding = tile.getIconAtlasTextureBinding(filterType); const Size& iconSize = tile.getIconAtlasTexture()->getSize(); - const bool variablePlacedIcon = bucket.hasVariablePlacement && bucketLayout.get() != IconTextFitType::None; + const bool variablePlacedIcon = bucket.hasVariablePlacement && + bucketLayout.get() != IconTextFitType::None; if (sdfIcons) { if (values.hasHalo) { @@ -572,80 +573,80 @@ void RenderSymbolLayer::render(PaintParameters& parameters) { } } - const auto drawCollisonData = [&](const bool isText, - const bool hasCollisionBox, - const bool hasCollisionCircle) { - if (!hasCollisionBox && !hasCollisionCircle) return; - - static const style::Properties<>::PossiblyEvaluated properties{}; - static const CollisionBoxProgram::Binders paintAttributeData(properties, 0); - const auto pixelRatio = tile.id.pixelsToTileUnits(1.0f, static_cast(parameters.state.getZoom())); - const auto scale = static_cast( - std::pow(2, parameters.state.getZoom() - tile.getOverscaledTileID().overscaledZ)); - std::array extrudeScale = {{parameters.pixelsToGLUnits[0] / (pixelRatio * scale), - parameters.pixelsToGLUnits[1] / (pixelRatio * scale)}}; - const auto& evaluated = getEvaluated(renderData->layerProperties); - const auto& bucketLayout = *bucket.layout; - const auto values = isText ? textPropertyValues(evaluated, bucketLayout) : iconPropertyValues(evaluated, bucketLayout); - const bool needTranslate = values.translate[0] != 0 || values.translate[1] != 0; - - if (hasCollisionBox) { - const auto& collisionBox = isText ? bucket.textCollisionBox : bucket.iconCollisionBox; - programs.collisionBoxProgram->draw( - parameters.context, - *parameters.renderPass, - gfx::Lines{1.0f}, - gfx::DepthMode::disabled(), - gfx::StencilMode::disabled(), - parameters.colorModeForRenderPass(), - gfx::CullFaceMode::disabled(), - CollisionBoxProgram::LayoutUniformValues{ - uniforms::matrix::Value( - (needTranslate - ? tile.translatedMatrix(values.translate, values.translateAnchor, parameters.state) - : tile.matrix)), - uniforms::extrude_scale::Value(extrudeScale), - uniforms::camera_to_center_distance::Value(parameters.state.getCameraToCenterDistance())}, - *collisionBox->vertexBuffer, - *collisionBox->dynamicVertexBuffer, - *collisionBox->indexBuffer, - collisionBox->segments, - paintAttributeData, - properties, - CollisionBoxProgram::TextureBindings{}, - static_cast(parameters.state.getZoom()), - getID()); - } - if (hasCollisionCircle) { - const auto& collisionCircle = isText ? bucket.textCollisionCircle : bucket.iconCollisionCircle; - programs.collisionCircleProgram->draw( - parameters.context, - *parameters.renderPass, - gfx::Triangles(), - gfx::DepthMode::disabled(), - gfx::StencilMode::disabled(), - parameters.colorModeForRenderPass(), - gfx::CullFaceMode::disabled(), - CollisionCircleProgram::LayoutUniformValues{ - uniforms::matrix::Value( - (needTranslate - ? tile.translatedMatrix(values.translate, values.translateAnchor, parameters.state) - : tile.matrix)), - uniforms::extrude_scale::Value(extrudeScale), - uniforms::overscale_factor::Value( - static_cast(tile.getOverscaledTileID().overscaleFactor())), - uniforms::camera_to_center_distance::Value(parameters.state.getCameraToCenterDistance())}, - *collisionCircle->vertexBuffer, - *collisionCircle->dynamicVertexBuffer, - *collisionCircle->indexBuffer, - collisionCircle->segments, - paintAttributeData, - properties, - CollisionCircleProgram::TextureBindings{}, - static_cast(parameters.state.getZoom()), - getID()); - } - }; + const auto drawCollisonData = + [&](const bool isText, const bool hasCollisionBox, const bool hasCollisionCircle) { + if (!hasCollisionBox && !hasCollisionCircle) return; + + static const style::Properties<>::PossiblyEvaluated properties{}; + static const CollisionBoxProgram::Binders paintAttributeData(properties, 0); + const auto pixelRatio = tile.id.pixelsToTileUnits(1.0f, static_cast(parameters.state.getZoom())); + const auto scale = static_cast( + std::pow(2, parameters.state.getZoom() - tile.getOverscaledTileID().overscaledZ)); + std::array extrudeScale = {{parameters.pixelsToGLUnits[0] / (pixelRatio * scale), + parameters.pixelsToGLUnits[1] / (pixelRatio * scale)}}; + const auto& evaluated = getEvaluated(renderData->layerProperties); + const auto& bucketLayout = *bucket.layout; + const auto values = isText ? textPropertyValues(evaluated, bucketLayout) + : iconPropertyValues(evaluated, bucketLayout); + const bool needTranslate = values.translate[0] != 0 || values.translate[1] != 0; + + if (hasCollisionBox) { + const auto& collisionBox = isText ? bucket.textCollisionBox : bucket.iconCollisionBox; + programs.collisionBoxProgram->draw( + parameters.context, + *parameters.renderPass, + gfx::Lines{1.0f}, + gfx::DepthMode::disabled(), + gfx::StencilMode::disabled(), + parameters.colorModeForRenderPass(), + gfx::CullFaceMode::disabled(), + CollisionBoxProgram::LayoutUniformValues{ + uniforms::matrix::Value( + (needTranslate + ? tile.translatedMatrix(values.translate, values.translateAnchor, parameters.state) + : tile.matrix)), + uniforms::extrude_scale::Value(extrudeScale), + uniforms::camera_to_center_distance::Value(parameters.state.getCameraToCenterDistance())}, + *collisionBox->vertexBuffer, + *collisionBox->dynamicVertexBuffer, + *collisionBox->indexBuffer, + collisionBox->segments, + paintAttributeData, + properties, + CollisionBoxProgram::TextureBindings{}, + static_cast(parameters.state.getZoom()), + getID()); + } + if (hasCollisionCircle) { + const auto& collisionCircle = isText ? bucket.textCollisionCircle : bucket.iconCollisionCircle; + programs.collisionCircleProgram->draw( + parameters.context, + *parameters.renderPass, + gfx::Triangles(), + gfx::DepthMode::disabled(), + gfx::StencilMode::disabled(), + parameters.colorModeForRenderPass(), + gfx::CullFaceMode::disabled(), + CollisionCircleProgram::LayoutUniformValues{ + uniforms::matrix::Value( + (needTranslate + ? tile.translatedMatrix(values.translate, values.translateAnchor, parameters.state) + : tile.matrix)), + uniforms::extrude_scale::Value(extrudeScale), + uniforms::overscale_factor::Value( + static_cast(tile.getOverscaledTileID().overscaleFactor())), + uniforms::camera_to_center_distance::Value(parameters.state.getCameraToCenterDistance())}, + *collisionCircle->vertexBuffer, + *collisionCircle->dynamicVertexBuffer, + *collisionCircle->indexBuffer, + collisionCircle->segments, + paintAttributeData, + properties, + CollisionCircleProgram::TextureBindings{}, + static_cast(parameters.state.getZoom()), + getID()); + } + }; drawCollisonData(false /*isText*/, bucket.hasIconCollisionBoxData(), bucket.hasIconCollisionCircleData()); drawCollisonData(true /*isText*/, bucket.hasTextCollisionBoxData(), bucket.hasTextCollisionCircleData()); } From 3ba762242505c49a7115f1e9e7ad1c4ef5baa624 Mon Sep 17 00:00:00 2001 From: springmeyer Date: Fri, 28 Mar 2025 16:42:02 -0700 Subject: [PATCH 009/221] boolean type not correct in this case, use int - thanks Adrian Cojocaru --- include/mbgl/shaders/mtl/symbol.hpp | 2 +- include/mbgl/shaders/symbol_layer_ubo.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mbgl/shaders/mtl/symbol.hpp b/include/mbgl/shaders/mtl/symbol.hpp index ebf50ab2b42f..fd473ca115e7 100644 --- a/include/mbgl/shaders/mtl/symbol.hpp +++ b/include/mbgl/shaders/mtl/symbol.hpp @@ -39,7 +39,7 @@ struct alignas(16) SymbolDrawableUBO { /* 244 */ float opacity_t; /* 248 */ float halo_width_t; /* 252 */ float halo_blur_t; - /* 256 */ bool is_offset; + /* 256 */ /*bool*/ int is_offset; /* 260 */ }; static_assert(sizeof(SymbolDrawableUBO) == 17 * 16, "wrong size"); diff --git a/include/mbgl/shaders/symbol_layer_ubo.hpp b/include/mbgl/shaders/symbol_layer_ubo.hpp index c35b4e29b462..97a05ab4b70a 100644 --- a/include/mbgl/shaders/symbol_layer_ubo.hpp +++ b/include/mbgl/shaders/symbol_layer_ubo.hpp @@ -28,7 +28,7 @@ struct alignas(16) SymbolDrawableUBO { /* 244 */ float opacity_t; /* 248 */ float halo_width_t; /* 252 */ float halo_blur_t; - /* 256 */ bool is_offset; + /* 256 */ /*bool*/ int is_offset; /* 260 */ }; static_assert(sizeof(SymbolDrawableUBO) == 17 * 16); From cd5c7ee8091a8088ea64ac0d18bef770fc686528 Mon Sep 17 00:00:00 2001 From: springmeyer Date: Fri, 28 Mar 2025 18:31:21 -0700 Subject: [PATCH 010/221] remove debug prints --- src/mbgl/renderer/layers/render_symbol_layer.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index fde6c2317259..d2acd5ed8c41 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #if MLN_DRAWABLE_RENDERER #include @@ -1001,7 +1000,6 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, std::multiset renderableSegments; std::unique_ptr builder; const bool isOffset = !layout.get().isUndefined(); - std::clog << " isOffset " << isOffset << std::endl; const auto currentZoom = static_cast(state.getZoom()); const auto layerPrefix = getID() + "/"; From 1a4ab7ec024587035abcc76dfed73bc1b2a8365c Mon Sep 17 00:00:00 2001 From: yousifd Date: Thu, 5 Dec 2024 15:10:41 +0300 Subject: [PATCH 011/221] remove all steps that aren't necessary to actually publish --- .github/workflows/ios-ci.yml | 171 +++++++++++++++++------------------ 1 file changed, 85 insertions(+), 86 deletions(-) diff --git a/.github/workflows/ios-ci.yml b/.github/workflows/ios-ci.yml index e251c68824fa..4548b92166b3 100644 --- a/.github/workflows/ios-ci.yml +++ b/.github/workflows/ios-ci.yml @@ -83,8 +83,8 @@ jobs: ${{ runner.os }}-bazel- path: ~/.cache/bazel - - name: Build Example (Swift) App - run: bazel build //platform/ios/app-swift:MapLibreApp --//:renderer=metal + # - name: Build Example (Swift) App + # run: bazel build //platform/ios/app-swift:MapLibreApp --//:renderer=metal - name: Check debug symbols run: bazel run //platform:check-public-symbols --//:renderer=metal @@ -99,62 +99,62 @@ jobs: #- name: Running iOS UI tests (Thread Sanitizer) # run: bazel test //platform/ios/iosapp-UITests:uitest --test_output=errors --//:renderer=metal --features=tsan - - name: Running iOS UI tests (Address+UB Sanitizer) - run: bazel test //platform/ios/iosapp-UITests:uitest --test_output=errors --//:renderer=metal --features=include_clang_rt --copt=-fsanitize=undefined --linkopt=-fsanitize=undefined --copt=-fsanitize-recover=null --linkopt=-fsanitize-recover=null + # - name: Running iOS UI tests (Address+UB Sanitizer) + # run: bazel test //platform/ios/iosapp-UITests:uitest --test_output=errors --//:renderer=metal --features=include_clang_rt --copt=-fsanitize=undefined --linkopt=-fsanitize=undefined --copt=-fsanitize-recover=null --linkopt=-fsanitize-recover=null # render test - - name: Build RenderTest .ipa and .xctest for AWS Device Farm - run: | - set -e - bazel run //platform/ios:xcodeproj --@rules_xcodeproj//xcodeproj:extra_common_flags="--//:renderer=metal" - build_dir="$(mktemp -d)" - xcodebuild build-for-testing -scheme RenderTest -project MapLibre.xcodeproj -derivedDataPath "$build_dir" - render_test_app_dir="$(dirname "$(find "$build_dir" -name RenderTestApp.app)")" - cd "$render_test_app_dir" - mkdir Payload - mv RenderTestApp.app Payload - zip -r RenderTestApp.zip Payload - mv RenderTestApp.zip RenderTestApp.ipa - cd Payload/RenderTestApp.app/PlugIns - zip -r "$render_test_app_dir"/RenderTest.xctest.zip RenderTest.xctest - echo render_test_artifacts_dir="$render_test_app_dir" >> "$GITHUB_ENV" - - - uses: actions/upload-artifact@v4 - with: - name: ios-render-test - retention-days: 3 - if-no-files-found: error - path: | - ${{ env.render_test_artifacts_dir }}/RenderTest.xctest.zip - ${{ env.render_test_artifacts_dir }}/RenderTestApp.ipa + # - name: Build RenderTest .ipa and .xctest for AWS Device Farm + # run: | + # set -e + # bazel run //platform/ios:xcodeproj --@rules_xcodeproj//xcodeproj:extra_common_flags="--//:renderer=metal" + # build_dir="$(mktemp -d)" + # xcodebuild build-for-testing -scheme RenderTest -project MapLibre.xcodeproj -derivedDataPath "$build_dir" + # render_test_app_dir="$(dirname "$(find "$build_dir" -name RenderTestApp.app)")" + # cd "$render_test_app_dir" + # mkdir Payload + # mv RenderTestApp.app Payload + # zip -r RenderTestApp.zip Payload + # mv RenderTestApp.zip RenderTestApp.ipa + # cd Payload/RenderTestApp.app/PlugIns + # zip -r "$render_test_app_dir"/RenderTest.xctest.zip RenderTest.xctest + # echo render_test_artifacts_dir="$render_test_app_dir" >> "$GITHUB_ENV" + + # - uses: actions/upload-artifact@v4 + # with: + # name: ios-render-test + # retention-days: 3 + # if-no-files-found: error + # path: | + # ${{ env.render_test_artifacts_dir }}/RenderTest.xctest.zip + # ${{ env.render_test_artifacts_dir }}/RenderTestApp.ipa # C++ unit tests - - name: Build CppUnitTests .ipa and .xctest for AWS Device Farm - run: | - set -e - bazel run //platform/ios:xcodeproj --@rules_xcodeproj//xcodeproj:extra_common_flags="--//:renderer=metal" - build_dir="$(mktemp -d)" - xcodebuild build-for-testing -scheme CppUnitTests -project MapLibre.xcodeproj -derivedDataPath "$build_dir" - ios_cpp_test_app_dir="$(dirname "$(find "$build_dir" -name CppUnitTestsApp.app)")" - cd "$ios_cpp_test_app_dir" - mkdir Payload - mv CppUnitTestsApp.app Payload - zip -r CppUnitTestsApp.zip Payload - mv CppUnitTestsApp.zip CppUnitTestsApp.ipa - cd Payload/CppUnitTestsApp.app/PlugIns - zip -r "$ios_cpp_test_app_dir"/CppUnitTests.xctest.zip CppUnitTests.xctest - echo ios_cpp_test_artifacts_dir="$ios_cpp_test_app_dir" >> "$GITHUB_ENV" - - - uses: actions/upload-artifact@v4 - with: - name: ios-cpp-unit-tests - retention-days: 3 - if-no-files-found: error - path: | - ${{ env.ios_cpp_test_artifacts_dir }}/CppUnitTests.xctest.zip - ${{ env.ios_cpp_test_artifacts_dir }}/CppUnitTestsApp.ipa + # - name: Build CppUnitTests .ipa and .xctest for AWS Device Farm + # run: | + # set -e + # bazel run //platform/ios:xcodeproj --@rules_xcodeproj//xcodeproj:extra_common_flags="--//:renderer=metal" + # build_dir="$(mktemp -d)" + # xcodebuild build-for-testing -scheme CppUnitTests -project MapLibre.xcodeproj -derivedDataPath "$build_dir" + # ios_cpp_test_app_dir="$(dirname "$(find "$build_dir" -name CppUnitTestsApp.app)")" + # cd "$ios_cpp_test_app_dir" + # mkdir Payload + # mv CppUnitTestsApp.app Payload + # zip -r CppUnitTestsApp.zip Payload + # mv CppUnitTestsApp.zip CppUnitTestsApp.ipa + # cd Payload/CppUnitTestsApp.app/PlugIns + # zip -r "$ios_cpp_test_app_dir"/CppUnitTests.xctest.zip CppUnitTests.xctest + # echo ios_cpp_test_artifacts_dir="$ios_cpp_test_app_dir" >> "$GITHUB_ENV" + + # - uses: actions/upload-artifact@v4 + # with: + # name: ios-cpp-unit-tests + # retention-days: 3 + # if-no-files-found: error + # path: | + # ${{ env.ios_cpp_test_artifacts_dir }}/CppUnitTests.xctest.zip + # ${{ env.ios_cpp_test_artifacts_dir }}/CppUnitTestsApp.ipa # Size test (Bloaty) @@ -177,19 +177,19 @@ jobs: platform/ios/MapLibre_DWARF platform/ios/MapLibre_dynamic - - name: Configure AWS Credentials - if: github.ref == 'refs/heads/main' && vars.OIDC_AWS_ROLE_TO_ASSUME - uses: aws-actions/configure-aws-credentials@v4 - with: - aws-region: us-west-2 - role-to-assume: ${{ vars.OIDC_AWS_ROLE_TO_ASSUME }} - role-session-name: ${{ github.run_id }} + # - name: Configure AWS Credentials + # if: github.ref == 'refs/heads/main' && vars.OIDC_AWS_ROLE_TO_ASSUME + # uses: aws-actions/configure-aws-credentials@v4 + # with: + # aws-region: us-west-2 + # role-to-assume: ${{ vars.OIDC_AWS_ROLE_TO_ASSUME }} + # role-session-name: ${{ github.run_id }} - - name: Upload MapLibre_DWARF & MapLibre_dynamic to S3 - if: github.ref == 'refs/heads/main' && vars.OIDC_AWS_ROLE_TO_ASSUME - run: | - aws s3 cp MapLibre_DWARF s3://maplibre-native/size-test-ios/MapLibre_DWARF-main - aws s3 cp MapLibre_dynamic s3://maplibre-native/size-test-ios/MapLibre_dynamic-main + # - name: Upload MapLibre_DWARF & MapLibre_dynamic to S3 + # if: github.ref == 'refs/heads/main' && vars.OIDC_AWS_ROLE_TO_ASSUME + # run: | + # aws s3 cp MapLibre_DWARF s3://maplibre-native/size-test-ios/MapLibre_DWARF-main + # aws s3 cp MapLibre_dynamic s3://maplibre-native/size-test-ios/MapLibre_dynamic-main - if: github.event_name == 'pull_request' uses: ./.github/actions/save-pr-number @@ -262,16 +262,16 @@ jobs: awk '/^##/ { p = 0 }; p == 1 { print }; $0 == "${{ env.changelog_version_heading }}" { p = 1 };' CHANGELOG.md > changelog_for_version.md cat changelog_for_version.md - - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v4 - with: - aws-region: us-west-2 - role-to-assume: ${{ vars.OIDC_AWS_ROLE_TO_ASSUME }} - role-session-name: ${{ github.run_id }} + # - name: Configure AWS Credentials + # uses: aws-actions/configure-aws-credentials@v4 + # with: + # aws-region: us-west-2 + # role-to-assume: ${{ vars.OIDC_AWS_ROLE_TO_ASSUME }} + # role-session-name: ${{ github.run_id }} - - name: Upload changelog to S3 - if: env.make_release - run: aws s3 cp changelog_for_version.md s3://maplibre-native/changelogs/ios-${{ env.version }}.md + # - name: Upload changelog to S3 + # if: env.make_release + # run: aws s3 cp changelog_for_version.md s3://maplibre-native/changelogs/ios-${{ env.version }}.md - name: Create tag if: env.make_release @@ -295,20 +295,19 @@ jobs: name: ios-v${{ env.version }} files: | MapLibre.dynamic.xcframework.zip - ${{ env.debug_symbols_ios }} tag_name: ios-v${{ env.version }} prerelease: ${{ github.event.inputs.release == 'pre' }} body_path: platform/ios/changelog_for_version.md fail_on_unmatched_files: true # needed to trigger workflow for Swift Package Index release - - name: Generate token - if: env.make_release - id: generate_token - uses: tibdex/github-app-token@v2 - with: - app_id: ${{ secrets.MAPLIBRE_NATIVE_BOT_APP_ID }} - private_key: ${{ secrets.MAPLIBRE_NATIVE_BOT_PRIVATE_KEY }} + # - name: Generate token + # if: env.make_release + # id: generate_token + # uses: tibdex/github-app-token@v2 + # with: + # app_id: ${{ secrets.MAPLIBRE_NATIVE_BOT_APP_ID }} + # private_key: ${{ secrets.MAPLIBRE_NATIVE_BOT_PRIVATE_KEY }} - name: Release (Swift Package Index) if: env.make_release @@ -326,11 +325,11 @@ jobs: "version":"${{ env.version }}", "download_url":"${{ fromJSON(steps.github_release.outputs.assets)[0].browser_download_url }}"}}' - - name: Release (CocoaPods) - shell: bash -leo pipefail {0} # so pod is found - if: env.make_release - run: | - VERSION=${{ env.version }} COCOAPODS_TRUNK_TOKEN=${{ secrets.COCOAPODS_PASSWORD }} pod trunk push MapLibre.podspec + # - name: Release (CocoaPods) + # shell: bash -leo pipefail {0} # so pod is found + # if: env.make_release + # run: | + # VERSION=${{ env.version }} COCOAPODS_TRUNK_TOKEN=${{ secrets.COCOAPODS_PASSWORD }} pod trunk push MapLibre.podspec ios-build-cmake: needs: pre_job From a9dd19a11f797c50e6f93e6c134fb52475ef3685 Mon Sep 17 00:00:00 2001 From: yousifd Date: Thu, 5 Dec 2024 15:16:14 +0300 Subject: [PATCH 012/221] use macos-latest to build ios package instead of self-hosted --- .github/workflows/ios-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ios-ci.yml b/.github/workflows/ios-ci.yml index 4548b92166b3..6d259dc1febc 100644 --- a/.github/workflows/ios-ci.yml +++ b/.github/workflows/ios-ci.yml @@ -56,7 +56,7 @@ jobs: ios-build: needs: pre_job if: needs.pre_job.outputs.should_skip != 'true' - runs-on: [self-hosted, macOS, ARM64] + runs-on: [macos-latest] concurrency: # cancel jobs on PRs only group: ${{ github.workflow }}-${{ github.ref }} @@ -200,7 +200,7 @@ jobs: HOSTING_BASE_PATH="maplibre-native/ios/latest" platform/ios/scripts/docc.sh ios-release: - runs-on: macos-14 + runs-on: macos-latest needs: ios-build if: github.ref == 'refs/heads/main' || github.event.inputs.release == 'pre' defaults: From 299ff2d46b677868b1a68209477c05375c320630 Mon Sep 17 00:00:00 2001 From: yousifd Date: Thu, 5 Dec 2024 15:16:42 +0300 Subject: [PATCH 013/221] publish to hudhud maplibre swift package repo instead of original --- .github/workflows/ios-ci.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ios-ci.yml b/.github/workflows/ios-ci.yml index 6d259dc1febc..a2230f049c40 100644 --- a/.github/workflows/ios-ci.yml +++ b/.github/workflows/ios-ci.yml @@ -312,16 +312,15 @@ jobs: - name: Release (Swift Package Index) if: env.make_release run: | - echo "::add-mask::${{ steps.generate_token.outputs.token }}" - release_workflow_id=81221759 # id of release.yml + echo "::add-mask::${{ secrets.MAPLIBRE_NATIVE_PRIVATE_TOKEN }}" + release_workflow_name=release.yml # github api allows you to pass workflow name instead of id curl -L \ -X POST \ -H "Accept: application/vnd.github+json" \ - -H "Authorization: token ${{ steps.generate_token.outputs.token }}" \ + -H "Authorization: token ${{ secrets.MAPLIBRE_NATIVE_PRIVATE_TOKEN }}" \ -H "X-GitHub-Api-Version: 2022-11-28" \ - https://api.github.com/repos/maplibre/maplibre-gl-native-distribution/actions/workflows/$release_workflow_id/dispatches \ + https://api.github.com/repos/hudhud-maps/maplibre-gl-native-distribution/actions/workflows/$release_workflow_name/dispatches \ -d '{"ref":"main","inputs":{ - "changelog_url": "https://maplibre-native.s3.eu-central-1.amazonaws.com/changelogs/ios-${{ env.version }}.md", "version":"${{ env.version }}", "download_url":"${{ fromJSON(steps.github_release.outputs.assets)[0].browser_download_url }}"}}' From e9f728604d0e6280a12f1228bf33dfceaa7e5ebe Mon Sep 17 00:00:00 2001 From: Yousif Date: Wed, 18 Dec 2024 17:26:29 +0300 Subject: [PATCH 014/221] disable ios tests and bloaty --- .github/workflows/ios-ci.yml | 40 ++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/ios-ci.yml b/.github/workflows/ios-ci.yml index a2230f049c40..374054c8b993 100644 --- a/.github/workflows/ios-ci.yml +++ b/.github/workflows/ios-ci.yml @@ -92,8 +92,8 @@ jobs: - name: Lint plist files run: bazel run //platform/ios:lint-plists --//:renderer=metal - - name: Running iOS tests - run: bazel test //platform/ios/test:ios_test --test_output=errors --//:renderer=metal + # - name: Running iOS tests + # run: bazel test //platform/ios/test:ios_test --test_output=errors --//:renderer=metal # tsan run fails with 'Interceptors are not working. This may be because ThreadSanitizer is loaded too late...' #- name: Running iOS UI tests (Thread Sanitizer) @@ -158,24 +158,24 @@ jobs: # Size test (Bloaty) - - name: Build dynamic library for size test (Bloaty) - run: | - bazel build //platform/ios:MapLibre.dynamic --//:renderer=metal --compilation_mode="opt" --copt -g --copt="-Oz" --strip never --output_groups=+dsyms --apple_generate_dsym - bazel_bin="$(bazel info --compilation_mode="opt" bazel-bin)" - unzip "$bazel_bin"/platform/ios/MapLibre.dynamic.xcframework.zip - cp "$bazel_bin"/platform/ios/MapLibre.dynamic_dsyms/MapLibre_ios_device.framework.dSYM/Contents/Resources/DWARF/MapLibre_ios_device MapLibre_DWARF - cp MapLibre.xcframework/ios-arm64/MapLibre.framework/MapLibre MapLibre_dynamic - - - name: Upload size test as artifact (Bloaty) - if: github.event_name == 'pull_request' - uses: actions/upload-artifact@v4 - with: - name: ios-size-test-files - retention-days: 3 - if-no-files-found: error - path: | - platform/ios/MapLibre_DWARF - platform/ios/MapLibre_dynamic + # - name: Build dynamic library for size test (Bloaty) + # run: | + # bazel build //platform/ios:MapLibre.dynamic --//:renderer=metal --compilation_mode="opt" --copt -g --copt="-Oz" --strip never --output_groups=+dsyms --apple_generate_dsym + # bazel_bin="$(bazel info --compilation_mode="opt" bazel-bin)" + # unzip "$bazel_bin"/platform/ios/MapLibre.dynamic.xcframework.zip + # cp "$bazel_bin"/platform/ios/MapLibre.dynamic_dsyms/MapLibre_ios_device.framework.dSYM/Contents/Resources/DWARF/MapLibre_ios_device MapLibre_DWARF + # cp MapLibre.xcframework/ios-arm64/MapLibre.framework/MapLibre MapLibre_dynamic + + # - name: Upload size test as artifact (Bloaty) + # if: github.event_name == 'pull_request' + # uses: actions/upload-artifact@v4 + # with: + # name: ios-size-test-files + # retention-days: 3 + # if-no-files-found: error + # path: | + # platform/ios/MapLibre_DWARF + # platform/ios/MapLibre_dynamic # - name: Configure AWS Credentials # if: github.ref == 'refs/heads/main' && vars.OIDC_AWS_ROLE_TO_ASSUME From 474dc313868685a03f9aff93f164f6425a4d8feb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Wed, 11 Dec 2024 15:03:35 -0500 Subject: [PATCH 015/221] Initial build completed --- platform/BUILD.bazel | 4 + platform/darwin/BUILD.bazel | 18 + platform/darwin/bazel/files.bzl | 83 ++ platform/darwin/src/gltf/Camera.cpp | 62 + platform/darwin/src/gltf/Camera.hpp | 32 + platform/darwin/src/gltf/GLTFMTLRenderItem.h | 23 + platform/darwin/src/gltf/GLTFMTLRenderItem.m | 12 + platform/darwin/src/gltf/GLTFManager.hpp | 107 ++ platform/darwin/src/gltf/GLTFManager.mm | 170 +++ .../gltf/GLTFManagerRenderingEnvironment.hpp | 31 + .../gltf/GLTFManagerRenderingEnvironment.mm | 8 + .../GLTFManagerRenderingEnvironmentMetal.hpp | 40 + .../GLTFManagerRenderingEnvironmentMetal.mm | 8 + platform/darwin/src/gltf/GLTFMath.cpp | 151 ++ platform/darwin/src/gltf/GLTFMath.hpp | 121 ++ platform/darwin/src/gltf/GLTFModel.cpp | 8 + platform/darwin/src/gltf/GLTFModel.hpp | 43 + platform/darwin/src/gltf/GLTFModelLayer.h | 21 + platform/darwin/src/gltf/GLTFModelLayer.mm | 418 ++++++ platform/darwin/src/gltf/GLTFModelLoader.h | 24 + platform/darwin/src/gltf/GLTFModelLoader.m | 74 + platform/darwin/src/gltf/GLTFRenderer.cpp | 82 ++ platform/darwin/src/gltf/GLTFRenderer.hpp | 69 + .../src/gltf/MetalRenderer+GLTFAsset.mm | 602 ++++++++ platform/darwin/src/gltf/MetalRenderer.hpp | 229 +++ platform/darwin/src/gltf/MetalRenderer.mm | 565 ++++++++ .../darwin/src/gltf/gltfkit/GLTFAccessor.h | 40 + .../darwin/src/gltf/gltfkit/GLTFAccessor.m | 26 + .../darwin/src/gltf/gltfkit/GLTFAnimation.h | 46 + .../darwin/src/gltf/gltfkit/GLTFAnimation.m | 172 +++ platform/darwin/src/gltf/gltfkit/GLTFAsset.h | 66 + platform/darwin/src/gltf/gltfkit/GLTFAsset.m | 1273 +++++++++++++++++ .../darwin/src/gltf/gltfkit/GLTFBinaryChunk.h | 35 + .../darwin/src/gltf/gltfkit/GLTFBinaryChunk.m | 23 + platform/darwin/src/gltf/gltfkit/GLTFBuffer.h | 30 + .../src/gltf/gltfkit/GLTFBufferAllocator.h | 29 + .../darwin/src/gltf/gltfkit/GLTFBufferView.h | 32 + .../darwin/src/gltf/gltfkit/GLTFBufferView.m | 26 + platform/darwin/src/gltf/gltfkit/GLTFCamera.h | 42 + platform/darwin/src/gltf/gltfkit/GLTFCamera.m | 115 ++ .../gltf/gltfkit/GLTFDefaultBufferAllocator.h | 27 + .../gltf/gltfkit/GLTFDefaultBufferAllocator.m | 93 ++ platform/darwin/src/gltf/gltfkit/GLTFEnums.h | 178 +++ .../src/gltf/gltfkit/GLTFExtensionNames.h | 23 + .../src/gltf/gltfkit/GLTFExtensionNames.m | 23 + platform/darwin/src/gltf/gltfkit/GLTFImage.h | 40 + platform/darwin/src/gltf/gltfkit/GLTFImage.m | 57 + .../darwin/src/gltf/gltfkit/GLTFKHRLight.h | 53 + .../darwin/src/gltf/gltfkit/GLTFKHRLight.m | 33 + .../src/gltf/gltfkit/GLTFMTLBufferAllocator.h | 36 + .../src/gltf/gltfkit/GLTFMTLBufferAllocator.m | 101 ++ .../src/gltf/gltfkit/GLTFMTLShaderBuilder.h | 39 + .../src/gltf/gltfkit/GLTFMTLShaderBuilder.m | 246 ++++ .../src/gltf/gltfkit/GLTFMTLTextureLoader.h | 32 + .../src/gltf/gltfkit/GLTFMTLTextureLoader.m | 244 ++++ .../src/gltf/gltfkit/GLTFMTLUtilities.h | 55 + .../src/gltf/gltfkit/GLTFMTLUtilities.m | 290 ++++ .../darwin/src/gltf/gltfkit/GLTFMaterial.h | 61 + .../darwin/src/gltf/gltfkit/GLTFMaterial.m | 35 + platform/darwin/src/gltf/gltfkit/GLTFMesh.h | 43 + platform/darwin/src/gltf/gltfkit/GLTFMesh.m | 69 + platform/darwin/src/gltf/gltfkit/GLTFNode.h | 49 + platform/darwin/src/gltf/gltfkit/GLTFNode.m | 171 +++ .../darwin/src/gltf/gltfkit/GLTFNodeVisitor.h | 33 + platform/darwin/src/gltf/gltfkit/GLTFObject.h | 45 + platform/darwin/src/gltf/gltfkit/GLTFObject.m | 32 + platform/darwin/src/gltf/gltfkit/GLTFScene.h | 35 + platform/darwin/src/gltf/gltfkit/GLTFScene.m | 57 + platform/darwin/src/gltf/gltfkit/GLTFSkin.h | 30 + platform/darwin/src/gltf/gltfkit/GLTFSkin.m | 20 + .../darwin/src/gltf/gltfkit/GLTFTexture.h | 66 + .../darwin/src/gltf/gltfkit/GLTFTexture.mm | 44 + .../src/gltf/gltfkit/GLTFTextureSampler.h | 34 + .../src/gltf/gltfkit/GLTFTextureSampler.m | 60 + .../darwin/src/gltf/gltfkit/GLTFUtilities.h | 79 + .../darwin/src/gltf/gltfkit/GLTFUtilities.m | 261 ++++ .../src/gltf/gltfkit/GLTFVertexDescriptor.h | 54 + .../src/gltf/gltfkit/GLTFVertexDescriptor.m | 71 + .../src/gltf/gltfkit/shaders/brdf.metal | 230 +++ .../darwin/src/gltf/gltfkit/shaders/hdr.metal | 123 ++ .../darwin/src/gltf/gltfkit/shaders/pbr.metal | 463 ++++++ .../darwin/src/gltf/gltfkit/shaders/pbr.txt | 463 ++++++ 82 files changed, 9158 insertions(+) create mode 100644 platform/darwin/src/gltf/Camera.cpp create mode 100644 platform/darwin/src/gltf/Camera.hpp create mode 100644 platform/darwin/src/gltf/GLTFMTLRenderItem.h create mode 100644 platform/darwin/src/gltf/GLTFMTLRenderItem.m create mode 100644 platform/darwin/src/gltf/GLTFManager.hpp create mode 100644 platform/darwin/src/gltf/GLTFManager.mm create mode 100644 platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp create mode 100644 platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.mm create mode 100644 platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp create mode 100644 platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.mm create mode 100644 platform/darwin/src/gltf/GLTFMath.cpp create mode 100644 platform/darwin/src/gltf/GLTFMath.hpp create mode 100644 platform/darwin/src/gltf/GLTFModel.cpp create mode 100644 platform/darwin/src/gltf/GLTFModel.hpp create mode 100644 platform/darwin/src/gltf/GLTFModelLayer.h create mode 100644 platform/darwin/src/gltf/GLTFModelLayer.mm create mode 100644 platform/darwin/src/gltf/GLTFModelLoader.h create mode 100644 platform/darwin/src/gltf/GLTFModelLoader.m create mode 100644 platform/darwin/src/gltf/GLTFRenderer.cpp create mode 100644 platform/darwin/src/gltf/GLTFRenderer.hpp create mode 100644 platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm create mode 100644 platform/darwin/src/gltf/MetalRenderer.hpp create mode 100644 platform/darwin/src/gltf/MetalRenderer.mm create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFAccessor.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFAccessor.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFAnimation.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFAnimation.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFAsset.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFAsset.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFBuffer.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFBufferAllocator.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFBufferView.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFBufferView.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFCamera.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFCamera.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFEnums.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFImage.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFImage.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFKHRLight.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFKHRLight.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMaterial.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMaterial.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMesh.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMesh.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFNode.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFNode.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFNodeVisitor.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFObject.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFObject.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFScene.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFScene.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFSkin.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFSkin.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFTexture.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFTexture.mm create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFUtilities.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFUtilities.m create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.h create mode 100644 platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.m create mode 100644 platform/darwin/src/gltf/gltfkit/shaders/brdf.metal create mode 100644 platform/darwin/src/gltf/gltfkit/shaders/hdr.metal create mode 100644 platform/darwin/src/gltf/gltfkit/shaders/pbr.metal create mode 100644 platform/darwin/src/gltf/gltfkit/shaders/pbr.txt diff --git a/platform/BUILD.bazel b/platform/BUILD.bazel index c400cd44e80d..c0225d4f0c7f 100644 --- a/platform/BUILD.bazel +++ b/platform/BUILD.bazel @@ -50,6 +50,8 @@ objc_library( objc_library( name = "macos-objc", srcs = [ + "//platform/darwin:darwin_gltf_hdrs", + "//platform/darwin:darwin_gltf_srcs", "//platform/darwin:darwin_objc_hdrs", "//platform/darwin:darwin_objc_srcs", "//platform/darwin:darwin_private_hdrs", @@ -135,6 +137,7 @@ objc_library( objc_library( name = "objc-sdk", srcs = [ + "//platform/darwin:darwin_gltf_srcs", "//platform/darwin:darwin_objc_srcs", "//platform/ios:ios_objc_srcs", "//platform/ios:ios_private_hdrs", @@ -161,6 +164,7 @@ objc_library( "CoreGraphics", "CoreLocation", "QuartzCore", + "Accelerate", ], deps = [ ":objc-headers", diff --git a/platform/darwin/BUILD.bazel b/platform/darwin/BUILD.bazel index 540614772e7e..dffa8398f425 100644 --- a/platform/darwin/BUILD.bazel +++ b/platform/darwin/BUILD.bazel @@ -6,6 +6,8 @@ load( load("//bazel:flags.bzl", "CPP_FLAGS", "MAPLIBRE_FLAGS", "WARNING_FLAGS") load( "bazel/files.bzl", + "MLN_GLTF_HEADERS", + "MLN_GLTF_SOURCE", "MLN_DARWIN_OBJCPP_HEADERS", "MLN_DARWIN_OBJC_HEADERS", "MLN_DARWIN_PRIVATE_HEADERS", @@ -42,6 +44,18 @@ filegroup( visibility = ["//visibility:public"], ) +filegroup( + name = "darwin_gltf_hdrs", + srcs = MLN_GLTF_HEADERS, + visibility = ["//visibility:public"], +) + +filegroup( + name = "darwin_gltf_srcs", + srcs = MLN_GLTF_SOURCE, + visibility = ["//visibility:public"], +) + filegroup( name = "darwin_objcpp_custom_drawable_srcs", srcs = MLN_DARWIN_PUBLIC_OBJCPP_CUSTOM_DRAWABLE_SOURCE, @@ -305,6 +319,8 @@ exports_files( "include/mbgl/util/image+MLNAdditions.hpp", ] + MLN_DARWIN_PUBLIC_OBJC_SOURCE + MLN_DARWIN_PUBLIC_OBJCPP_SOURCE + + MLN_GLTF_HEADERS + + MLN_GLTF_SOURCE + MLN_DARWIN_PUBLIC_OBJCPP_CUSTOM_DRAWABLE_SOURCE + MLN_DARWIN_PRIVATE_HEADERS + MLN_DARWIN_OBJC_HEADERS + @@ -330,6 +346,8 @@ js_library( srcs = [ ":darwin_objc_hdrs", ":darwin_objc_srcs", + ":darwin_gltf_hdrs", + ":darwin_gltf_srcs", ":darwin_objcpp_hdrs", ":darwin_objcpp_srcs", ":darwin_private_hdrs", diff --git a/platform/darwin/bazel/files.bzl b/platform/darwin/bazel/files.bzl index facd90f72a8e..fde648a6c853 100644 --- a/platform/darwin/bazel/files.bzl +++ b/platform/darwin/bazel/files.bzl @@ -1,3 +1,86 @@ +MLN_GLTF_HEADERS = [ +] + +MLN_GLTF_SOURCE = [ + "src/gltf/Camera.hpp", + "src/gltf/Camera.cpp", + "src/gltf/GLTFMath.cpp", + "src/gltf/GLTFMath.hpp", + "src/gltf/GLTFManager.hpp", + "src/gltf/GLTFManager.mm", + "src/gltf/GLTFManagerRenderingEnvironment.hpp", + "src/gltf/GLTFManagerRenderingEnvironment.mm", + "src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp", + "src/gltf/GLTFManagerRenderingEnvironmentMetal.mm", + "src/gltf/GLTFModel.hpp", + "src/gltf/GLTFModel.cpp", + "src/gltf/MetalRenderer.hpp", + "src/gltf/MetalRenderer.mm", + "src/gltf/GLTFModelLayer.h", + "src/gltf/GLTFModelLayer.mm", + "src/gltf/GLTFModelLoader.h", + "src/gltf/GLTFModelLoader.m", + "src/gltf/GLTFMTLRenderItem.h", + "src/gltf/GLTFMTLRenderItem.m", + "src/gltf/GLTFRenderer.hpp", + "src/gltf/GLTFRenderer.cpp", + "src/gltf/MetalRenderer+GLTFAsset.mm", + "src/gltf/gltfkit/GLTFAsset.h", + "src/gltf/gltfkit/GLTFAsset.m", + "src/gltf/gltfkit/GLTFAccessor.h", + "src/gltf/gltfkit/GLTFAccessor.m", + "src/gltf/gltfkit/GLTFAnimation.h", + "src/gltf/gltfkit/GLTFAnimation.m", + "src/gltf/gltfkit/GLTFBinaryChunk.h", + "src/gltf/gltfkit/GLTFBinaryChunk.m", + "src/gltf/gltfkit/GLTFBuffer.h", + "src/gltf/gltfkit/GLTFBufferAllocator.h", + "src/gltf/gltfkit/GLTFBufferView.h", + "src/gltf/gltfkit/GLTFBufferView.m", + "src/gltf/gltfkit/GLTFCamera.h", + "src/gltf/gltfkit/GLTFCamera.m", + "src/gltf/gltfkit/GLTFDefaultBufferAllocator.h", + "src/gltf/gltfkit/GLTFDefaultBufferAllocator.m", + "src/gltf/gltfkit/GLTFEnums.h", + "src/gltf/gltfkit/GLTFExtensionNames.h", + "src/gltf/gltfkit/GLTFExtensionNames.m", + "src/gltf/gltfkit/GLTFImage.h", + "src/gltf/gltfkit/GLTFImage.m", + "src/gltf/gltfkit/GLTFKHRLight.h", + "src/gltf/gltfkit/GLTFKHRLight.m", + "src/gltf/gltfkit/GLTFMaterial.h", + "src/gltf/gltfkit/GLTFMaterial.m", + "src/gltf/gltfkit/GLTFMesh.h", + "src/gltf/gltfkit/GLTFMesh.m", + "src/gltf/gltfkit/GLTFMTLBufferAllocator.h", + "src/gltf/gltfkit/GLTFMTLBufferAllocator.m", + "src/gltf/gltfkit/GLTFMTLShaderBuilder.h", + "src/gltf/gltfkit/GLTFMTLShaderBuilder.m", + "src/gltf/gltfkit/GLTFMTLTextureLoader.h", + "src/gltf/gltfkit/GLTFMTLTextureLoader.m", + "src/gltf/gltfkit/GLTFMTLUtilities.h", + "src/gltf/gltfkit/GLTFMTLUtilities.m", + "src/gltf/gltfkit/GLTFNode.h", + "src/gltf/gltfkit/GLTFNode.m", + "src/gltf/gltfkit/GLTFNodeVisitor.h", + "src/gltf/gltfkit/GLTFObject.h", + "src/gltf/gltfkit/GLTFObject.m", + "src/gltf/gltfkit/GLTFScene.h", + "src/gltf/gltfkit/GLTFScene.m", + "src/gltf/gltfkit/GLTFSkin.h", + "src/gltf/gltfkit/GLTFSkin.m", + "src/gltf/gltfkit/GLTFTexture.h", + "src/gltf/gltfkit/GLTFTexture.mm", + "src/gltf/gltfkit/GLTFTextureSampler.h", + "src/gltf/gltfkit/GLTFTextureSampler.m", + "src/gltf/gltfkit/GLTFUtilities.h", + "src/gltf/gltfkit/GLTFUtilities.m", + "src/gltf/gltfkit/GLTFVertexDescriptor.h", + "src/gltf/gltfkit/GLTFVertexDescriptor.m", + +] + + MLN_GENERATED_DARWIN_STYLE_SOURCE = [ "src/MLNLight.mm", "src/MLNBackgroundStyleLayer.mm", diff --git a/platform/darwin/src/gltf/Camera.cpp b/platform/darwin/src/gltf/Camera.cpp new file mode 100644 index 000000000000..e7b639152be5 --- /dev/null +++ b/platform/darwin/src/gltf/Camera.cpp @@ -0,0 +1,62 @@ +// +// Camera.cpp +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/19/24. +// + +#include "Camera.hpp" +#include "GLTFMath.hpp" + +const float GLTFViewerOrbitCameraDefaultDistance = 2; +const float GLTFViewerOrbitCameraZoomDrag = 0.95; +const float GLTFViewerOrbitCameraRotationDrag = 0.6667; +const float GLTFViewerOrbitCameraZoomSensitivity = 2; + +using namespace maplibre::gltf; + +Camera::Camera() { + _rotationAngles = 0; + _rotationVelocity = 0; + _velocity = 0; + _distance = 4; // 0; // 2; + +} + +simd_float4x4 Camera::projectionMatrix() { + float fov = M_PI / 3; // original + fov = 0.6435011087932844; // Constant that i found in ML + simd_float4x4 matrix = GLTFPerspectiveProjectionMatrixAspectFovRH(fov, 1.0, 0.01, 250); + return matrix; +} + +void Camera::updateWithTimestep(double timestep) { + + + _rotationAngles += _rotationVelocity * timestep; + + static double rot = 0; + // rot += 0.03; +// self.rotationAngles = rot; +// _rotationAngles = simd_make_float3(rot, M_PI/4.0, 0); + _rotationAngles = simd_make_float3(rot, 0, 0); + + + // Clamp pitch + _rotationAngles = (simd_float3){ _rotationAngles.x, + static_cast(fmax(-M_PI_2, fmin(_rotationAngles.y, M_PI_2))), + 0 }; + + + _rotationVelocity *= GLTFViewerOrbitCameraRotationDrag; + + // _distance += _velocity * timestep; + _velocity *= GLTFViewerOrbitCameraZoomDrag; + + simd_float4x4 pitchRotation = GLTFRotationMatrixFromAxisAngle(GLTFAxisX, -_rotationAngles.y); + simd_float4x4 yawRotation = GLTFRotationMatrixFromAxisAngle(GLTFAxisY, -_rotationAngles.x); + simd_float4x4 translation = GLTFMatrixFromTranslation((simd_float3){ 0, 0, _distance }); + _viewMatrix = matrix_invert(matrix_multiply(matrix_multiply(yawRotation, pitchRotation), translation)); + + +} diff --git a/platform/darwin/src/gltf/Camera.hpp b/platform/darwin/src/gltf/Camera.hpp new file mode 100644 index 000000000000..e364d1cee6da --- /dev/null +++ b/platform/darwin/src/gltf/Camera.hpp @@ -0,0 +1,32 @@ +// +// Camera.hpp +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/19/24. +// + +#ifndef Camera_hpp +#define Camera_hpp + +#include +#include + +namespace maplibre { namespace gltf { + +class Camera { +public: + simd_float3 _rotationAngles; + simd_float3 _rotationVelocity; + double _velocity; + float _distance; + Camera(); + simd_float4x4 projectionMatrix(); + simd_float4x4 _viewMatrix; + void updateWithTimestep(double timestep); + +}; + +}} + + +#endif /* Camera_hpp */ diff --git a/platform/darwin/src/gltf/GLTFMTLRenderItem.h b/platform/darwin/src/gltf/GLTFMTLRenderItem.h new file mode 100644 index 000000000000..4b9cc968b0d0 --- /dev/null +++ b/platform/darwin/src/gltf/GLTFMTLRenderItem.h @@ -0,0 +1,23 @@ +// +// GLTFMTLRenderItem.h +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/19/24. +// + +#import +#import "gltfkit/GLTFNode.h" +#import "gltfkit/GLTFMesh.h" + +NS_ASSUME_NONNULL_BEGIN + + +@interface GLTFMTLRenderItem: NSObject +@property (nonatomic) NSString *label; +@property (nonatomic) GLTFNode *node; +@property (nonatomic, strong) GLTFSubmesh *submesh; +@property (nonatomic, assign) VertexUniforms vertexUniforms; +@property (nonatomic, assign) FragmentUniforms fragmentUniforms; +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/GLTFMTLRenderItem.m b/platform/darwin/src/gltf/GLTFMTLRenderItem.m new file mode 100644 index 000000000000..9f7ac94705cf --- /dev/null +++ b/platform/darwin/src/gltf/GLTFMTLRenderItem.m @@ -0,0 +1,12 @@ +// +// GLTFMTLRenderItem.m +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/19/24. +// + +#import "GLTFMTLRenderItem.h" + +@implementation GLTFMTLRenderItem + +@end diff --git a/platform/darwin/src/gltf/GLTFManager.hpp b/platform/darwin/src/gltf/GLTFManager.hpp new file mode 100644 index 000000000000..fcd1061e8ddd --- /dev/null +++ b/platform/darwin/src/gltf/GLTFManager.hpp @@ -0,0 +1,107 @@ +// +// GLTFManager.hpp +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/25/24. +// + +#ifndef GLTFManager_hpp +#define GLTFManager_hpp + +#include +#include +#include +#include +#include +#include "GLTFRenderer.hpp" +#include "GLTFModel.hpp" +#include "GLTFManagerRenderingEnvironment.hpp" + +namespace maplibre { namespace gltf { + + // The type of rendering environment we're in + typedef enum { + RenderingEnvironmentUnknown, + RenderingEnvironmentMetal, + RenderingEnvironmentOpenGL, + RenderingEnvironmentVulkan + } RenderingEnvironment; + + struct Coordinate2D { + double _lat; + double _lon; + }; + + struct Cartesian3D { + double _x; + double _y; + double _z; + }; + + + typedef std::function ProjectionCallback; + + // The GLTF Manager class is the top level entry point + // for all things model based + class GLTFManager { + public: + // Set the callback + void setProjectionCallback(ProjectionCallback projectionCallback); + + // Instantiate the manager with the appropriate environment + GLTFManager(RenderingEnvironment renderingEnvironment); + + // Load a model + void addModel(std::shared_ptr model); + + // Remove a model + void removeModel(std::shared_ptr model); + + // Current meter to screen pixel scale + double _metersPerPixel = 1.0; + + // Set the drawable size + void setDrawableSize(int width, int height); + + // Set the tilt deg + void setTiltDeg(double tiltDeg); + + // Set the rotation deg + void setRotationDeg(double rotationDeg); + + // Set the rendering environment variables + void setRenderingEnvironmentVariables(std::shared_ptr environmentVars); + + // Update any animations + void updateScene(float timeSinceLastDraw); + + // Render + void render(); + + private: + RenderingEnvironment _renderingEnvironment = RenderingEnvironmentUnknown; + + // List of models + std::vector> _models; + + // Projection callback + ProjectionCallback _projectionCallback; + + private: + // Rendering environment + void createRenderingEnvironment(); + + // The renderer + std::shared_ptr _renderer = nullptr; + + + int _drawableWidth = 1; + int _drawableHeight = 1; + double _tiltDeg = 0; + double _rotationDeg = 0; + + }; + +}} + +#endif /* GLTFManager_hpp */ diff --git a/platform/darwin/src/gltf/GLTFManager.mm b/platform/darwin/src/gltf/GLTFManager.mm new file mode 100644 index 000000000000..7a3936a53668 --- /dev/null +++ b/platform/darwin/src/gltf/GLTFManager.mm @@ -0,0 +1,170 @@ +// +// GLTFManager.cpp +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/25/24. +// + +#include "GLTFManager.hpp" +#include "MetalRenderer.hpp" +#include "GLTFManagerRenderingEnvironmentMetal.hpp" +#include + +using namespace maplibre::gltf; + +// Set the callback +void GLTFManager::setProjectionCallback(ProjectionCallback projectionCallback) { + _projectionCallback = projectionCallback; +} + +// Instantiate the manager with the appropriate environment +GLTFManager::GLTFManager(RenderingEnvironment renderingEnvironment) { + _renderingEnvironment = renderingEnvironment; + createRenderingEnvironment(); +} + +// Load a model +void GLTFManager::addModel(std::shared_ptr model) { + + _models.push_back(model); + if (_renderer != nullptr) { + _renderer->loadGLTFModel(model); + } + + + +} + +// Remove a model +void GLTFManager::removeModel(std::shared_ptr model) { + + _models.erase(std::find(_models.begin(), _models.end(), model)); + +} + +// Set the drawable size +void GLTFManager::setDrawableSize(int width, int height) { + + _drawableWidth = width; + _drawableHeight = height; + + if (_renderer != nullptr) { + _renderer->setDrawableSize(_drawableWidth, _drawableHeight); + } + +} + + +// Set the tilt deg +void GLTFManager::setTiltDeg(double tiltDeg) { + + _tiltDeg = tiltDeg; + if (_renderer != nullptr) { + _renderer->setTiltDeg(_tiltDeg); + } + +} + + +// Set the rotation deg +void GLTFManager::setRotationDeg(double rotationDeg) { + + _rotationDeg = rotationDeg; + if (_renderer != nullptr) { + _renderer->setRotationDeg(_rotationDeg); + } +} + + + +// Set the rendering environment variables +void GLTFManager::setRenderingEnvironmentVariables(std::shared_ptr environmentVars) { + + if (_renderingEnvironment == RenderingEnvironmentMetal) { + + if (_renderer != nullptr) { + + // Set metal specific stuff + auto mr = std::static_pointer_cast(_renderer); + auto mevars = std::static_pointer_cast(environmentVars); + mr->setMetalDevice(mevars->_metalDevice); + //mr->setCurrentDrawable(mevars->_currentDrawable); + //mr->setCurrentOutputRenderPassDescriptor(mevars->_currentRenderPassDescriptor); + + // TODO: Add depth buffer variable management + + // TODO: Add bloom pass toggle + mr->setUseBloomPass(mevars->_useBloomPass); + + // TODO: Remove all the above and use this instead + mr->setRenderingEnvironemnt(environmentVars); + + + } + + } + +} + + +// Update any animations +void GLTFManager::updateScene(float timeSinceLastDraw) { + if (_renderer == nullptr) { + return; + } + + // Go through all the models and project them. This is a + // hack right now to try and sync the models with the scene + if (_projectionCallback != nullptr) { + + for (auto m: _models) { + Coordinate2D c; + c._lat = m->_referenceLat; + c._lon = m->_referenceLon; + + + + auto cartesian = _projectionCallback(c); + m->_xLateX = cartesian._x; + m->_xLateY = cartesian._y; + m->_xLateZ = cartesian._z; + + } + + } + + + _renderer->setMetersPerPixel(_metersPerPixel); + _renderer->update(timeSinceLastDraw); +} + +// Render +void GLTFManager::render() { + if (_renderer == nullptr) { + return; + } + _renderer->render(); +} + + + +void GLTFManager::createRenderingEnvironment() { + + if (_renderingEnvironment == RenderingEnvironmentMetal) { + + // Create the renderer + _renderer = std::make_shared(); + + // Set the drawable size + _renderer->setDrawableSize(_drawableWidth, _drawableHeight); + + // Set the initial tilt deg + _renderer->setTiltDeg(_tiltDeg); + + // Set metal specific stuff + auto mr = std::static_pointer_cast(_renderer); + + + } + +} diff --git a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp new file mode 100644 index 000000000000..a434745d5c18 --- /dev/null +++ b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp @@ -0,0 +1,31 @@ +// +// GLTFManagerRenderingEnvironment.hpp +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/25/24. +// + +#ifndef GLTFManagerRenderingEnvironment_hpp +#define GLTFManagerRenderingEnvironment_hpp + +#include +#include + +namespace maplibre { namespace gltf { + + // Bsae class does nothing really, just a place holder + class GLTFManagerRenderingEnvironment { + public: + // If the bloom should be used + bool _useBloomPass = false; + + // FOV + double _currentFOVDEG = 50; + + // Environment projection matrix + simd_float4x4 _currentProjectionMatrix; + + }; + +}} +#endif /* GLTFManagerRenderingEnvironment_hpp */ diff --git a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.mm b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.mm new file mode 100644 index 000000000000..c372f7608b8d --- /dev/null +++ b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.mm @@ -0,0 +1,8 @@ +// +// GLTFManagerRenderingEnvironment.cpp +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/25/24. +// + +#include "GLTFManagerRenderingEnvironment.hpp" diff --git a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp new file mode 100644 index 000000000000..a052fbbaf295 --- /dev/null +++ b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp @@ -0,0 +1,40 @@ +// +// GLTFManagerRenderingEnvironmentMetal.hpp +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/25/24. +// + +#ifndef GLTFManagerRenderingEnvironmentMetal_hpp +#define GLTFManagerRenderingEnvironmentMetal_hpp + +#include +#include +#include +#include "GLTFManagerRenderingEnvironment.hpp" + +namespace maplibre { namespace gltf { + + // Bsae class does nothing really, just a place holder + class GLTFManagerRenderingEnvironmentMetal: public GLTFManagerRenderingEnvironment { + public: + // Allows command buffer and render encoder to be passed in. + // if these are nil, then the renderer will create them + id _currentCommandEncoder = nullptr; + id _currentCommandBuffer = nullptr; + + id _currentDrawable = nullptr; + MTLRenderPassDescriptor *_currentRenderPassDescriptor = nullptr; + id _metalDevice = nullptr; + + // TBD: These are placeholders as we noodle how to integrate with ML + // Depth descriptor: If this is null, then use an internal depth + id _depthStencilTexture = nullptr; + + + }; + +}} + + +#endif /* GLTFManagerRenderingEnvironmentMetal_hpp */ diff --git a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.mm b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.mm new file mode 100644 index 000000000000..fd35693ae6bb --- /dev/null +++ b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.mm @@ -0,0 +1,8 @@ +// +// GLTFManagerRenderingEnvironmentMetal.cpp +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/25/24. +// + +#include "GLTFManagerRenderingEnvironmentMetal.hpp" diff --git a/platform/darwin/src/gltf/GLTFMath.cpp b/platform/darwin/src/gltf/GLTFMath.cpp new file mode 100644 index 000000000000..29b56d65e53d --- /dev/null +++ b/platform/darwin/src/gltf/GLTFMath.cpp @@ -0,0 +1,151 @@ +// +// Math.cpp +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/19/24. +// + +#include "GLTFMath.hpp" + + +simd_float4x4 GLTFMatrixFromScale(const simd_float3 s) { + simd_float4x4 m = matrix_identity_float4x4; + m.columns[0].x = s.x; + m.columns[1].y = s.y; + m.columns[2].z = s.z; + return m; +} + +simd_float4x4 GLTFMatrixFromUniformScale(float s) { + simd_float4x4 m = matrix_identity_float4x4; + m.columns[0].x = s; + m.columns[1].y = s; + m.columns[2].z = s; + return m; +} + +simd_float4x4 GLTFMatrixFromTranslation(simd_float3 t) { + simd_float4x4 m = matrix_identity_float4x4; + m.columns[3] = (simd_float4) { t.x, t.y, t.z, 1.0 }; + return m; +} + +GLTFBoundingSphere GLTFBoundingSphereFromBox(const GLTFBoundingBox b) { + GLTFBoundingSphere s; + float midX = (b.maxPoint.x + b.minPoint.x) * 0.5; + float midY = (b.maxPoint.y + b.minPoint.y) * 0.5; + float midZ = (b.maxPoint.z + b.minPoint.z) * 0.5; + + float r = sqrt(pow(b.maxPoint.x - midX, 2) + pow(b.maxPoint.y - midY, 2) + pow(b.maxPoint.z - midZ, 2)); + + s.center = (simd_float3){ midX, midY, midZ }; + s.radius = r; + return s; +} + +simd_float4x4 GLTFRotationMatrixFromAxisAngle(simd_float3 axis, float angle) { + float x = axis.x, y = axis.y, z = axis.z; + float c = cosf(angle); + float s = sinf(angle); + float t = 1 - c; + + simd_float4 c0 = { t * x * x + c, t * x * y + z * s, t * x * z - y * s, 0 }; + simd_float4 c1 = { t * x * y - z * s, t * y * y + c, t * y * z + x * s, 0 }; + simd_float4 c2 = { t * x * z + y * s, t * y * z - x * s, t * z * z + c, 0 }; + simd_float4 c3 = { 0, 0, 0, 1 }; + + return (simd_float4x4){ c0, c1, c2, c3 }; +} + +simd_float3 GLTFAxisX = (simd_float3){ 1, 0, 0 }; +simd_float3 GLTFAxisY = (simd_float3){ 0, 1, 0 }; +simd_float3 GLTFAxisZ = (simd_float3){ 0, 0, 1 }; + +simd_float4x4 GLTFPerspectiveProjectionMatrixAspectFovRH(const float fovY, const float aspect, const float nearZ, const float farZ) +{ + float yscale = 1 / tanf(fovY * 0.5f); // 1 / tan == cot + float xscale = yscale / aspect; + float q = -farZ / (farZ - nearZ); + + simd_float4x4 m = { + .columns[0] = { xscale, 0, 0, 0 }, + .columns[1] = { 0, yscale, 0, 0 }, + .columns[2] = { 0, 0, q, -1 }, + .columns[3] = { 0, 0, q * nearZ, 0 } + }; + + return m; +} + + +simd_float4x4 GLTFOrthoProjectionMatrix(const float left, + const float right, + const float bottom, + const float top, + const float nearZ, + const float farZ) { + + simd_float4x4 m = { + .columns[0] = { 2 / (right - left), 0, 0, 0 }, + .columns[1] = { 0, 2 / (top - bottom), 0, 0 }, + .columns[2] = { 0, 0, 1 / (farZ - nearZ), 0 }, + .columns[3] = { (left + right) / (left - right), (top + bottom) / (bottom - top), nearZ / (nearZ - farZ), 1 } + }; + + return m; + +} + + +simd_float3x3 GLTFMatrixUpperLeft3x3(simd_float4x4 m) { + simd_float3x3 mout = { { + { m.columns[0][0], m.columns[0][1], m.columns[0][2] }, + { m.columns[1][0], m.columns[1][1], m.columns[1][2] }, + { m.columns[2][0], m.columns[2][1], m.columns[2][2] } + } }; + return mout; +} + + +GLTFTextureTransform GLTFTextureTransformMakeIdentity(void) { + GLTFTextureTransform t = { + .offset = (simd_float2){ 0, 0 }, + .scale = (simd_float2){ 1, 1 }, + .rotation = 0, + }; + return t; +} + +GLTFTextureTransform GLTFTextureTransformMakeSRT(simd_float2 scale, float rotation, simd_float2 offset) { + GLTFTextureTransform t = { + .offset = offset, + .scale = scale, + .rotation = rotation, + }; + return t; +} + +simd_float3x3 GLTFTextureMatrixFromTransform(GLTFTextureTransform transform) { + float rs = sinf(-transform.rotation); + float rc = cosf(-transform.rotation); + float tx = transform.offset.x; + float ty = transform.offset.y; + float sx = transform.scale.x; + float sy = transform.scale.y; + simd_float3 c0 = (simd_float3){ rc * sx, rs * sy, 0 }; + simd_float3 c1 = (simd_float3){ -rs * sx, rc * sy, 0 }; + simd_float3 c2 = (simd_float3){ tx, ty, 1 }; + simd_float3x3 m = (simd_float3x3){ c0, c1, c2 }; + return m; +} + +simd_float4x4 GLTFNormalMatrixFromModelMatrix(simd_float4x4 m) { + simd_float3x3 nm = simd_inverse(simd_transpose(GLTFMatrixUpperLeft3x3(m))); + simd_float4x4 mout = { { + { nm.columns[0][0], nm.columns[0][1], nm.columns[0][2], 0 }, + { nm.columns[1][0], nm.columns[1][1], nm.columns[1][2], 0 }, + { nm.columns[2][0], nm.columns[2][1], nm.columns[2][2], 0 }, + { 0, 0, 0, 1 } + } }; + return mout; +} diff --git a/platform/darwin/src/gltf/GLTFMath.hpp b/platform/darwin/src/gltf/GLTFMath.hpp new file mode 100644 index 000000000000..0b8764c1c029 --- /dev/null +++ b/platform/darwin/src/gltf/GLTFMath.hpp @@ -0,0 +1,121 @@ +// +// Math.hpp +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/19/24. +// + +#ifndef Math_hpp +#define Math_hpp + +#include +#include + +typedef enum { + GLTFTextureBindIndexBaseColor, + GLTFTextureBindIndexNormal, + GLTFTextureBindIndexMetallicRoughness, + GLTFTextureBindIndexOcclusion, + GLTFTextureBindIndexEmissive, + GLTFTextureBindIndexDiffuseEnvironment, + GLTFTextureBindIndexSpecularEnvironment, + GLTFTextureBindIndexBRDFLookup, +} GLTFMTLTextureBindIndex; + +#define DEG_RAD 0.0174533 +#define RAD_DEG 57.2958 + +#define GLTFMTLMaximumLightCount 3 +#define GLTFMTLMaximumTextureCount (GLTFTextureBindIndexEmissive + 1) + + +typedef struct { + simd_float3 minPoint; + simd_float3 maxPoint; +} GLTFBoundingBox; + +typedef struct { + simd_float3 center; + float radius; +} GLTFBoundingSphere; + + +typedef struct { + simd_float4x4 modelMatrix; + simd_float4x4 modelViewProjectionMatrix; + simd_float4x4 normalMatrix; +} VertexUniforms; + +typedef struct { + simd_float4 position; + simd_float4 color; + float intensity; + float innerConeAngle; + float outerConeAngle; + float range; + simd_float4 spotDirection; +} Light; + +typedef struct { + float normalScale; + simd_float3 emissiveFactor; + float occlusionStrength; + simd_float2 metallicRoughnessValues; + simd_float4 baseColorFactor; + simd_float3 camera; + float alphaCutoff; + float envIntensity; + Light ambientLight; + Light lights[GLTFMTLMaximumLightCount]; + simd_float3x3 textureMatrices[GLTFMTLMaximumTextureCount]; +} FragmentUniforms; + +typedef struct { + simd_float2 offset; + simd_float2 scale; + float rotation; +} GLTFTextureTransform; + +#ifdef __cplusplus +extern "C" { +#endif + +extern simd_float3 GLTFAxisX; +extern simd_float3 GLTFAxisY; +extern simd_float3 GLTFAxisZ; + +simd_float4x4 GLTFMatrixFromScale(const simd_float3 s); + +simd_float4x4 GLTFMatrixFromUniformScale(float s); + +GLTFBoundingSphere GLTFBoundingSphereFromBox(const GLTFBoundingBox b); + +simd_float4x4 GLTFMatrixFromTranslation(simd_float3 t); + +simd_float4x4 GLTFRotationMatrixFromAxisAngle(simd_float3 axis, float angle); + +simd_float4x4 GLTFPerspectiveProjectionMatrixAspectFovRH(const float fovY, const float aspect, const float nearZ, const float farZ); + +simd_float4x4 GLTFOrthoProjectionMatrix(const float left, + const float right, + const float bottom, + const float top, + const float nearZ, + const float farZ); + +simd_float3x3 GLTFMatrixUpperLeft3x3(simd_float4x4 m); + +GLTFTextureTransform GLTFTextureTransformMakeIdentity(void); + +GLTFTextureTransform GLTFTextureTransformMakeSRT(simd_float2 scale, float rotation, simd_float2 offset); + +simd_float3x3 GLTFTextureMatrixFromTransform(GLTFTextureTransform transform); + +simd_float4x4 GLTFNormalMatrixFromModelMatrix(simd_float4x4 m); + + +#ifdef __cplusplus +} +#endif + +#endif /* Math_hpp */ diff --git a/platform/darwin/src/gltf/GLTFModel.cpp b/platform/darwin/src/gltf/GLTFModel.cpp new file mode 100644 index 000000000000..4d97152eff71 --- /dev/null +++ b/platform/darwin/src/gltf/GLTFModel.cpp @@ -0,0 +1,8 @@ +// +// GLTFModel.cpp +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/25/24. +// + +#include "GLTFModel.hpp" diff --git a/platform/darwin/src/gltf/GLTFModel.hpp b/platform/darwin/src/gltf/GLTFModel.hpp new file mode 100644 index 000000000000..0158e5d8ccdd --- /dev/null +++ b/platform/darwin/src/gltf/GLTFModel.hpp @@ -0,0 +1,43 @@ +// +// GLTFModel.hpp +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/25/24. +// + +#ifndef GLTFModel_hpp +#define GLTFModel_hpp + +#include +#include + +namespace maplibre { namespace gltf { + + // Model + class GLTFModel { + public: + // + double _referenceLat = 0; + double _referenceLon = 0; + + // What it takes to scale this model to meters units + float _scaleFactor = 1; + + // Rotation around the reference point + float _rotationDeg = 0; + + // The URL for the model, used by the loader + std::string _modelURL; + + // This is a hack to deal with passing in the translation vector. + // NEed to reconcile this with the renderable model's version of it + double _xLateX = 0; + double _xLateY = 0; + double _xLateZ = 0; + + }; + + +}} + +#endif /* GLTFModel_hpp */ diff --git a/platform/darwin/src/gltf/GLTFModelLayer.h b/platform/darwin/src/gltf/GLTFModelLayer.h new file mode 100644 index 000000000000..ab22715c4a9f --- /dev/null +++ b/platform/darwin/src/gltf/GLTFModelLayer.h @@ -0,0 +1,21 @@ +// +// CustomLayerTest.h +// MapLibreTest +// +// Created by Malcolm Toon on 11/7/24. +// + +#import "MLNCustomStyleLayer.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface GLTFModelLayer : MLNCustomStyleLayer + +-(void)loadModel:(NSString *)appResourceFilename + lat:(double)lat + lon:(double)lon + rotationDeg:(double)rotationDeg; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/GLTFModelLayer.mm b/platform/darwin/src/gltf/GLTFModelLayer.mm new file mode 100644 index 000000000000..d9980d7a97ac --- /dev/null +++ b/platform/darwin/src/gltf/GLTFModelLayer.mm @@ -0,0 +1,418 @@ +// +// CustomLayerTest.m +// MapLibreTest +// +// Created by Malcolm Toon on 11/6/24. +// + +#import "GLTFModelLayer.h" +#import +#import "MLNBackendResource.h" +#import "MLNMapView.h" +#import "MLNMapProjection.h" +#include +#import "GLTFManagerRenderingEnvironmentMetal.hpp" +#import "GLTFManager.hpp" +#import "GLTFMath.hpp" + +using namespace maplibre::gltf; + +// This is here to hold the metadata about the model if load is called before +// the layer is created +@interface GLTFModelMetadata : NSObject +@property NSString *modelPath; +@property CLLocationCoordinate2D modelCoordinate; +@property double modelRotation; +@property BOOL modelLoaded; +@end + +@implementation GLTFModelMetadata +@end + +@interface GLTFModelLayer () { + std::shared_ptr _metalEnvironment; + std::shared_ptr _manager; + +} + +@property NSMutableArray *models; +@property BOOL managerCreated; + + +@end + +simd_float4x4 toSimdMatrix4F(const MLNMatrix4 & mlMatrix) { + simd_float4x4 tempResult; + + /* + typedef struct MLNMatrix4 { + double m00, m01, m02, m03; + double m10, m11, m12, m13; + double m20, m21, m22, m23; + double m30, m31, m32, m33; + } MLNMatrix4; +*/ + + tempResult.columns[0][0] = mlMatrix.m00; + tempResult.columns[0][1] = mlMatrix.m01; + tempResult.columns[0][2] = mlMatrix.m02; + tempResult.columns[0][3] = mlMatrix.m03; + tempResult.columns[1][0] = mlMatrix.m10; + tempResult.columns[1][1] = mlMatrix.m11; + tempResult.columns[1][2] = mlMatrix.m12; + tempResult.columns[1][3] = mlMatrix.m13; + tempResult.columns[2][0] = mlMatrix.m20; + tempResult.columns[2][1] = mlMatrix.m21; + tempResult.columns[2][2] = mlMatrix.m22; + tempResult.columns[2][3] = mlMatrix.m23; + tempResult.columns[3][0] = mlMatrix.m30; + tempResult.columns[3][1] = mlMatrix.m31; + tempResult.columns[3][2] = mlMatrix.m32; + tempResult.columns[3][3] = mlMatrix.m33; + + + return tempResult; +} + + + +simd_double4x4 toSimdMatrix4D(const MLNMatrix4 & mlMatrix) { + simd_double4x4 tempResult; + + /* + typedef struct MLNMatrix4 { + double m00, m01, m02, m03; + double m10, m11, m12, m13; + double m20, m21, m22, m23; + double m30, m31, m32, m33; + } MLNMatrix4; +*/ + + tempResult.columns[0][0] = mlMatrix.m00; + tempResult.columns[0][1] = mlMatrix.m01; + tempResult.columns[0][2] = mlMatrix.m02; + tempResult.columns[0][3] = mlMatrix.m03; + tempResult.columns[1][0] = mlMatrix.m10; + tempResult.columns[1][1] = mlMatrix.m11; + tempResult.columns[1][2] = mlMatrix.m12; + tempResult.columns[1][3] = mlMatrix.m13; + tempResult.columns[2][0] = mlMatrix.m20; + tempResult.columns[2][1] = mlMatrix.m21; + tempResult.columns[2][2] = mlMatrix.m22; + tempResult.columns[2][3] = mlMatrix.m23; + tempResult.columns[3][0] = mlMatrix.m30; + tempResult.columns[3][1] = mlMatrix.m31; + tempResult.columns[3][2] = mlMatrix.m32; + tempResult.columns[3][3] = mlMatrix.m33; + + + return tempResult; +} + +@implementation GLTFModelLayer { + // The render pipeline state + id _pipelineState; + id _depthStencilStateWithoutStencil; +} + +-(id)initWithIdentifier:(NSString *)identifier { + if (self = [super initWithIdentifier:identifier]) { + self.models = [NSMutableArray array]; + } + return self; +} + +- (void)didMoveToMapView:(MLNMapView *)mapView { + MLNBackendResource resource = [mapView backendResource]; + + NSString *shaderSource = @ +" #include \n" +" using namespace metal;\n" +" typedef struct\n" +" {\n" +" vector_float2 position;\n" +" vector_float4 color;\n" +" } Vertex;\n" +" struct RasterizerData\n" +" {\n" +" float4 position [[position]];\n" +" float4 color;\n" +" };\n" +" vertex RasterizerData\n" +" vertexShader(uint vertexID [[vertex_id]],\n" +" constant Vertex *vertices [[buffer(0)]],\n" +" constant vector_uint2 *viewportSizePointer [[buffer(1)]])\n" +" {\n" +" RasterizerData out;\n" +" float2 pixelSpacePosition = vertices[vertexID].position.xy;\n" +" vector_float2 viewportSize = vector_float2(*viewportSizePointer);\n" +" out.position = vector_float4(0.0, 0.0, 0.0, 1.0);\n" +" out.position.xy = pixelSpacePosition / (viewportSize / 2.0);\n" +" out.color = vertices[vertexID].color;\n" +" return out;\n" +" }\n" +" fragment float4 fragmentShader(RasterizerData in [[stage_in]])\n" +" {\n" +" return in.color;\n" +" }\n"; + + + NSError *error = nil; + id _device = resource.device; + id library = [_device newLibraryWithSource:shaderSource options:nil error:&error]; + NSAssert(library, @"Error compiling shaders: %@", error); + id vertexFunction = [library newFunctionWithName:@"vertexShader"]; + id fragmentFunction = [library newFunctionWithName:@"fragmentShader"]; + + // Configure a pipeline descriptor that is used to create a pipeline state. + MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; + pipelineStateDescriptor.label = @"Simple Pipeline"; + pipelineStateDescriptor.vertexFunction = vertexFunction; + pipelineStateDescriptor.fragmentFunction = fragmentFunction; + pipelineStateDescriptor.colorAttachments[0].pixelFormat = resource.mtkView.colorPixelFormat; + pipelineStateDescriptor.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; + pipelineStateDescriptor.stencilAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; + + _pipelineState = [_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor + error:&error]; + NSAssert(_pipelineState, @"Failed to create pipeline state: %@", error); + + // Notice that we don't configure the stencilTest property, leaving stencil testing disabled + MTLDepthStencilDescriptor *depthStencilDescriptor = [[MTLDepthStencilDescriptor alloc] init]; + depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways; // Or another value as needed + depthStencilDescriptor.depthWriteEnabled = NO; + + _depthStencilStateWithoutStencil = [_device newDepthStencilStateWithDescriptor:depthStencilDescriptor]; + + + + +} + +-(void)loadModels { + + // This goes through the model array and loads whatever hasn't been loaded already + for (GLTFModelMetadata *m in self.models) { + [self addModel:m]; + } + + /* + @{@"modelURL":@"al_awwal_v02.glb",@"lat":@(24.729326775575686),@"lon":@(46.623841518553355),@"rot":@(0)}, + @{@"modelURL":@"alawwalpark-03.glb",@"lat":@(24.729326775575686),@"lon":@(46.623841518553355),@"rot":@(0)}, + @{@"modelURL":@"Al_faisaliyah_005.glb",@"lat":@(24.69052042910012),@"lon":@(46.6856124145449),@"rot":@(0)}, + @{@"modelURL":@"Al_faisaliyah_007.glb",@"lat":@(24.69052042910012),@"lon":@(46.6856124145449),@"rot":@(0)}, + @{@"modelURL":@"alnajdoul_004.glb",@"lat":@(24.739367517042293),@"lon":@(46.65956858776968),@"rot":@(0)}, + @{@"modelURL":@"masmak_010-bl.glb",@"lat":@(24.63125410132941),@"lon":@(46.713372982335976),@"rot":@(0)}, + @{@"modelURL":@"turaif-03-bl.glb",@"lat":@(24.733690223733547),@"lon":@(46.57492745287205),@"rot":@(0)}, + @{@"modelURL":@"tvtower_009.glb",@"lat":@(24.643391710253425),@"lon":@(46.69595652756665),@"rot":@(0)}, +*/ + + //[self loadModel:@"alawwalpark-03.glb" lat:24.729326775575686 lon:46.623841518553355 rotationDeg:90]; + /* + [self loadModel:@"Al_faisaliyah_007.glb" lat:24.69052042910012 lon:46.6856124145449 rotationDeg:-65]; + [self loadModel:@"alnajdoul_004.glb" lat:24.739367517042293 lon:46.65956858776968 rotationDeg:25]; + [self loadModel:@"masmak_010-bl.glb" lat:24.63125410132941 lon:46.713372982335976 rotationDeg:0]; + [self loadModel:@"turaif-03-bl.glb" lat:24.733690223733547 lon:46.57492745287205 rotationDeg:0]; + [self loadModel:@"tvtower_009.glb" lat:24.643391710253425 lon:46.69595652756665 rotationDeg:0]; + + + [self loadModel:@"KAFD_Building01_v01.glb" lat:24.76592011755998 lon:46.64337787824368 rotationDeg:0]; + [self loadModel:@"KAFD_Building02_v01.glb" lat:24.76592011755998 lon:46.64337787824368 rotationDeg:0]; + [self loadModel:@"KAFD_Building06_v02.glb" lat:24.76592011755998 lon:46.64337787824368 rotationDeg:0]; + [self loadModel:@"KAFD_Building07_v01.glb" lat:24.76592011755998 lon:46.64337787824368 rotationDeg:0]; + [self loadModel:@"KAFD_Building09_v01.glb" lat:24.76592011755998 lon:46.64337787824368 rotationDeg:0]; +*/ + +} + +-(void)loadModel:(NSString *)appResourceFilename + lat:(double)lat + lon:(double)lon + rotationDeg:(double)rotationDeg { + + GLTFModelMetadata *modelMetadata = [[GLTFModelMetadata alloc] init]; + modelMetadata.modelPath = appResourceFilename; + modelMetadata.modelCoordinate = CLLocationCoordinate2DMake(lat, lon); + modelMetadata.modelRotation = rotationDeg; + [self.models addObject:modelMetadata]; + + if (self.managerCreated) { + [self addModel:modelMetadata]; + } + +} + + +-(void)addModel:(GLTFModelMetadata *)modelMetadata { + + if (modelMetadata.modelLoaded) { + return; + } + + NSURL *fileURL = [[NSBundle mainBundle] URLForResource:modelMetadata.modelPath withExtension:nil]; + + std::string modelURL = [[fileURL absoluteString] UTF8String]; + + std::shared_ptr model = std::make_shared(); + model->_referenceLat = modelMetadata.modelCoordinate.latitude; + model->_referenceLon = modelMetadata.modelCoordinate.longitude; + model->_modelURL = modelURL; + model->_rotationDeg = modelMetadata.modelRotation; + model->_scaleFactor = 1.0; // Models are in meters + + _manager->addModel(model); + + modelMetadata.modelLoaded = YES; + +} + + +- (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingContext)context { + + MLNBackendResource resource = [mapView backendResource]; + + bool loadModels = false; + + if (_manager == nullptr) { + + // Setup the metal environment for the model rendering + _metalEnvironment = std::make_shared(); + + // Create the GLTF Manager + _manager = std::make_shared(RenderingEnvironmentMetal); + _manager->setRenderingEnvironmentVariables(_metalEnvironment); + + _manager->setProjectionCallback(^Cartesian3D(const Coordinate2D & coordinate){ + Cartesian3D tempResult; + + tempResult._x = 0; + tempResult._y = 0; + tempResult._z = 0; + + + MLNMapProjection *proj = mapView.mapProjection; + CGPoint p = [proj convertCoordinate:CLLocationCoordinate2DMake(coordinate._lat, coordinate._lon)]; + + //NSLog(@"ZOOM LEVEL: %f",mapView.zoomLevel); + //NSLog(@"Meters Per Pixel: %f",proj.metersPerPoint); + + + // The 2.0 is point to pixel scaling + double viewportSizeX = resource.mtkView.drawableSize.width / 2.0; + double viewportSizeY = resource.mtkView.drawableSize.height / 2.0; + + double halfX = (viewportSizeX / 2.0); + double halfY = (viewportSizeY / 2.0); + + double offsetX = p.x - halfX; + + double projX = offsetX / viewportSizeX; + double projY = (viewportSizeY - p.y - halfY) / viewportSizeY; + + double aspect = viewportSizeX / viewportSizeY; + + tempResult._x = projX * 2.0 * aspect; + tempResult._y = projY * 2.0; + + tempResult._x = projX; + tempResult._y = projY; + + NSLog(@"P: %f, %f -> %f, %f", p.x, p.y, projX, projY); + + return tempResult; + }); + + loadModels = true; + } + + _metalEnvironment->_currentFOVDEG = context.fieldOfView * RAD_DEG; + _metalEnvironment->_currentProjectionMatrix = toSimdMatrix4F(context.projectionMatrix); + _metalEnvironment->_currentCommandEncoder = self.renderEncoder; + _metalEnvironment->_currentCommandBuffer = resource.commandBuffer; + _metalEnvironment->_metalDevice = resource.mtkView.device; + _metalEnvironment->_currentDrawable = resource.mtkView.currentDrawable; + _metalEnvironment->_currentRenderPassDescriptor = resource.mtkView.currentRenderPassDescriptor; + + // TODO: Remove this.. This is legacy + _manager->setRenderingEnvironmentVariables(_metalEnvironment); + + if (loadModels) { + [self loadModels]; + } + + vector_uint2 _viewportSize; + _viewportSize.x = resource.mtkView.drawableSize.width; + _viewportSize.y = resource.mtkView.drawableSize.height; + + _manager->setDrawableSize(_viewportSize.x, _viewportSize.y); + _manager->_metersPerPixel = 0.05; + + + MLNMapProjection *proj2 = mapView.mapProjection; + _manager->_metersPerPixel = proj2.metersPerPoint / 2.0; + _manager->setTiltDeg(90-mapView.camera.pitch); + _manager->setRotationDeg(-mapView.camera.heading); + + float timestep = (1 / 60.0f); + _manager->updateScene(timestep); + + + // Render the image + _manager->render(); + + return; + + #if TEST + + + + MLNMapProjection *proj = mapView.mapProjection; + CGPoint p = [proj convertCoordinate:CLLocationCoordinate2DMake(43, -70)]; + NSLog(@"P: %f, %f", p.x, p.y); + + // Use the supplied render command encoder to encode commands + id renderEncoder = self.renderEncoder; + if(renderEncoder != nil) + { + + typedef struct + { + vector_float2 position; + vector_float4 color; + } Vertex; + + static const Vertex triangleVertices[] = + { + // 2D positions, RGBA colors + { { 250, -250 }, { 1, 0, 0, 1 } }, + { { -250, -250 }, { 0, 1, 0, 1 } }, + { { 0, 250 }, { 0, 0, 1, 1 } }, + }; + + [renderEncoder setRenderPipelineState:_pipelineState]; + [renderEncoder setDepthStencilState:_depthStencilStateWithoutStencil]; + + // Pass in the parameter data. + [renderEncoder setVertexBytes:triangleVertices + length:sizeof(triangleVertices) + atIndex:0]; + + [renderEncoder setVertexBytes:&_viewportSize + length:sizeof(_viewportSize) + atIndex:1]; + + // Draw the triangle. + [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle + vertexStart:0 + vertexCount:3]; + } + #endif + +} + +- (void)willMoveFromMapView:(MLNMapView *)mapView { + // Clean up +} + +@end + diff --git a/platform/darwin/src/gltf/GLTFModelLoader.h b/platform/darwin/src/gltf/GLTFModelLoader.h new file mode 100644 index 000000000000..6cf1b928b989 --- /dev/null +++ b/platform/darwin/src/gltf/GLTFModelLoader.h @@ -0,0 +1,24 @@ +// +// GLTFModelLoader.h +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/25/24. +// + +#import +#import "gltfkit/GLTFAsset.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^GLTFModelLoaderCompletionHandler)(GLTFAsset *asset); + +@interface GLTFModelLoader : NSObject + +-(void)loadURL:(NSURL *)assetURL +withCompletionHandler:(GLTFModelLoaderCompletionHandler)completionHandler +bufferAllocator:(id)bufferAllocator; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/GLTFModelLoader.m b/platform/darwin/src/gltf/GLTFModelLoader.m new file mode 100644 index 000000000000..66aeba4ec862 --- /dev/null +++ b/platform/darwin/src/gltf/GLTFModelLoader.m @@ -0,0 +1,74 @@ +// +// GLTFModelLoader.m +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/25/24. +// + +#import "GLTFModelLoader.h" +#import "gltfkit/GLTFAsset.h" +#import "gltfkit/GLTFMTLBufferAllocator.h" + +@interface GLTFModelLoader () { + +} + +@property GLTFModelLoaderCompletionHandler completionHandler; + +@end + +@implementation GLTFModelLoader + +-(void)loadURL:(NSURL *)assetURL +withCompletionHandler:(GLTFModelLoaderCompletionHandler)completionHandler +bufferAllocator:(id)bufferAllocator { + + self.completionHandler = completionHandler; + [GLTFAsset loadAssetWithURL:assetURL + bufferAllocator:bufferAllocator + delegate:self]; + +} + + +- (void)assetWithURL:(nonnull NSURL *)assetURL didFailToLoadWithError:(nonnull NSError *)error { + NSLog(@"Asset load failed with error: %@", error); +} + +- (void)assetWithURL:(nonnull NSURL *)assetURL + didFinishLoading:(nonnull GLTFAsset *)asset { + dispatch_async(dispatch_get_main_queue(), ^{ + + if (self.completionHandler) { + self.completionHandler(asset); + } + self.completionHandler = nil; + + NSLog(@"INFO: Total live buffer allocation size after document load is %0.2f MB", ([GLTFMTLBufferAllocator liveAllocationSize] / (float)1e6)); + }); +} + +- (void)assetWithURL:(nonnull NSURL *)assetURL +requiresContentsOfURL:(nonnull NSURL *)url + completionHandler:(void (^)(NSData *_Nullable, NSError *_Nullable))completionHandler { + NSURLSessionDataTask *task = [GLTFModelLoader.urlSession dataTaskWithURL:url + completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) + { + completionHandler(data, error); + }]; + [task resume]; +} + ++ (NSURLSession *)urlSession { + static NSURLSession *_urlSession = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; + _urlSession = [NSURLSession sessionWithConfiguration:configuration]; + }); + return _urlSession; +} + + + +@end diff --git a/platform/darwin/src/gltf/GLTFRenderer.cpp b/platform/darwin/src/gltf/GLTFRenderer.cpp new file mode 100644 index 000000000000..f02c711593ab --- /dev/null +++ b/platform/darwin/src/gltf/GLTFRenderer.cpp @@ -0,0 +1,82 @@ +// +// GLTFRenderer.cpp +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/19/24. +// + +#include "GLTFRenderer.hpp" + +using namespace maplibre::gltf; + +GLTFRenderer::GLTFRenderer() { + _camera = std::make_unique(); +} + +// Destructor +GLTFRenderer::~GLTFRenderer() { + // Base class does nothing +} + + +// Update any animations +void GLTFRenderer::update(float timeSinceLastDraw) { + // Base class does nothing +} + +// Render +void GLTFRenderer::render() { + // Base class does nothing +} + +// Set the drawable size +void GLTFRenderer::setDrawableSize(int width, int height) { + // Base class does nothing +} + +// Protected items +void GLTFRenderer::loadBloomPipelines() { + +} + +void GLTFRenderer::loadTonemapPipeline() { + +} + +void GLTFRenderer::updateFramebufferSize() { + +} + + +// Load a model +void GLTFRenderer::loadGLTFModel(std::shared_ptr model) { + // Base class does nothing +} + +// Set the meters per pixel scale +void GLTFRenderer::setMetersPerPixel(double metersPerPixel) { + _metersPerPixel = metersPerPixel; +} + +// Set tilt +void GLTFRenderer::setTiltDeg(double tiltDeg) { + _tiltDeg = tiltDeg; +} + +// Set the rotation deg +void GLTFRenderer::setRotationDeg(double rotationDeg) { + _rotationDeg = rotationDeg; +} + + + +// Use bloom pass +void GLTFRenderer::setUseBloomPass(bool useBloomPass) { + _useBloomPass = useBloomPass; +} + + +// Set the rendering environemnt variables +void GLTFRenderer::setRenderingEnvironemnt(std::shared_ptr renderingEnvironment) { + _renderingEnvironment = renderingEnvironment; +} diff --git a/platform/darwin/src/gltf/GLTFRenderer.hpp b/platform/darwin/src/gltf/GLTFRenderer.hpp new file mode 100644 index 000000000000..22d52ad0722e --- /dev/null +++ b/platform/darwin/src/gltf/GLTFRenderer.hpp @@ -0,0 +1,69 @@ +// +// GLTFRenderer.hpp +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/19/24. +// + +#ifndef GLTFRenderer_hpp +#define GLTFRenderer_hpp + +#include +#include "Camera.hpp" +#include "GLTFModel.hpp" +#include "GLTFManagerRenderingEnvironment.hpp" +#include + +namespace maplibre { namespace gltf { + + class GLTFRenderer { + public: + // Constructor + GLTFRenderer(); + + // Destructor + virtual ~GLTFRenderer(); + + // Update any animations + virtual void update(float timeSinceLastDraw); + + // Render + virtual void render(); + + // Set the drawable size + virtual void setDrawableSize(int width, int height); + + // Load a model + virtual void loadGLTFModel(std::shared_ptr model); + + // Set the meters per pixel scale + void setMetersPerPixel(double metersPerPixel); + + // Set tilt + void setTiltDeg(double tiltDeg); + + // Set the rotation deg + void setRotationDeg(double rotationDeg); + + // Use bloom pass + void setUseBloomPass(bool useBloomPass); + + // Set the rendering environemnt variables + virtual void setRenderingEnvironemnt(std::shared_ptr renderingEnvironment); + + protected: + std::unique_ptr _camera = nullptr; + double _metersPerPixel = 1; + std::shared_ptr _renderingEnvironment = nullptr; + double _tiltDeg = 0; + double _rotationDeg = 0; + bool _useBloomPass = true; + virtual void loadBloomPipelines(); + virtual void loadTonemapPipeline(); + virtual void updateFramebufferSize(); + + }; + +}} + +#endif /* GLTFRenderer_hpp */ diff --git a/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm b/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm new file mode 100644 index 000000000000..7524bf3a8e81 --- /dev/null +++ b/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm @@ -0,0 +1,602 @@ +// +// Untitled.h +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/19/24. +// + +#include "MetalRenderer.hpp" + + +#import "GLTFMath.hpp" +#import "gltfkit/GLTFScene.h" +#import "gltfkit/GLTFMesh.h" +#import "gltfkit/GLTFMaterial.h" +#import "gltfkit/GLTFKHRLight.h" +#import "gltfkit/GLTFMTLUtilities.h" +#import "gltfkit/GLTFSkin.h" +#import "gltfkit/GLTFMTLBufferAllocator.h" +#import "gltfkit/GLTFAccessor.h" +#import "gltfkit/GLTFBufferView.h" +#import "gltfkit/GLTFVertexDescriptor.h" + + + +using namespace maplibre::gltf; + +// Encapsulated in GLTFRenderer+GLTFAsset +void MetalRenderer::setGLTFAsset(GLTFAsset *asset, std::shared_ptr model) { + + _models.clear(); + addGLTFAsset(asset, model); + +// _asset = asset; +// if (_asset != nullptr) { +// computeRegularizationMatrix(); +// computeTransforms(); +// addDefaultLights(); +// } + + +} + +// +void MetalRenderer::addGLTFAsset(GLTFAsset *asset, std::shared_ptr model) { + + auto m = createRenderModel(asset, model); + _models.push_back(m); + +} + +std::shared_ptr MetalRenderer::createRenderModel(GLTFAsset *asset, std::shared_ptr model) { + + std::shared_ptr tempResult = std::make_shared(); + tempResult->_asset = asset; + tempResult->_gltfModel = model; + + computeRegularizationMatrix(tempResult); + computeTransforms(tempResult); + addDefaultLights(tempResult); + + return tempResult; + +} + + + +void MetalRenderer::addDefaultLights(std::shared_ptr model) { +// GLTFNode *lightNode = [[GLTFNode alloc] init]; +// lightNode.translation = (simd_float3){ 0, 0, 1 }; +// lightNode.rotationQuaternion = simd_quaternion(1.0f, 0, 0, 0); +// GLTFKHRLight *light = [[GLTFKHRLight alloc] init]; +// lightNode.light = light; +// [self.asset.defaultScene addNode:lightNode]; +// [self.asset addLight:light]; +// +// GLTFKHRLight *ambientLight = [[GLTFKHRLight alloc] init]; +// ambientLight.type = GLTFKHRLightTypeAmbient; +// ambientLight.intensity = 0.1; +// [self.asset addLight:ambientLight]; +// self.asset.defaultScene.ambientLight = ambientLight; +} + +void MetalRenderer::computeRegularizationMatrix(std::shared_ptr model) { + GLTFBoundingSphere bounds = GLTFBoundingSphereFromBox(model->_asset.defaultScene.approximateBounds); + model->_boundingSphere = bounds; + float scale = (bounds.radius > 0) ? (1 / (bounds.radius)) : 1; + simd_float4x4 centerScale = GLTFMatrixFromUniformScale(scale); + simd_float4x4 centerTranslation = GLTFMatrixFromTranslation(-bounds.center); + + // This regularization matrix centers the model + model->_regularizationMatrix = matrix_multiply(centerScale, centerTranslation); + + + // The regularization matrix just scales it to show in the viewport + model->_regularizationMatrix = centerScale; + +} + +void MetalRenderer::computeTransforms(std::shared_ptr model) { + + // New stuff + + + + + + + + + + + + + + // TODO: Someday look into point of view? + /* + if (self.pointOfView == nil) { + self.viewMatrix = matrix_multiply(self.camera.viewMatrix, self.regularizationMatrix); + } else { + self.viewMatrix = self.camera.viewMatrix; + } + */ + + // TODO: Remove this.. just something to show that the translation stuff + // is in there + //model->_rotationDeg = 0; // model->_rotationDeg + 0.75; + + /* + auto rotationMatrix = GLTFRotationMatrixFromAxisAngle(simd_make_float3(0.0, 1.0, 0.0), model->_rotationDeg * DEG_RAD); + auto rotatedModel = matrix_multiply(modelMatrix, rotationMatrix); + auto translatedVector = model->_translationVector + model->_translationDistance; + translatedVector.z = 0; + auto translationMatrix = GLTFMatrixFromTranslation(translatedVector); + auto modelMatrix2 = matrix_multiply(translationMatrix, rotatedModel); + model->_viewMatrix = matrix_multiply(modelMatrix2, _camera->_viewMatrix); +*/ + + // Compute the model matrix: This was the original + model->_modelViewMatrix = matrix_multiply(_camera->_viewMatrix, + model->_regularizationMatrix); + + // New news + #if TEST + static float rot = 0; + rot += 0.01; + static float xLate = 0; + static float xLateDir = 0.01; + xLate = xLate + xLateDir; + if (xLate > 1) { + xLateDir = -0.01; + } else if (xLate < -1) { + xLateDir = 0.01; + } + rot = 0; + xLate = 0; + #endif + + simd_float3 translatedVector = simd_make_float3(model->_gltfModel->_xLateX, + model->_gltfModel->_xLateY, + model->_gltfModel->_xLateZ); + + auto translationMatrix = GLTFMatrixFromTranslation(translatedVector); + + + // TODO: This goes away.. Just the regularizating matrix + auto modelMatrix = model->_regularizationMatrix; + + // This will be the first matrix in the future + modelMatrix = matrix_identity_float4x4; + double metersInView = (double)_drawableSize.x * _metersPerPixel; + double scale = 2.0 / metersInView; + auto scaleMatrix = GLTFMatrixFromUniformScale(scale); + modelMatrix = matrix_multiply(scaleMatrix, modelMatrix); + + // Rotation + auto modelEnvironmentRotation = GLTFRotationMatrixFromAxisAngle(GLTFAxisY, (model->_gltfModel->_rotationDeg -_rotationDeg) * DEG_RAD); + auto modelRotated = matrix_multiply(modelEnvironmentRotation, modelMatrix); + + // Tilt + auto modelEnvironmentTilt = GLTFRotationMatrixFromAxisAngle(GLTFAxisX, _tiltDeg * DEG_RAD); + auto modelTilted = matrix_multiply(modelEnvironmentTilt, modelRotated); + + // This was just debug stuff to rotate in the scene +// auto modelRotation = GLTFRotationMatrixFromAxisAngle(GLTFAxisY, -rot); +// auto modelRotation2 = matrix_multiply(modelRotation, modelMatrix); +// + + + // + auto modelTranslated = matrix_multiply(modelTilted, translationMatrix); + + model->_modelMatrix = modelTranslated; + + model->_modelViewMatrix = matrix_multiply(_camera->_viewMatrix, + modelTranslated); + + + + + + + + +} + +void MetalRenderer::renderScene(std::shared_ptr model, + GLTFScene *scene, + id commandBuffer, + id renderEncoder) { + + if (scene == nil) { + return; + } +/* + long timedOut = dispatch_semaphore_wait(_frameBoundarySemaphore, dispatch_time(0, 1 * NSEC_PER_SEC)); + if (timedOut) { + NSLog(@"Failed to receive frame boundary signal before timing out; calling signalFrameCompletion manually. " + "Remember to call signalFrameCompletion on GLTFMTLRenderer from the completion handler of the command buffer " + "into which you encode the work for drawing assets"); + signalFrameCompletion(); + } + */ + //self.ambientLight = scene.ambientLight; + + for (GLTFNode *rootNode in scene.nodes) { + buildLightListRecursive(rootNode); + } + + for (GLTFNode *rootNode in scene.nodes) { + buildRenderListRecursive(model, + rootNode, matrix_identity_float4x4, scene.ambientLight); + } + + NSMutableArray *renderList = [NSMutableArray arrayWithArray:_opaqueRenderItems]; + [renderList addObjectsFromArray:_transparentRenderItems]; + + drawRenderList(renderList, renderEncoder); + + NSArray *copiedDeferredReusableBuffers = [_deferredReusableBuffers copy]; + [commandBuffer addCompletedHandler:^(id commandBuffer) { + dispatch_async(dispatch_get_main_queue(), ^{ + for (id buffer in copiedDeferredReusableBuffers) { + enqueueReusableBuffer(buffer); + } + }); + }]; + + [_opaqueRenderItems removeAllObjects]; + [_transparentRenderItems removeAllObjects]; + [_currentLightNodes removeAllObjects]; + [_deferredReusableBuffers removeAllObjects]; +} + +void MetalRenderer::buildLightListRecursive(GLTFNode *node) { + if (node.light != nil) { + [_currentLightNodes addObject:node]; + } + + for (GLTFNode *childNode in node.children) { + buildLightListRecursive(childNode); + } +} + + +void MetalRenderer::buildRenderListRecursive(std::shared_ptr model, + GLTFNode *node, + simd_float4x4 modelMatrix, + GLTFKHRLight *defaultAmbientLight) { + modelMatrix = matrix_multiply(modelMatrix, node.localTransform); + + GLTFMesh *mesh = node.mesh; + if (mesh) { + for (GLTFSubmesh *submesh in mesh.submeshes) { + GLTFMaterial *material = submesh.material; + + simd_float3x3 viewAffine = simd_inverse(GLTFMatrixUpperLeft3x3(model->_modelViewMatrix)); + simd_float3 cameraPos = model->_modelViewMatrix.columns[3].xyz; + simd_float3 cameraWorldPos = matrix_multiply(viewAffine, -cameraPos); + + VertexUniforms vertexUniforms; + vertexUniforms.modelMatrix = modelMatrix; + vertexUniforms.modelViewProjectionMatrix = matrix_multiply(matrix_multiply(_projectionMatrix, model->_modelViewMatrix), modelMatrix); + vertexUniforms.normalMatrix = GLTFNormalMatrixFromModelMatrix(modelMatrix); + + FragmentUniforms fragmentUniforms = { 0 }; + fragmentUniforms.normalScale = material.normalTextureScale; + fragmentUniforms.emissiveFactor = material.emissiveFactor; + fragmentUniforms.occlusionStrength = material.occlusionStrength; + fragmentUniforms.metallicRoughnessValues = (simd_float2){ material.metalnessFactor, material.roughnessFactor }; + fragmentUniforms.baseColorFactor = material.baseColorFactor; + fragmentUniforms.camera = cameraWorldPos; + fragmentUniforms.alphaCutoff = material.alphaCutoff; + fragmentUniforms.envIntensity = 2; // self.lightingEnvironment.intensity; + + if (material.baseColorTexture != nil) { + fragmentUniforms.textureMatrices[GLTFTextureBindIndexBaseColor] = GLTFTextureMatrixFromTransform(material.baseColorTexture.transform); + } + if (material.normalTexture != nil) { + fragmentUniforms.textureMatrices[GLTFTextureBindIndexNormal] = GLTFTextureMatrixFromTransform(material.normalTexture.transform); + } + if (material.metallicRoughnessTexture != nil) { + fragmentUniforms.textureMatrices[GLTFTextureBindIndexMetallicRoughness] = GLTFTextureMatrixFromTransform(material.metallicRoughnessTexture.transform); + } + if (material.occlusionTexture != nil) { + fragmentUniforms.textureMatrices[GLTFTextureBindIndexOcclusion] = GLTFTextureMatrixFromTransform(material.occlusionTexture.transform); + } + if (material.emissiveTexture != nil) { + fragmentUniforms.textureMatrices[GLTFTextureBindIndexEmissive] = GLTFTextureMatrixFromTransform(material.emissiveTexture.transform); + } + + if (defaultAmbientLight != nil) { + fragmentUniforms.ambientLight.color = defaultAmbientLight.color; // self.ambientLight.color; + fragmentUniforms.ambientLight.intensity = defaultAmbientLight.intensity; //self.ambientLight.intensity; + } + + // TODO: Make this more efficient. Iterating the light list for every submesh is pretty silly. + for (int lightIndex = 0; lightIndex < _currentLightNodes.count; ++lightIndex) { + GLTFNode *lightNode = _currentLightNodes[lightIndex]; + GLTFKHRLight *light = lightNode.light; + if (light.type == GLTFKHRLightTypeDirectional) { + fragmentUniforms.lights[lightIndex].position = lightNode.globalTransform.columns[2]; + } else { + fragmentUniforms.lights[lightIndex].position = lightNode.globalTransform.columns[3]; + } + fragmentUniforms.lights[lightIndex].color = light.color; + fragmentUniforms.lights[lightIndex].intensity = light.intensity; + fragmentUniforms.lights[lightIndex].range = light.range; + if (light.type == GLTFKHRLightTypeSpot) { + fragmentUniforms.lights[lightIndex].innerConeAngle = light.innerConeAngle; + fragmentUniforms.lights[lightIndex].outerConeAngle = light.outerConeAngle; + } else { + fragmentUniforms.lights[lightIndex].innerConeAngle = 0; + fragmentUniforms.lights[lightIndex].outerConeAngle = M_PI; + } + fragmentUniforms.lights[lightIndex].spotDirection = lightNode.globalTransform.columns[2]; + } + + GLTFMTLRenderItem *item = [GLTFMTLRenderItem new]; + item.label = [NSString stringWithFormat:@"%@ - %@", node.name ?: @"Unnamed node", submesh.name ?: @"Unnamed primitive"]; + item.node = node; + item.submesh = submesh; + item.vertexUniforms = vertexUniforms; + item.fragmentUniforms = fragmentUniforms; + + if (submesh.material.alphaMode == GLTFAlphaModeBlend) { + [_transparentRenderItems addObject:item]; + } else { + [_opaqueRenderItems addObject:item]; + } + } + } + + for (GLTFNode *childNode in node.children) { + buildRenderListRecursive(model, + childNode, modelMatrix, defaultAmbientLight); + // [self buildRenderListRecursive:childNode modelMatrix:modelMatrix]; + } +} + +void MetalRenderer::drawRenderList(NSArray *renderList, + id renderEncoder) { + for (GLTFMTLRenderItem *item in renderList) { + GLTFNode *node = item.node; + GLTFSubmesh *submesh = item.submesh; + GLTFMaterial *material = submesh.material; + + [renderEncoder pushDebugGroup:[NSString stringWithFormat:@"%@", item.label]]; + + id renderPipelineState = renderPipelineStateForSubmesh(submesh); + + [renderEncoder setRenderPipelineState:renderPipelineState]; + + [renderEncoder setFrontFacingWinding:MTLWindingCounterClockwise]; + + NSDictionary *accessorsForAttributes = submesh.accessorsForAttributes; + + GLTFAccessor *indexAccessor = submesh.indexAccessor; + BOOL useIndexBuffer = (indexAccessor != nil); + + // TODO: Check primitive type for unsupported types (tri fan, line loop), and modify draw calls as appropriate + MTLPrimitiveType primitiveType = GLTFMTLPrimitiveTypeForPrimitiveType(submesh.primitiveType); + + bindTexturesForMaterial(material, renderEncoder); + + VertexUniforms vertexUniforms = item.vertexUniforms; + [renderEncoder setVertexBytes:&vertexUniforms length:sizeof(vertexUniforms) atIndex:GLTFVertexDescriptorMaxAttributeCount + 0]; + + if (node.skin != nil && node.skin.jointNodes != nil && node.skin.jointNodes.count > 0) { + id jointBuffer = dequeueReusableBufferOfLength(node.skin.jointNodes.count * sizeof(simd_float4x4)); + computeJointsForSubmesh(submesh, node, jointBuffer); + [renderEncoder setVertexBuffer:jointBuffer offset:0 atIndex:GLTFVertexDescriptorMaxAttributeCount + 1]; + [_deferredReusableBuffers addObject:jointBuffer]; + } + + FragmentUniforms fragmentUniforms = item.fragmentUniforms; + [renderEncoder setFragmentBytes:&fragmentUniforms length: sizeof(fragmentUniforms) atIndex: 0]; + + GLTFVertexDescriptor *vertexDescriptor = submesh.vertexDescriptor; + for (int i = 0; i < GLTFVertexDescriptorMaxAttributeCount; ++i) { + NSString *semantic = vertexDescriptor.attributes[i].semantic; + if (semantic == nil) { continue; } + GLTFAccessor *accessor = submesh.accessorsForAttributes[semantic]; + + [renderEncoder setVertexBuffer:((GLTFMTLBuffer *)accessor.bufferView.buffer).buffer + offset:accessor.offset + accessor.bufferView.offset + atIndex:i]; + } + + if (material.alphaMode == GLTFAlphaModeBlend){ + id depthStencilState = depthStencilStateForDepthWriteEnabled(YES, YES, MTLCompareFunctionLess); + [renderEncoder setDepthStencilState:depthStencilState]; + } else { + id depthStencilState = depthStencilStateForDepthWriteEnabled(YES,YES,MTLCompareFunctionLess); + [renderEncoder setDepthStencilState:depthStencilState]; + } + + if (material.isDoubleSided) { + [renderEncoder setCullMode:MTLCullModeNone]; + } else { + [renderEncoder setCullMode:MTLCullModeBack]; + } + + if (useIndexBuffer) { + GLTFMTLBuffer *indexBuffer = (GLTFMTLBuffer *)indexAccessor.bufferView.buffer; + + MTLIndexType indexType = (indexAccessor.componentType == GLTFDataTypeUShort) ? MTLIndexTypeUInt16 : MTLIndexTypeUInt32; + + [renderEncoder drawIndexedPrimitives:primitiveType + indexCount:indexAccessor.count + indexType:indexType + indexBuffer:[indexBuffer buffer] + indexBufferOffset:indexAccessor.offset + indexAccessor.bufferView.offset]; + } else { + GLTFAccessor *positionAccessor = accessorsForAttributes[GLTFAttributeSemanticPosition]; + [renderEncoder drawPrimitives:primitiveType vertexStart:0 vertexCount:positionAccessor.count]; + } + + [renderEncoder popDebugGroup]; + } +} + + +void MetalRenderer::bindTexturesForMaterial(GLTFMaterial *material, + id renderEncoder) { + if (material.baseColorTexture != nil) { + id texture = textureForImage(material.baseColorTexture.texture.image, true); + id sampler = samplerStateForSampler(material.baseColorTexture.texture.sampler); + [renderEncoder setFragmentTexture:texture atIndex:GLTFTextureBindIndexBaseColor]; + [renderEncoder setFragmentSamplerState:sampler atIndex:GLTFTextureBindIndexBaseColor]; + } + + if (material.normalTexture != nil) { + id texture = textureForImage(material.normalTexture.texture.image, false); + id sampler = samplerStateForSampler(material.normalTexture.texture.sampler); + [renderEncoder setFragmentTexture:texture atIndex:GLTFTextureBindIndexNormal]; + [renderEncoder setFragmentSamplerState:sampler atIndex:GLTFTextureBindIndexNormal]; + } + + if (material.metallicRoughnessTexture != nil) { + id texture = textureForImage(material.metallicRoughnessTexture.texture.image, false); + id sampler = samplerStateForSampler(material.metallicRoughnessTexture.texture.sampler); + [renderEncoder setFragmentTexture:texture atIndex:GLTFTextureBindIndexMetallicRoughness]; + [renderEncoder setFragmentSamplerState:sampler atIndex:GLTFTextureBindIndexMetallicRoughness]; + } + + if (material.emissiveTexture != nil) { + id texture = textureForImage(material.emissiveTexture.texture.image, true); + id sampler = samplerStateForSampler(material.emissiveTexture.texture.sampler); + [renderEncoder setFragmentTexture:texture atIndex:GLTFTextureBindIndexEmissive]; + [renderEncoder setFragmentSamplerState:sampler atIndex:GLTFTextureBindIndexEmissive]; + } + + if (material.occlusionTexture != nil) { + id texture = textureForImage(material.occlusionTexture.texture.image, false); + id sampler = samplerStateForSampler(material.occlusionTexture.texture.sampler); + [renderEncoder setFragmentTexture:texture atIndex:GLTFTextureBindIndexOcclusion]; + [renderEncoder setFragmentSamplerState:sampler atIndex:GLTFTextureBindIndexOcclusion]; + } + +// if (self.lightingEnvironment) { +// [renderEncoder setFragmentTexture:self.lightingEnvironment.specularCube atIndex:GLTFTextureBindIndexSpecularEnvironment]; +// [renderEncoder setFragmentTexture:self.lightingEnvironment.diffuseCube atIndex:GLTFTextureBindIndexDiffuseEnvironment]; +// [renderEncoder setFragmentTexture:self.lightingEnvironment.brdfLUT atIndex:GLTFTextureBindIndexBRDFLookup]; +// } +} + +id MetalRenderer::dequeueReusableBufferOfLength(size_t length) { + int indexToReuse = -1; + for (int i = 0; i < _bufferPool.count; ++i) { + if (_bufferPool[i].length >= length) { + indexToReuse = i; + } + } + + if (indexToReuse >= 0) { + id buffer = _bufferPool[indexToReuse]; + [_bufferPool removeObjectAtIndex:indexToReuse]; + return buffer; + } else { + return [_metalDevice newBufferWithLength:length options:MTLResourceStorageModeShared]; + } +} + +void MetalRenderer::computeJointsForSubmesh(GLTFSubmesh *submesh, + GLTFNode *node, + id jointBuffer) { + GLTFAccessor *jointsAccessor = submesh.accessorsForAttributes[GLTFAttributeSemanticJoints0]; + GLTFSkin *skin = node.skin; + GLTFAccessor *inverseBindingAccessor = node.skin.inverseBindMatricesAccessor; + + if (jointsAccessor != nil && inverseBindingAccessor != nil) { + NSInteger jointCount = skin.jointNodes.count; + simd_float4x4 *jointMatrices = (simd_float4x4 *)jointBuffer.contents; + simd_float4x4 *inverseBindMatrices = (simd_float4x4 *)((char *)inverseBindingAccessor.bufferView.buffer.contents + inverseBindingAccessor.bufferView.offset + inverseBindingAccessor.offset); + for (NSInteger i = 0; i < jointCount; ++i) { + GLTFNode *joint = skin.jointNodes[i]; + simd_float4x4 inverseBindMatrix = inverseBindMatrices[i]; + jointMatrices[i] = matrix_multiply(matrix_invert(node.globalTransform), matrix_multiply(joint.globalTransform, inverseBindMatrix)); + } + } +} + +id MetalRenderer::depthStencilStateForDepthWriteEnabled(bool depthWriteEnabled, + bool depthTestEnabled, + MTLCompareFunction compareFunction) { + + NSInteger depthWriteBit = depthWriteEnabled ? 1 : 0; + NSInteger depthTestBit = depthTestEnabled ? 1 : 0; + + NSInteger hash = (compareFunction << 2) | (depthWriteBit << 1) | depthTestBit; + + id depthStencilState = _depthStencilStateMap[@(hash)]; + if (depthStencilState) { + return depthStencilState; + } + + MTLDepthStencilDescriptor *depthDescriptor = [MTLDepthStencilDescriptor new]; + depthDescriptor.depthCompareFunction = depthTestEnabled ? compareFunction : MTLCompareFunctionAlways; + depthDescriptor.depthWriteEnabled = depthWriteEnabled; + depthStencilState = [_metalDevice newDepthStencilStateWithDescriptor:depthDescriptor]; + + _depthStencilStateMap[@(hash)] = depthStencilState; + + return depthStencilState; +} + + +id MetalRenderer::textureForImage(GLTFImage *image, + bool sRGB) { +// NSParameterAssert(image != nil); + + id texture = _texturesForImageIdentifiers[image.identifier]; + + if (texture) { + return texture; + } + + NSDictionary *options = @{ GLTFMTLTextureLoaderOptionGenerateMipmaps : @YES, + GLTFMTLTextureLoaderOptionSRGB : @(sRGB) + }; + + NSError *error = nil; + if (image.imageData != nil) { + texture = [_textureLoader newTextureWithData:image.imageData options:options error:&error]; + texture.label = image.name; + } else if (image.url != nil) { + texture = [_textureLoader newTextureWithContentsOfURL:image.url options:options error:&error]; + texture.label = image.name ?: image.url.lastPathComponent; + } else if (image.bufferView != nil) { + GLTFBufferView *bufferView = image.bufferView; + NSData *data = [NSData dataWithBytesNoCopy:(char *)bufferView.buffer.contents + bufferView.offset length:bufferView.length freeWhenDone:NO]; + texture = [_textureLoader newTextureWithData:data options:options error:&error]; + texture.label = image.name; + } + + if (!texture) { + NSLog(@"Error occurred while loading texture: %@", error); + } else { + _texturesForImageIdentifiers[image.identifier] = texture; + } + + return texture; +} + +id MetalRenderer::samplerStateForSampler(GLTFTextureSampler *sampler) { +// NSParameterAssert(sampler != nil); + + id samplerState = _samplerStatesForSamplers[sampler]; + if (samplerState == nil) { + MTLSamplerDescriptor *descriptor = [MTLSamplerDescriptor new]; + descriptor.magFilter = GLTFMTLSamplerMinMagFilterForSamplingFilter(sampler.magFilter); + descriptor.minFilter = GLTFMTLSamplerMinMagFilterForSamplingFilter(sampler.minFilter); + descriptor.mipFilter = GLTFMTLSamplerMipFilterForSamplingFilter(sampler.minFilter); + descriptor.sAddressMode = GLTFMTLSamplerAddressModeForSamplerAddressMode(sampler.sAddressMode); + descriptor.tAddressMode = GLTFMTLSamplerAddressModeForSamplerAddressMode(sampler.tAddressMode); + descriptor.normalizedCoordinates = YES; + samplerState = [_metalDevice newSamplerStateWithDescriptor:descriptor]; + _samplerStatesForSamplers[sampler] = samplerState; + } + return samplerState; +} + diff --git a/platform/darwin/src/gltf/MetalRenderer.hpp b/platform/darwin/src/gltf/MetalRenderer.hpp new file mode 100644 index 000000000000..25aeeb160a39 --- /dev/null +++ b/platform/darwin/src/gltf/MetalRenderer.hpp @@ -0,0 +1,229 @@ +// +// GLTFRenderer.hpp +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/19/24. +// + +#ifndef MetalRenderer_hpp +#define MetalRenderer_hpp + +#include +#include +#include "GLTFRenderer.hpp" +#import "gltfkit/GLTFAsset.h" +#import "gltfkit//GLTFNode.h" +#import "gltfkit/GLTFImage.h" +#import "gltfkit/GLTFTextureSampler.h" +#include "GLTFMTLRenderItem.h" +#import "gltfkit/GLTFMTLTextureLoader.h" +#include "GLTFManagerRenderingEnvironmentMetal.hpp" +#include +#include +#include + +namespace maplibre { namespace gltf { + + class GLTFRenderModel { + public: + // The model metadata + std::shared_ptr _gltfModel = nullptr; + + // The loaded model + GLTFAsset *_asset = nil; + + // Rendering variables + // Translation Vector is the translation of the model from the + simd_float3 _translationVector; // This might need to be a doubles vector + double _rotationDeg = 0; // Rotation around the zAxis (if applicable) + double _scaling = 1; // Scaling from + + // This is the model matrix (rotation, scaling and transformation applied) + simd_float4x4 _modelMatrix; + + // This is the model matrix combined with the camera's view matrix + simd_float4x4 _modelViewMatrix; + + // We probably won't need this in the final thing. Used to normalize the model to the + // viewport size + simd_float4x4 _regularizationMatrix; + + // + GLTFBoundingSphere _boundingSphere; + + }; + + + + // + class MetalRenderer : public GLTFRenderer { + public: + // Constructor + MetalRenderer(); + ~MetalRenderer(); + + void setMetalDevice(id device); + + // Set the drawable size + void setDrawableSize(int width, int height) override; + + // Set the current drawable (used for a metal view) + //void setCurrentDrawable(id drawable); + + // Set the output render pass descriptor (this is for outputting to a metal view) + //void setCurrentOutputRenderPassDescriptor(MTLRenderPassDescriptor *renderPassDescriptor); + + // Update any animations + void update(float timeSinceLastDraw) override; + + // Render + void render() override; + + // Load a model + void loadGLTFModel(std::shared_ptr model) override; + + // Set the rendering environemnt variables + void setRenderingEnvironemnt(std::shared_ptr renderingEnvironment) override; + + private: + // Rendering environment variables + simd_float4x4 _projectionMatrix; + int _sampleCount = 1; + MTLPixelFormat _colorPixelFormat; + MTLPixelFormat _depthStencilPixelFormat; + simd_int2 _drawableSize; + double _globalTime = 0; + int _maxInflightFrames = 3; + + // Current external environment variables + std::shared_ptr _metalRenderingEnvironment = nullptr; + + //id _currentDrawable = nullptr; + //MTLRenderPassDescriptor *_currentOutputRenderPassDescriptor = nullptr; + + dispatch_semaphore_t _frameBoundarySemaphore; + + void encodeMainPass(id commandBuffer); + void encodeBloomPasses(id commandBuffer); + void encodeTonemappingPass(id commandBuffer); + void drawFullscreenPassWithPipeline(id renderPipelineState, + id renderCommandEncoder, + id sourceTexture); + void signalFrameCompletion(); + MTLRenderPassDescriptor* newRenderPassDescriptor(); + + private: + // Per-frame + void computeTransforms(std::shared_ptr model); + + protected: + void loadBloomPipelines() override; + void loadTonemapPipeline() override; + void updateFramebufferSize() override; // Updates the framebuffers based on size + + private: + // Set by the environment + id _metalDevice = nullptr; + + // Created for rendering the model + id _internalMetalCommandQueue = nullptr; + id _metalLibrary = nullptr; + + + // Setup the rendering environment. Called after device is set + void setupMetal(); + + // Bloom + id _bloomThresholdPipelineState = nullptr; + id _blurHorizontalPipelineState = nullptr; + id _blurVerticalPipelineState = nullptr; + id _additiveBlendPipelineState = nullptr; + + // Tonemap + id _tonemapPipelineState = nullptr; + + // Render targets + id _multisampleColorTexture = nullptr; + id _colorTexture = nullptr; + id _depthStencilTexture = nullptr; + id _bloomTextureA = nullptr; + id _bloomTextureB = nullptr; + + public: + // Encapsulated in GLTFRenderer+GLTFAsset + void setGLTFAsset(GLTFAsset *asset, std::shared_ptr model); + + // + void addGLTFAsset(GLTFAsset *asset, std::shared_ptr model); + + // + id _bufferAllocator; + + private: + std::shared_ptr createRenderModel(GLTFAsset *asset, std::shared_ptr model); + + std::vector> _models; +// GLTFAsset *_asset = nil; +// NSMutableArray *_assets = nil; + + // + void computeRegularizationMatrix(std::shared_ptr model); + void addDefaultLights(std::shared_ptr model); + + void renderScene(std::shared_ptr model, + GLTFScene *scene, + id commandBuffer, + id renderEncoder); + + void buildLightListRecursive(GLTFNode *node); + + void buildRenderListRecursive(std::shared_ptr model, + GLTFNode *node, + simd_float4x4 modelMatrix, + GLTFKHRLight *defaultAmbientLight); + + void drawRenderList(NSArray *renderList, + id renderEncoder); + + id renderPipelineStateForSubmesh(GLTFSubmesh *submesh); + + void bindTexturesForMaterial(GLTFMaterial *material, + id renderEncoder); + + id dequeueReusableBufferOfLength(size_t length); + + void computeJointsForSubmesh(GLTFSubmesh *submesh, + GLTFNode *node, + id jointBuffer); + + id depthStencilStateForDepthWriteEnabled(bool depthWriteEnabled, + bool depthTestEnabled, + MTLCompareFunction compareFunction); + + id textureForImage(GLTFImage *image, bool sRGB); + id samplerStateForSampler(GLTFTextureSampler *sampler); + + NSMutableArray *_opaqueRenderItems; + NSMutableArray *_transparentRenderItems; + NSMutableArray *_currentLightNodes; + NSMutableArray> *_deferredReusableBuffers; + NSMutableArray> *_bufferPool; + NSMutableDictionary> *_depthStencilStateMap; + + NSMutableDictionary> *_pipelineStatesForSubmeshes; + NSMutableDictionary> *_texturesForImageIdentifiers; + GLTFMTLTextureLoader *_textureLoader; + NSMutableDictionary> *_samplerStatesForSamplers; + + void enqueueReusableBuffer(id buffer); + + + // This is the depth stencil descriptor for overlaying the + id _fullscreenTransfterDepthStencilState = nullptr; + + + }; + +}} + +#endif /* MetalRenderer_hpp */ diff --git a/platform/darwin/src/gltf/MetalRenderer.mm b/platform/darwin/src/gltf/MetalRenderer.mm new file mode 100644 index 000000000000..9ca0e2563d86 --- /dev/null +++ b/platform/darwin/src/gltf/MetalRenderer.mm @@ -0,0 +1,565 @@ +// +// GLTFRenderer.cpp +// GLTFTestRendering +// +// Created by Malcolm Toon on 11/19/24. +// + +#include "MetalRenderer.hpp" +#include +#include + +#import "GLTFModelLoader.h" +#import "gltfkit/GLTFAnimation.h" +#import "gltfkit/GLTFMTLShaderBuilder.h" +#import "gltfkit/GLTFMTLBufferAllocator.h" + + +using namespace maplibre::gltf; + +MetalRenderer::MetalRenderer() { + GLTFRenderer(); +} + +MetalRenderer::~MetalRenderer() { + std::cout << "Destructor\n"; +} + + +void MetalRenderer::setMetalDevice(id device) { + if (_metalDevice == device) { + return; + } + + _metalDevice = device; + setupMetal(); +} + +// Set the drawable size +void MetalRenderer::setDrawableSize(int width, int height) { + if ((_drawableSize.x == width) && (_drawableSize.y == height)) { + return; + } + _drawableSize = {width, height}; + updateFramebufferSize(); +} + +// Set the current drawable +//void MetalRenderer::setCurrentDrawable(id drawable) { +// _currentDrawable = drawable; +//} + +// Set the output render pass descriptor (this is for outputting to a metal view) +//void MetalRenderer::setCurrentOutputRenderPassDescriptor(MTLRenderPassDescriptor *renderPassDescriptor) { +// _currentOutputRenderPassDescriptor = renderPassDescriptor; +//} + + + +// Update any animations +void MetalRenderer::update(float timeSinceLastDraw) { + + // Update the global time + _globalTime += timeSinceLastDraw; + + // If we don't have an asset, then bail + if (_models.size() == 0) { + return; + } + + double maxAnimDuration = 0; + for (auto m: _models) { + for (GLTFAnimation *animation in m->_asset.animations) { + for (GLTFAnimationChannel *channel in animation.channels) { + if (channel.duration > maxAnimDuration) { + maxAnimDuration = channel.duration; + } + } + } + } + + double animTime = fmod(_globalTime, maxAnimDuration); + for (auto m: _models) { + for (GLTFAnimation *animation in m->_asset.animations) { + [animation runAtTime:animTime]; + } + } + + _camera->updateWithTimestep(timeSinceLastDraw); + for (auto m: _models) { + computeTransforms(m); + } + +} + +// Render +void MetalRenderer::render() { + + // Compute the projection matrix + float aspectRatio = (float)_drawableSize.x / (float)_drawableSize.y; + simd_float4x4 aspectCorrection = GLTFMatrixFromScale((simd_float3){ 1 / aspectRatio, 1, 1 }); + _projectionMatrix = simd_mul(aspectCorrection, _camera->projectionMatrix()); + + + simd_float4x4 tempMatrix = _projectionMatrix; + + // Set the projection matrix from the incoming environment + _projectionMatrix = _metalRenderingEnvironment->_currentProjectionMatrix; + + // Remove the translation + _projectionMatrix.columns[3][0] = tempMatrix.columns[3][0]; + _projectionMatrix.columns[3][1] = tempMatrix.columns[3][1]; + _projectionMatrix.columns[3][2] = tempMatrix.columns[3][2]; + _projectionMatrix.columns[3][3] = tempMatrix.columns[3][3]; + + + // Moved this to the camera projectionMatrix +// double fov = 0.6435011087932844; +// _projectionMatrix = GLTFPerspectiveProjectionMatrixAspectFovRH(fov, aspectRatio, 0.0001, 2); + + + + // The above projection matrix is a perspective matrix. I think we need an ortho matrix + float w = ((float)_drawableSize.x) / 2.0; + float h = ((float)_drawableSize.y) / 2.0; + float aspect = w/h; + _projectionMatrix = GLTFOrthoProjectionMatrix(-w,w,-h*aspect,h*aspect,0.001,250); + _projectionMatrix = GLTFOrthoProjectionMatrix(-1*aspect,1*aspect,-1,1,10,-10); + + + // ANother projection matrix test + float fov = _renderingEnvironment->_currentFOVDEG * DEG_RAD; // 0.6435011087932844; // Constant that i found in ML + simd_float4x4 matrix = GLTFPerspectiveProjectionMatrixAspectFovRH(fov, aspect, 0.01, 250); + _projectionMatrix = matrix; + + + + + + + // Check to see if we're drawing directly or using another command buffer + bool _existingCommandBuffer = _metalRenderingEnvironment->_currentCommandBuffer != nullptr; + + id currentDrawable = nil; + + // Internal command buffer + id internalCommandBuffer = [_internalMetalCommandQueue commandBuffer]; +// +// if (_existingCommandBuffer) { +// commandBuffer = _metalRenderingEnvironment->_currentCommandBuffer; +// } else { +// // Create a command buffer and we're going to be expected to draw to the output +// commandBuffer = [_internalMetalCommandQueue commandBuffer]; +// currentDrawable = _metalRenderingEnvironment->_currentDrawable; +// } +// + encodeMainPass(internalCommandBuffer); + if (_useBloomPass) { + encodeBloomPasses(internalCommandBuffer); + } + +// [internalCommandBuffer addCompletedHandler:^(id buffer) { +// dispatch_async(dispatch_get_main_queue(), ^{ +// signalFrameCompletion(); +// }); +// }]; + + [internalCommandBuffer commit]; + + // This will write out the tone mapping + //id externalBuffer = _metalRenderingEnvironment->_currentCommandBuffer; + //encodeTonemappingPass(externalBuffer); + + // TESTING + [_metalRenderingEnvironment->_currentCommandEncoder pushDebugGroup:@"Post-process (Tonemapping)"]; + [_metalRenderingEnvironment->_currentCommandEncoder setDepthStencilState:_fullscreenTransfterDepthStencilState]; + drawFullscreenPassWithPipeline(_tonemapPipelineState,_metalRenderingEnvironment->_currentCommandEncoder,_colorTexture); + [_metalRenderingEnvironment->_currentCommandEncoder popDebugGroup]; + // [_metalRenderingEnvironment->_currentCommandEncoder endEncoding]; + + + +// if (!_existingCommandBuffer) { +// [commandBuffer presentDrawable:currentDrawable]; +// } + + + +} + +// Load a model +void MetalRenderer::loadGLTFModel(std::shared_ptr model) { + + GLTFModelLoader *modelLoader = [[GLTFModelLoader alloc] init]; + NSURL *u = [NSURL URLWithString:[NSString stringWithCString:model->_modelURL.c_str()]]; + [modelLoader loadURL:u + withCompletionHandler:^(GLTFAsset * _Nonnull asset) { + addGLTFAsset(asset, model); + } + bufferAllocator:_bufferAllocator]; + +} + +// Set the rendering environemnt variables +void MetalRenderer::setRenderingEnvironemnt(std::shared_ptr renderingEnvironment) { + GLTFRenderer::setRenderingEnvironemnt(renderingEnvironment); + + _metalRenderingEnvironment = std::static_pointer_cast(renderingEnvironment); + +} + + +// RENDERING +void MetalRenderer::encodeMainPass(id commandBuffer) { + + MTLRenderPassDescriptor *pass = newRenderPassDescriptor(); + id renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:pass]; + + /* + if (self.lightingEnvironment != nil) { + [renderEncoder pushDebugGroup:@"Draw Backdrop"]; + [self drawSkyboxWithCommandEncoder:renderEncoder]; + [renderEncoder popDebugGroup]; + } + */ + + /* + long timedOut = dispatch_semaphore_wait(_frameBoundarySemaphore, dispatch_time(0, 10 * NSEC_PER_SEC)); + if (timedOut) { + NSLog(@"Failed to receive frame boundary signal before timing out; calling signalFrameCompletion manually. " + "Remember to call signalFrameCompletion on GLTFMTLRenderer from the completion handler of the command buffer " + "into which you encode the work for drawing assets"); + signalFrameCompletion(); + } +*/ + + for (auto m: _models) { + [renderEncoder pushDebugGroup:@"Draw glTF Scene"]; + renderScene(m, m->_asset.defaultScene, commandBuffer, renderEncoder); + // [self.renderer renderScene:self.asset.defaultScene + // commandBuffer:commandBuffer + // commandEncoder:renderEncoder]; + [renderEncoder popDebugGroup]; + } + + [renderEncoder endEncoding]; + +} + +void MetalRenderer::encodeBloomPasses(id commandBuffer) { + + MTLRenderPassDescriptor *pass = [MTLRenderPassDescriptor renderPassDescriptor]; + pass.colorAttachments[0].texture = _bloomTextureA; + pass.colorAttachments[0].loadAction = MTLLoadActionDontCare; + pass.colorAttachments[0].storeAction = MTLStoreActionStore; + + id renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:pass]; + [renderEncoder pushDebugGroup:@"Post-process (Bloom threshold)"]; + drawFullscreenPassWithPipeline(_bloomThresholdPipelineState,renderEncoder,_colorTexture); + [renderEncoder popDebugGroup]; + [renderEncoder endEncoding]; + + pass = [MTLRenderPassDescriptor renderPassDescriptor]; + pass.colorAttachments[0].texture = _bloomTextureB; + pass.colorAttachments[0].loadAction = MTLLoadActionDontCare; + pass.colorAttachments[0].storeAction = MTLStoreActionStore; + renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:pass]; + [renderEncoder pushDebugGroup:@"Post-process (Bloom blur - horizontal)"]; + drawFullscreenPassWithPipeline(_blurHorizontalPipelineState,renderEncoder,_bloomTextureA); + [renderEncoder popDebugGroup]; + [renderEncoder endEncoding]; + + pass = [MTLRenderPassDescriptor renderPassDescriptor]; + pass.colorAttachments[0].texture = _bloomTextureA; + pass.colorAttachments[0].loadAction = MTLLoadActionDontCare; + pass.colorAttachments[0].storeAction = MTLStoreActionStore; + renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:pass]; + [renderEncoder pushDebugGroup:@"Post-process (Bloom blur - vertical)"]; + drawFullscreenPassWithPipeline(_blurVerticalPipelineState,renderEncoder,_bloomTextureB); + [renderEncoder popDebugGroup]; + [renderEncoder endEncoding]; + + pass = [MTLRenderPassDescriptor renderPassDescriptor]; + pass.colorAttachments[0].texture = _colorTexture; + pass.colorAttachments[0].loadAction = MTLLoadActionLoad; + pass.colorAttachments[0].storeAction = MTLStoreActionStore; + + renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:pass]; + [renderEncoder pushDebugGroup:@"Post-process (Bloom combine)"]; + drawFullscreenPassWithPipeline(_additiveBlendPipelineState,renderEncoder,_bloomTextureA); + [renderEncoder popDebugGroup]; + [renderEncoder endEncoding]; +} + +void MetalRenderer::encodeTonemappingPass(id commandBuffer) { + + if (_metalRenderingEnvironment->_currentRenderPassDescriptor == nil) { + return; + } + + id renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:_metalRenderingEnvironment->_currentRenderPassDescriptor]; + [renderEncoder pushDebugGroup:@"Post-process (Tonemapping)"]; + drawFullscreenPassWithPipeline(_tonemapPipelineState,renderEncoder,_colorTexture); + [renderEncoder popDebugGroup]; + [renderEncoder endEncoding]; + + + +} + +void MetalRenderer::drawFullscreenPassWithPipeline(id renderPipelineState, + id renderCommandEncoder, + id sourceTexture) { + float triangleData[] = { + -1, 3, 0, -1, + -1, -1, 0, 1, + 3, -1, 2, 1 + }; + [renderCommandEncoder setRenderPipelineState:renderPipelineState]; + [renderCommandEncoder setFrontFacingWinding:MTLWindingCounterClockwise]; + [renderCommandEncoder setCullMode:MTLCullModeNone]; + [renderCommandEncoder setVertexBytes:triangleData length:sizeof(float) * 12 atIndex:0]; + [renderCommandEncoder setFragmentTexture:sourceTexture atIndex:0]; + [renderCommandEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:3]; +} + +void MetalRenderer::signalFrameCompletion() { + dispatch_semaphore_signal(_frameBoundarySemaphore); +} + + +MTLRenderPassDescriptor* MetalRenderer::newRenderPassDescriptor() { + MTLRenderPassDescriptor *pass = [MTLRenderPassDescriptor renderPassDescriptor]; + if (_sampleCount > 1) { + pass.colorAttachments[0].texture = _multisampleColorTexture; + pass.colorAttachments[0].resolveTexture = _colorTexture; + pass.colorAttachments[0].loadAction = MTLLoadActionClear; + pass.colorAttachments[0].storeAction = MTLStoreActionMultisampleResolve; + pass.colorAttachments[0].clearColor = MTLClearColorMake(1, 0, 0, 0); + } else { + pass.colorAttachments[0].texture = _colorTexture; + pass.colorAttachments[0].loadAction = MTLLoadActionClear; + pass.colorAttachments[0].storeAction = MTLStoreActionStore; + pass.colorAttachments[0].clearColor = MTLClearColorMake(1, 0, 0, 0); + + } + pass.depthAttachment.texture = _depthStencilTexture; + pass.depthAttachment.loadAction = MTLLoadActionClear; + pass.depthAttachment.storeAction = MTLStoreActionDontCare; + + return pass; +} + +/* + ------- ------- ----- ----------------------------------------------- + PRIVATE METHODS BELOW + ------- ------- ----- ----------------------------------------------- +*/ + + +void MetalRenderer::setupMetal() { + + _internalMetalCommandQueue = [_metalDevice newCommandQueue]; + _metalLibrary = [_metalDevice newDefaultLibrary]; + + //_viewMatrix = matrix_identity_float4x4; + _projectionMatrix = matrix_identity_float4x4; + _colorPixelFormat = MTLPixelFormatBGRA8Unorm; + _depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8; + _sampleCount = 1; + _drawableSize = {1, 1}; + + _frameBoundarySemaphore = dispatch_semaphore_create(_maxInflightFrames); + + loadBloomPipelines(); + loadTonemapPipeline(); + + _opaqueRenderItems = [NSMutableArray array]; + _transparentRenderItems = [NSMutableArray array]; + _currentLightNodes = [NSMutableArray array]; + _deferredReusableBuffers = [NSMutableArray array]; + _bufferPool = [NSMutableArray array]; + + _pipelineStatesForSubmeshes = [NSMutableDictionary dictionary]; + _depthStencilStateMap = [NSMutableDictionary dictionary]; + _texturesForImageIdentifiers = [NSMutableDictionary dictionary]; + _samplerStatesForSamplers = [NSMutableDictionary dictionary]; + + _textureLoader = [[GLTFMTLTextureLoader alloc] initWithDevice:_metalDevice]; + _bufferAllocator = [[GLTFMTLBufferAllocator alloc] initWithDevice:_metalDevice]; + //_assets = [NSMutableArray array]; + + + + + MTLDepthStencilDescriptor *fullscreenTransfterDepthStencilDescriptor = [[MTLDepthStencilDescriptor alloc] init]; + fullscreenTransfterDepthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways; // Or another value as needed + fullscreenTransfterDepthStencilDescriptor.depthWriteEnabled = NO; + _fullscreenTransfterDepthStencilState = [_metalDevice newDepthStencilStateWithDescriptor:fullscreenTransfterDepthStencilDescriptor]; + + + +} + +void MetalRenderer::updateFramebufferSize() { + + MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor new]; + textureDescriptor.width = _drawableSize.x; + textureDescriptor.height = _drawableSize.y; + textureDescriptor.depth = 1; + + textureDescriptor.textureType = _sampleCount > 1 ? MTLTextureType2DMultisample : MTLTextureType2D; + textureDescriptor.pixelFormat = _colorPixelFormat; + textureDescriptor.sampleCount = _sampleCount; + textureDescriptor.storageMode = MTLStorageModePrivate; + textureDescriptor.usage = MTLTextureUsageRenderTarget; + _multisampleColorTexture = [_metalDevice newTextureWithDescriptor:textureDescriptor]; + + textureDescriptor.textureType = MTLTextureType2D; + textureDescriptor.pixelFormat = _colorPixelFormat; + textureDescriptor.sampleCount = 1; + textureDescriptor.storageMode = MTLStorageModePrivate; + textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; + _colorTexture = [_metalDevice newTextureWithDescriptor:textureDescriptor]; + + textureDescriptor.textureType = _sampleCount > 1 ? MTLTextureType2DMultisample : MTLTextureType2D; + textureDescriptor.pixelFormat = _depthStencilPixelFormat; + textureDescriptor.sampleCount = _sampleCount; + textureDescriptor.storageMode = MTLStorageModePrivate; + textureDescriptor.usage = MTLTextureUsageRenderTarget; + _depthStencilTexture = [_metalDevice newTextureWithDescriptor:textureDescriptor]; + + textureDescriptor.width = _drawableSize.x / 2; + textureDescriptor.height = _drawableSize.y / 2; + textureDescriptor.textureType = MTLTextureType2D; + textureDescriptor.pixelFormat = _colorPixelFormat; + textureDescriptor.sampleCount = 1; + textureDescriptor.storageMode = MTLStorageModePrivate; + textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; + _bloomTextureA = [_metalDevice newTextureWithDescriptor:textureDescriptor]; + + textureDescriptor.width = _drawableSize.x / 2; + textureDescriptor.height = _drawableSize.y / 2; + textureDescriptor.textureType = MTLTextureType2D; + textureDescriptor.pixelFormat = _colorPixelFormat; + textureDescriptor.sampleCount = 1; + textureDescriptor.storageMode = MTLStorageModePrivate; + textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; + _bloomTextureB = [_metalDevice newTextureWithDescriptor:textureDescriptor]; + + //self.renderer.sampleCount = self.sampleCount; + + +} + + + + + + +void MetalRenderer::loadBloomPipelines() { + + NSError *error = nil; + MTLRenderPipelineDescriptor *descriptor = [MTLRenderPipelineDescriptor new]; + descriptor.vertexFunction = [_metalLibrary newFunctionWithName:@"quad_vertex_main"]; + descriptor.colorAttachments[0].pixelFormat = _colorPixelFormat; + descriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"bloom_threshold_fragment_main"]; + _bloomThresholdPipelineState = [_metalDevice newRenderPipelineStateWithDescriptor:descriptor error:&error]; + if (_bloomThresholdPipelineState == nil) { + NSLog(@"Error occurred when creating render pipeline state: %@", error); + } + + descriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"blur_horizontal7_fragment_main"]; + _blurHorizontalPipelineState = [_metalDevice newRenderPipelineStateWithDescriptor:descriptor error:&error]; + if (_blurHorizontalPipelineState == nil) { + NSLog(@"Error occurred when creating render pipeline state: %@", error); + } + + descriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"blur_vertical7_fragment_main"]; + _blurVerticalPipelineState = [_metalDevice newRenderPipelineStateWithDescriptor:descriptor error:&error]; + if (_blurVerticalPipelineState == nil) { + NSLog(@"Error occurred when creating render pipeline state: %@", error); + } + + descriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"additive_blend_fragment_main"]; + + // Original Values + descriptor.colorAttachments[0].blendingEnabled = YES; + descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; + descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd; + descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne; + descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne; + descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOne; + descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorZero; + + descriptor.colorAttachments[0].blendingEnabled = YES; + descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; + descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationMin; + descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne; + descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha; + descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOne; + descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorDestinationAlpha; + + + _additiveBlendPipelineState = [_metalDevice newRenderPipelineStateWithDescriptor:descriptor error:&error]; + if (_additiveBlendPipelineState == nil) { + NSLog(@"Error occurred when creating render pipeline state: %@", error); + } +} + +void MetalRenderer::loadTonemapPipeline() { + + NSError *error = nil; + MTLRenderPipelineDescriptor *descriptor = [MTLRenderPipelineDescriptor new]; + + + // MT: Added blending + descriptor.colorAttachments[0].blendingEnabled = YES; + descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; + descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd; + descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha; + descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha; + descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha; + descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha; + + + id vertexFunction = [_metalLibrary newFunctionWithName:@"quad_vertex_main"]; + + descriptor.vertexFunction = vertexFunction; + descriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"tonemap_fragment_main"]; + descriptor.sampleCount = _sampleCount; + descriptor.colorAttachments[0].pixelFormat = _colorPixelFormat; + + // TODO: This was hard coded to fix an issue whe moving to ML. Need to sort out + // how these params are set in ML and pass them into here + descriptor.stencilAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; + descriptor.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; + + + _tonemapPipelineState = [_metalDevice newRenderPipelineStateWithDescriptor:descriptor error:&error]; + if (_tonemapPipelineState == nil) { + NSLog(@"Error occurred when creating render pipeline state: %@", error); + } +} + +void MetalRenderer::enqueueReusableBuffer(id buffer) { + [_bufferPool addObject:buffer]; +} + +id MetalRenderer::renderPipelineStateForSubmesh(GLTFSubmesh *submesh) { + + id pipeline = _pipelineStatesForSubmeshes[submesh.identifier]; + + if (pipeline == nil) { + GLTFMTLShaderBuilder *shaderBuilder = [[GLTFMTLShaderBuilder alloc] init]; + pipeline = [shaderBuilder renderPipelineStateForSubmesh: submesh + // lightingEnvironment:self.lightingEnvironment + colorPixelFormat:_colorPixelFormat + depthStencilPixelFormat:_depthStencilPixelFormat + sampleCount:_sampleCount + device:_metalDevice]; + _pipelineStatesForSubmeshes[submesh.identifier] = pipeline; + } + + return pipeline; +} diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAccessor.h b/platform/darwin/src/gltf/gltfkit/GLTFAccessor.h new file mode 100644 index 000000000000..4414b8ab58fe --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFAccessor.h @@ -0,0 +1,40 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFObject.h" +#import "GLTFEnums.h" + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class GLTFBufferView; + +typedef struct { + float minValue[16]; + float maxValue[16]; +} GLTFValueRange; + +@interface GLTFAccessor : GLTFObject +@property (nonatomic, weak) GLTFBufferView *bufferView; +@property (nonatomic, assign) GLTFDataType componentType; +@property (nonatomic, assign) GLTFDataDimension dimension; +@property (nonatomic, assign) NSInteger offset; +@property (nonatomic, assign) NSInteger count; +@property (nonatomic, assign) GLTFValueRange valueRange; +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAccessor.m b/platform/darwin/src/gltf/gltfkit/GLTFAccessor.m new file mode 100644 index 000000000000..fdcc77e6c85c --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFAccessor.m @@ -0,0 +1,26 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFAccessor.h" + +@implementation GLTFAccessor + +- (NSString *)description { + return [NSString stringWithFormat:@"GLTFAccessor: count: %d, component type: %d, dimension: %d, offset: %d, view: %@", + (int)self.count, (int)self.componentType, (int)self.dimension, (int)self.offset, self.bufferView]; +} + +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAnimation.h b/platform/darwin/src/gltf/gltfkit/GLTFAnimation.h new file mode 100644 index 000000000000..b70ab091a024 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFAnimation.h @@ -0,0 +1,46 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFObject.h" +#import "GLTFEnums.h" + +NS_ASSUME_NONNULL_BEGIN + +@class GLTFNode, GLTFAccessor; + +@interface GLTFAnimation : GLTFObject +@property (nonatomic, copy) NSArray *channels; +@property (nonatomic, copy) NSDictionary *samplers; + +- (void)runAtTime:(NSTimeInterval)time; +@end + +@interface GLTFAnimationSampler : GLTFObject +@property (nonatomic, weak) GLTFAccessor *inputAccessor; +@property (nonatomic, weak) GLTFAccessor *outputAccessor; +@property (nonatomic, assign) GLTFInterpolationMode interpolationMode; +@end + +@interface GLTFAnimationChannel : NSObject +@property (nonatomic, weak) GLTFNode *targetNode; +@property (nonatomic, weak) NSString *targetPath; +@property (nonatomic, weak) GLTFAnimationSampler *sampler; +@property (nonatomic, readonly, assign) NSTimeInterval duration; +@property (nonatomic, readonly, assign) NSTimeInterval startTime; +@property (nonatomic, readonly, assign) NSTimeInterval endTime; +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAnimation.m b/platform/darwin/src/gltf/gltfkit/GLTFAnimation.m new file mode 100644 index 000000000000..7bde7e060135 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFAnimation.m @@ -0,0 +1,172 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFAnimation.h" +#import "GLTFAccessor.h" +#import "GLTFBufferView.h" +#import "GLTFBuffer.h" +#import "GLTFNode.h" + +@implementation GLTFAnimationSampler + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ interpolation: %d", super.description, (int)self.interpolationMode]; +} + +- (const void *)inputValues { + return [self.inputAccessor.bufferView.buffer contents] + self.inputAccessor.bufferView.offset + self.inputAccessor.offset; +} + +- (const void *)outputValues { + return [self.outputAccessor.bufferView.buffer contents] + self.outputAccessor.bufferView.offset + self.outputAccessor.offset; +} + +- (int)keyFrameCount { + return (int)self.inputAccessor.count; +} + +@end + +@implementation GLTFAnimationChannel + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ target: %@; path: %@; sampler: %@", super.description, self.targetNode, self.targetPath, self.sampler]; +} + +- (NSTimeInterval)startTime { + GLTFAnimationSampler *sampler = self.sampler; + const float *timeValues = sampler.inputValues; + float startTime = timeValues[0]; + return startTime; +} + +- (NSTimeInterval)endTime { + GLTFAnimationSampler *sampler = self.sampler; + const float *timeValues = sampler.inputValues; + int keyFrameCount = sampler.keyFrameCount; + float endTime = timeValues[keyFrameCount - 1]; + return endTime; +} + +- (NSTimeInterval)duration { + return self.endTime - self.startTime; +} + +@end + +@implementation GLTFAnimation + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ channels: %@", super.description, self.channels]; +} + +- (void)runAtTime:(NSTimeInterval)time { + for (GLTFAnimationChannel *channel in self.channels) { + GLTFNode *target = channel.targetNode; + NSString *path = channel.targetPath; + GLTFAnimationSampler *sampler = channel.sampler; + + int keyFrameCount = sampler.keyFrameCount; + + const float *timeValues = sampler.inputValues; + + float minTime = timeValues[0]; + float maxTime = timeValues[keyFrameCount - 1]; + + if (time < minTime || time > maxTime) { + continue; + } + + int previousKeyFrame = 0, nextKeyFrame = 1; + while (timeValues[nextKeyFrame] < time) { + ++previousKeyFrame; + ++nextKeyFrame; + } + + if (previousKeyFrame >= keyFrameCount) { + previousKeyFrame = 0; + } + + if (nextKeyFrame >= keyFrameCount) { + nextKeyFrame = 0; + } + + float frameTimeDelta = timeValues[nextKeyFrame] - timeValues[previousKeyFrame]; + float timeWithinFrame = time - timeValues[previousKeyFrame]; + float frameProgress = timeWithinFrame / frameTimeDelta; + + if ([path isEqualToString:@"rotation"]) { + if(sampler.outputAccessor.componentType != GLTFDataTypeFloat) { + static dispatch_once_t floatRotationsNonce; + dispatch_once(&floatRotationsNonce, ^{ + NSLog(@"WARNING: Only float accessors are supported for rotation animations. This will only be reported once."); + }); + } + const GLTFQuaternion *rotationValues = sampler.outputValues; + + GLTFQuaternion previousRotation = rotationValues[previousKeyFrame]; + GLTFQuaternion nextRotation = rotationValues[nextKeyFrame]; + GLTFQuaternion interpRotation = simd_slerp(previousRotation, nextRotation, frameProgress); + + target.rotationQuaternion = interpRotation; + } else if ([path isEqualToString:@"translation"]) { + const GLTFVector3 *translationValues = sampler.outputValues; + + GLTFVector3 previousTranslation = translationValues[previousKeyFrame]; + GLTFVector3 nextTranslation = translationValues[nextKeyFrame]; + + GLTFVector3 interpTranslation = (GLTFVector3) { + ((1 - frameProgress) * previousTranslation.x) + (frameProgress * nextTranslation.x), + ((1 - frameProgress) * previousTranslation.y) + (frameProgress * nextTranslation.y), + ((1 - frameProgress) * previousTranslation.z) + (frameProgress * nextTranslation.z) + }; + + target.translation = (simd_float3){ interpTranslation.x, interpTranslation.y, interpTranslation.z }; + } else if ([path isEqualToString:@"scale"]) { + const float *scaleValues = sampler.outputValues; + + float previousScale = scaleValues[previousKeyFrame]; + float nextScale = scaleValues[nextKeyFrame]; + + float interpScale = ((1 - frameProgress) * previousScale) + (frameProgress * nextScale); + + target.scale = (simd_float3)interpScale; + } else if ([path isEqualToString:@"weights"]) { + if(sampler.outputAccessor.componentType != GLTFDataTypeFloat) { + static dispatch_once_t floatWeightsNonce; + dispatch_once(&floatWeightsNonce, ^{ + NSLog(@"WARNING: Only scalar float accessors are supported for weight animations. This will only be reported once."); + }); + } + const float *weightValues = sampler.outputValues; + + long weightCount = sampler.outputAccessor.count / keyFrameCount; + + const float *previousWeights = weightValues + (previousKeyFrame * weightCount); + const float *nextWeights = weightValues + (nextKeyFrame * weightCount); + + NSMutableArray *interpWeights = [NSMutableArray array]; + for (int i = 0; i < weightCount; ++i) { + float interpWeight = ((1 - frameProgress) * previousWeights[i]) + (frameProgress * nextWeights[i]); + [interpWeights addObject:@(interpWeight)]; + } + + target.morphTargetWeights = [interpWeights copy]; + } + } +} + +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAsset.h b/platform/darwin/src/gltf/gltfkit/GLTFAsset.h new file mode 100644 index 000000000000..2f883a685bd1 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFAsset.h @@ -0,0 +1,66 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import + +#import "GLTFObject.h" +#import "GLTFEnums.h" + +NS_ASSUME_NONNULL_BEGIN + +@class GLTFAsset; +@class GLTFScene, GLTFCamera, GLTFAnimation; +@class GLTFKHRLight; +@protocol GLTFBufferAllocator; + +@protocol GLTFAssetLoadingDelegate +- (void)assetWithURL:(NSURL *)assetURL requiresContentsOfURL:(NSURL *)url completionHandler:(void (^)(NSData *_Nullable, NSError *_Nullable))completionHandler; +- (void)assetWithURL:(NSURL *)assetURL didFinishLoading:(GLTFAsset *)asset; +- (void)assetWithURL:(NSURL *)assetURL didFailToLoadWithError:(NSError *)error; +@end + +@interface GLTFAsset : NSObject + +@property (nonatomic, readonly, strong) NSArray *scenes; +@property (nonatomic, readonly) GLTFScene * _Nullable defaultScene; + +@property (nonatomic, readonly, strong) NSArray *animations; + +@property (nonatomic, readonly, strong) NSArray *lights; + +@property (nonatomic, readonly, strong) NSArray *cameras; + +@property (nonatomic, copy) NSString * _Nullable generator; +@property (nonatomic, copy) NSString * _Nullable copyright; +@property (nonatomic, copy) NSString * _Nullable formatVersion; + +@property (nonatomic, copy) NSArray *extensionsUsed; + +/// Load an asset asynchronously. The asset may either be a local asset or a remote asset; the provided +/// delegate will receive callbacks requesting the contents of remote URLs referenced by the asset. These +/// callbacks will occur on an arbitrary internal queue. ++ (void)loadAssetWithURL:(NSURL *)url bufferAllocator:(id)bufferAllocator delegate:(id)delegate; + +/// Load a local asset. The provided URL must be a file URL, or else loading will fail. +- (instancetype)initWithURL:(NSURL *)url bufferAllocator:(id)bufferAllocator; + +- (void)addLight:(GLTFKHRLight *)light; + +- (void)addCamera:(GLTFCamera *)camera; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAsset.m b/platform/darwin/src/gltf/gltfkit/GLTFAsset.m new file mode 100644 index 000000000000..c375ca1e6463 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFAsset.m @@ -0,0 +1,1273 @@ + +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFAsset.h" +#import "GLTFAnimation.h" +#import "GLTFAccessor.h" +#import "GLTFBinaryChunk.h" +#import "GLTFBuffer.h" +#import "GLTFBufferAllocator.h" +#import "GLTFBufferView.h" +#import "GLTFCamera.h" +#import "GLTFExtensionNames.h" +#import "GLTFImage.h" +#import "GLTFKHRLight.h" +#import "GLTFMaterial.h" +#import "GLTFMesh.h" +#import "GLTFNode.h" +#import "GLTFTexture.h" +#import "GLTFTextureSampler.h" +#import "GLTFScene.h" +#import "GLTFSkin.h" +#import "GLTFUtilities.h" + +#import + +#define USE_AGGRESSIVE_ALIGNMENT 0 + +@interface GLTFAsset () +@property (nonatomic, strong) NSURL *url; +@property (nonatomic, strong) id bufferAllocator; +@property (nonatomic, weak) id delegate; +@property (nonatomic, copy) NSArray *accessors; +@property (nonatomic, copy) NSArray> *buffers; +@property (nonatomic, copy) NSArray *bufferViews; +@property (nonatomic, copy) NSArray *images; +@property (nonatomic, copy) NSArray *samplers; +@property (nonatomic, copy) NSArray *textures; +@property (nonatomic, copy) NSArray *meshes; +@property (nonatomic, copy) NSArray *materials; +@property (nonatomic, strong) NSMutableArray *lights; +@property (nonatomic, strong) NSMutableArray *cameras; +@property (nonatomic, copy) NSArray *nodes; +@property (nonatomic, strong) NSArray *animations; +@property (nonatomic, copy) NSArray *skins; +@property (nonatomic, copy) NSArray *chunks; +@property (nonatomic, strong) GLTFMaterial *defaultMaterial; +@property (nonatomic, strong) GLTFTextureSampler *defaultSampler; +@property (nonatomic, assign) BOOL usesPBRSpecularGlossiness; +@property (nonatomic, assign) BOOL usesEXTPBRAttributes; +@property (nonatomic, assign) BOOL usesKHRLights; +@property (nonatomic, assign) BOOL usesKHRTextureTransform; +@property (nonatomic, assign) BOOL usesKHRMaterialsUnlit; +@end + +@implementation GLTFAsset + ++ (dispatch_queue_t)assetLoaderQueue { + static dispatch_once_t onceToken; + static dispatch_queue_t _assetLoaderQueue; + dispatch_once(&onceToken, ^{ + _assetLoaderQueue = dispatch_queue_create("net.warrenmoore.gltfkit.asset-loader-queue", DISPATCH_QUEUE_CONCURRENT); + }); + return _assetLoaderQueue; +} + ++ (void)loadAssetWithURL:(NSURL *)url bufferAllocator:(id)bufferAllocator delegate:(id)delegate { + dispatch_async(GLTFAsset.assetLoaderQueue, ^{ + (void)[[GLTFAsset alloc] _initWithURL:url bufferAllocator:bufferAllocator delegate:delegate]; + }); +} + +- (instancetype)initWithURL:(NSURL *)url bufferAllocator:(id)bufferAllocator { + return [self _initWithURL:url bufferAllocator:bufferAllocator delegate:nil]; +} + +- (instancetype)_initWithURL:(NSURL *)url bufferAllocator:(id)bufferAllocator delegate:(id)delegate { + if ((self = [super init])) { + _url = url; + _bufferAllocator = bufferAllocator; + _delegate = delegate; + NSError *error = nil; + if (![self loadWithError:&error]) { + [_delegate assetWithURL:_url didFailToLoadWithError:error]; + return nil; + } + } + + [_delegate assetWithURL:_url didFinishLoading:self]; + + return self; +} + +- (void)addLight:(GLTFKHRLight *)light { + [_lights addObject:light]; +} + +- (void)addCamera:(GLTFCamera *)camera { + [_cameras addObject:camera]; +} + +- (NSData *)imageDataForDataURI:(NSString *)uriData { + NSString *prefix = @"data:"; + if ([uriData hasPrefix:prefix]) { + NSInteger prefixEnd = prefix.length; + NSInteger firstComma = [uriData rangeOfString:@","].location; + if (firstComma != NSNotFound) { + NSString *mediaTypeAndTokenString = [uriData substringWithRange:NSMakeRange(prefixEnd, firstComma - prefixEnd)]; + NSArray *mediaTypeAndToken = [mediaTypeAndTokenString componentsSeparatedByString:@";"]; + if (mediaTypeAndToken.count > 0) { + NSString *encodedImageData = [uriData substringFromIndex:firstComma + 1]; + NSData *imageData = [[NSData alloc] initWithBase64EncodedString:encodedImageData + options:NSDataBase64DecodingIgnoreUnknownCharacters]; + return imageData; + } + } + } + return nil; +} + +- (NSData *_Nullable)_contentsOfURL:(NSURL *)url error:(NSError **)error { + __block NSData *urlData = nil; + __block NSError *internalError = nil; + if (![_url isFileURL]) { + dispatch_semaphore_t loadingSemaphore = dispatch_semaphore_create(0); + [_delegate assetWithURL:_url requiresContentsOfURL:url completionHandler:^(NSData *_Nullable data, NSError *_Nullable responseError) { + urlData = data; + internalError = responseError; + dispatch_semaphore_signal(loadingSemaphore); + }]; + dispatch_semaphore_wait(loadingSemaphore, DISPATCH_TIME_FOREVER); + } else { + urlData = [NSData dataWithContentsOfURL:url]; + } + + if (internalError != nil && error != nil) { + *error = internalError; + } + + return urlData; +} + +- (BOOL)loadWithError:(NSError **)errorOrNil { + NSError *error = nil; + NSDictionary *rootObject = nil; + + NSData *assetData = [self _contentsOfURL:_url error:&error]; + if (assetData == nil) { + return NO; + } + + if ([self assetIsGLB:assetData]) { + [self readBinaryChunks:assetData]; + rootObject = [NSJSONSerialization JSONObjectWithData:_chunks.firstObject.data options:0 error:&error]; + } else { + rootObject = [NSJSONSerialization JSONObjectWithData:assetData options:0 error:&error]; + } + + if (!rootObject) { + if (errorOrNil) { *errorOrNil = error; } + return NO; + } + + _extensionsUsed = [rootObject[@"extensionsUsed"] ?: @[] copy]; + + [self toggleExtensionFeatureFlags]; + + _defaultSampler = [GLTFTextureSampler new]; + + _defaultMaterial = [GLTFMaterial new]; + + _lights = [NSMutableArray array]; + + _cameras = [NSMutableArray array]; + + // Since we aren't streaming, we have the properties for all objects in memory + // and we can load in the order that makes the least work for us, i.e. by + // reducing the number of name resolutions we have to do after we deserialize + // everything into glTF objects. The only object subgraph that can't be + // resolved by careful ordering of loading is the subgraph of nodes itself, + // which is stored unordered and may contain arbitrary node-node relationships. + // Therefore, we run a post-load fix-up pass to resolve all node graph edges + // into real object references. Refer to `fixNodeRelationships` below. + + [self loadAssetProperties:rootObject[@"asset"]]; + [self loadBuffers:rootObject[@"buffers"]]; + [self loadBufferViews:rootObject[@"bufferViews"]]; + [self loadAccessors:rootObject[@"accessors"]]; + [self loadSamplers:rootObject[@"samplers"]]; + [self loadImages:rootObject[@"images"]]; + [self loadTextures:rootObject[@"textures"]]; + [self loadMaterials:rootObject[@"materials"]]; + if (_usesKHRLights) { + NSDictionary *extensionProperties = rootObject[@"extensions"][GLTFExtensionKHRLights]; + NSArray *lightsProperties = extensionProperties[@"lights"]; + [self loadLights:lightsProperties]; + } + [self loadCameras:rootObject[@"cameras"]]; + [self loadSkins:rootObject[@"skins"]]; + [self loadMeshes:rootObject[@"meshes"]]; + [self loadNodes:rootObject[@"nodes"]]; + [self loadAnimations:rootObject[@"animations"]]; + [self loadScenes:rootObject[@"scenes"]]; + [self loadDefaultScene:rootObject[@"scene"]]; + + return YES; +} + +- (void)toggleExtensionFeatureFlags { + for (NSString *extension in _extensionsUsed) { + if ([extension isEqualToString:GLTFExtensionKHRMaterialsPBRSpecularGlossiness]) { + NSLog(@"WARNING: Extension \"%@\" is not fully supported", extension); + _usesPBRSpecularGlossiness = YES; + } else if ([extension isEqualToString:GLTFExtensionEXTPBRAttributes]) { + _usesEXTPBRAttributes = YES; + } else if ([extension isEqualToString:GLTFExtensionKHRLights]) { + _usesKHRLights = YES; + } else if ([extension isEqualToString:GLTFExtensionKHRMaterialsUnlit]) { + _usesKHRMaterialsUnlit = YES; + } else if ([extension isEqualToString:GLTFExtensionKHRTextureTransform]) { + _usesKHRTextureTransform = YES; + } else { + NSLog(@"WARNING: Unsupported extension \"%@\" used", extension); + } + } +} + +- (BOOL)assetIsGLB:(NSData *)assetData { + if (assetData.length < sizeof(GLTFBinaryHeader)) { + return NO; + } else { + GLTFBinaryHeader header; + [assetData getBytes:&header length:sizeof(header)]; + return (header.magic == GLTFBinaryMagic); + } +} + +- (void)readBinaryChunks:(NSData *)assetData { + NSMutableArray *chunks = [NSMutableArray array]; + + GLTFBinaryHeader header; + [assetData getBytes:&header length:sizeof(GLTFBinaryHeader)]; + + NSInteger offset = sizeof(GLTFBinaryHeader); + while (offset < header.length && offset < assetData.length) { + GLTFBinaryChunk *chunk = [GLTFBinaryChunk new]; + struct { + UInt32 length; + UInt32 type; + } chunkHeader; + + [assetData getBytes:&chunkHeader range:NSMakeRange(offset, sizeof(chunkHeader))]; + + NSData *chunkData = [NSData dataWithBytesNoCopy:(void *)(assetData.bytes + offset + sizeof(chunkHeader)) + length:chunkHeader.length + freeWhenDone:NO]; + chunk.data = chunkData; + chunk.chunkType = chunkHeader.type; + + [chunks addObject:chunk]; + + offset += sizeof(chunkHeader) + chunkHeader.length; + } + + _chunks = [chunks copy]; + + NSAssert(_chunks.firstObject.chunkType == GLTFChunkTypeJSON, @"First chunk in GLB file had type %u rather than expected %u", + (unsigned int)_chunks.firstObject.chunkType, (unsigned int)GLTFChunkTypeJSON); +} + +- (BOOL)loadAssetProperties:(NSDictionary *)propertiesMap { + _generator = [propertiesMap[@"generator"] copy]; + _copyright = [propertiesMap[@"copyright"] copy]; + _formatVersion = propertiesMap[@"version"] ?: @"2.0"; + return YES; +} + +- (BOOL)loadAccessors:(NSArray *)accessorsMap { + if (accessorsMap.count == 0) { + _accessors = @[]; + return YES; + } + + NSMutableArray *accessors = [NSMutableArray arrayWithCapacity:accessorsMap.count]; + for (NSDictionary *properties in accessorsMap) { + GLTFAccessor *accessor = [[GLTFAccessor alloc] init]; + accessor.componentType = [properties[@"componentType"] integerValue]; + accessor.dimension = GLTFDataDimensionForName(properties[@"type"]); + accessor.offset = [properties[@"byteOffset"] integerValue]; + accessor.count = [properties[@"count"] integerValue]; + NSUInteger bufferViewIndex = [properties[@"bufferView"] intValue]; + if (bufferViewIndex < _bufferViews.count) { + accessor.bufferView = _bufferViews[bufferViewIndex]; +#if USE_AGGRESSIVE_ALIGNMENT + size_t alignment = GLTFSizeOfComponentTypeWithDimension(accessor.componentType, accessor.dimension); +#else + size_t alignment = GLTFSizeOfDataType(accessor.componentType); +#endif + NSInteger dataOffset = accessor.offset + accessor.bufferView.offset; + if (dataOffset % alignment != 0) { + size_t elementSize = GLTFSizeOfComponentTypeWithDimension(accessor.componentType, accessor.dimension); + size_t length = accessor.count * elementSize; + NSLog(@"WARNING: Accessor had misaligned offset %d, which is not a multiple of %d. Building auxiliary buffer of length %d and continuing...", + (int)dataOffset, (int)alignment, (int)length); + id buffer = [_bufferAllocator newBufferWithLength:length]; + memcpy(buffer.contents, accessor.bufferView.buffer.contents + accessor.bufferView.offset + accessor.offset, buffer.length); + _buffers = [_buffers arrayByAddingObject:buffer]; + + GLTFBufferView *bufferView = [GLTFBufferView new]; + bufferView.buffer = buffer; + bufferView.offset = 0; + bufferView.stride = 0; + _bufferViews = [_bufferViews arrayByAddingObject:bufferView]; + + accessor.bufferView = bufferView; + accessor.offset = 0; + } + } + + __block GLTFValueRange valueRange = { 0 }; + NSArray *minValues = properties[@"min"]; + [minValues enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger index, BOOL *stop) { + valueRange.minValue[index] = num.floatValue; + }]; + NSArray *maxValues = properties[@"max"]; + [maxValues enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger index, BOOL *stop) { + valueRange.maxValue[index] = num.floatValue; + }]; + accessor.valueRange = valueRange; + + [accessors addObject:accessor]; + } + + _accessors = [accessors copy]; + + return YES; +} + +- (BOOL)loadBuffers:(NSArray *)buffersMap { + if (buffersMap.count == 0) { + _buffers = @[]; + } + + NSMutableArray *buffers = [NSMutableArray arrayWithCapacity:buffersMap.count]; + for (NSDictionary *properties in buffersMap) { + NSUInteger byteLength = [properties[@"byteLength"] integerValue]; + + NSString *uri = properties[@"uri"]; + NSData *data = nil; + + if ([uri hasPrefix:@"data:"]) { + if ([uri hasPrefix:@"data:application/octet-stream;base64,"]) { + NSString *dataSubstring = [uri substringFromIndex:[@"data:application/octet-stream;base64," length]]; + data = [[NSData alloc] initWithBase64EncodedString:dataSubstring options:0]; + } else { + NSLog(@"WARNING: Encountered URL-encoded buffer that did not have the expected MIME type or encoding. Skipping..."); + continue; + } + } else if (uri.length > 0) { + NSURL *bufferURL = [[_url URLByDeletingLastPathComponent] URLByAppendingPathComponent:uri]; + NSError *error = nil; + data = [self _contentsOfURL:bufferURL error:&error]; + NSAssert(data != nil, @"Unable to load data at URL %@; error %@", bufferURL, error); + } else if (_chunks.count > 1) { + data = _chunks[1].data; + } else { + NSLog(@"WARNING: Encountered buffer which was not URL-encoded, nor a file reference, nor a GLB chunk reference. Skipping..."); + continue; + } + + id buffer = [_bufferAllocator newBufferWithData:data]; + + if (byteLength != [buffer length]) { + NSLog(@"WARNING: Expected to load buffer of length %lu bytes; got %lu bytes", (unsigned long)byteLength, (unsigned long)[buffer length]); + } + [buffers addObject: buffer]; + } + + _buffers = [buffers copy]; + return YES; +} + +- (BOOL)loadBufferViews:(NSArray *)bufferViewsMap { + if (bufferViewsMap.count == 0) { + _bufferViews = @[]; + } + + NSMutableArray *bufferViews = [NSMutableArray arrayWithCapacity:bufferViewsMap.count]; + [bufferViewsMap enumerateObjectsUsingBlock:^(NSDictionary *properties, NSUInteger index, BOOL *stop) { + + GLTFBufferView *bufferView = [[GLTFBufferView alloc] init]; + NSUInteger bufferIndex = [properties[@"buffer"] intValue]; + if (bufferIndex < _buffers.count) { + bufferView.buffer = _buffers[bufferIndex]; + } + bufferView.length = [properties[@"byteLength"] integerValue]; + bufferView.stride = [properties[@"byteStride"] integerValue]; + bufferView.offset = [properties[@"byteOffset"] integerValue]; + bufferView.target = [properties[@"target"] integerValue]; + +// if ((bufferView.buffer != nil) && (bufferView.offset % 16 != 0)) { +// NSLog(@"WARNING: Buffer view %d had misaligned offset of %d. Creating auxilliary buffer of length %d and continuing...", +// (int)index, (int)bufferView.offset, (int)bufferView.length); +// id alignedBuffer = [_bufferAllocator newBufferWithLength:bufferView.length]; +// _buffers = [_buffers arrayByAddingObject:alignedBuffer]; +// memcpy([alignedBuffer contents], bufferView.buffer.contents + bufferView.offset, bufferView.length); +// bufferView.buffer = alignedBuffer; +// bufferView.offset = 0; +// } + + [bufferViews addObject: bufferView]; + }]; + + _bufferViews = [bufferViews copy]; + return YES; +} + +- (BOOL)loadSamplers:(NSArray *)samplersMap { + if (samplersMap.count == 0) { + _samplers = @[]; + } + + NSMutableArray *samplers = [NSMutableArray arrayWithCapacity:samplersMap.count]; + for (NSDictionary *properties in samplersMap) { + GLTFTextureSampler *sampler = [[GLTFTextureSampler alloc] init]; + sampler.minFilter = [properties[@"minFilter"] integerValue] ?: sampler.minFilter; + sampler.magFilter = [properties[@"magFilter"] integerValue] ?: sampler.magFilter; + sampler.sAddressMode = [properties[@"wrapS"] integerValue] ?: sampler.sAddressMode; + sampler.tAddressMode = [properties[@"wrapT"] integerValue] ?: sampler.tAddressMode; + sampler.name = properties[@"name"]; + sampler.extensions = properties[@"extensions"]; + sampler.extras = properties[@"extras"]; + + [samplers addObject:sampler]; + } + + _samplers = [samplers copy]; + return YES; +} + +- (BOOL)loadImages:(NSArray *)imagesMap { + if (imagesMap.count == 0) { + _images = @[]; + } + + NSMutableArray *images = [NSMutableArray arrayWithCapacity:imagesMap.count]; + for (NSDictionary *properties in imagesMap) { + GLTFImage *image = [[GLTFImage alloc] init]; + + NSString *uri = properties[@"uri"]; + + if ([uri hasPrefix:@"data:image/"]) { + image.imageData = [self imageDataForDataURI:uri]; + } else if (uri.length > 0) { + NSURL *resourceURL = [self.url URLByDeletingLastPathComponent]; + image.url = [resourceURL URLByAppendingPathComponent:uri]; + } + + image.mimeType = properties[@"mimeType"]; + + NSString *bufferViewIndexString = properties[@"bufferView"]; + if (bufferViewIndexString) { + NSUInteger bufferViewIndex = bufferViewIndexString.integerValue; + if (bufferViewIndex < _bufferViews.count) { + image.bufferView = _bufferViews[bufferViewIndex]; + } + } + + image.name = properties[@"name"]; + image.extensions = properties[@"extensions"]; + image.extras = properties[@"extras"]; + + [images addObject:image]; + } + + _images = [images copy]; + return YES; +} + +- (BOOL)loadTextures:(NSArray *)texturesMap { + if (texturesMap.count == 0) { + _textures = @[]; + } + + NSMutableArray *textures = [NSMutableArray arrayWithCapacity:texturesMap.count]; + for (NSDictionary *properties in texturesMap) { + GLTFTexture *texture = [[GLTFTexture alloc] init]; + + NSUInteger samplerIndex = [properties[@"sampler"] intValue]; + if (samplerIndex < _samplers.count) { + texture.sampler = _samplers[samplerIndex]; + } else { + texture.sampler = _defaultSampler; + } + + NSUInteger imageIndex = [properties[@"source"] intValue]; + if (imageIndex < _images.count) { + texture.image = _images[imageIndex]; + } + + texture.format = [properties[@"format"] integerValue] ?: texture.format; + texture.internalFormat = [properties[@"internalFormat"] integerValue] ?: texture.internalFormat; + texture.target = [properties[@"target"] integerValue] ?: texture.target; + texture.type = [properties[@"type"] integerValue] ?: texture.type; + texture.name = properties[@"name"]; + texture.extensions = properties[@"extensions"]; + texture.extras = properties[@"extras"]; + + [textures addObject: texture]; + } + + _textures = [textures copy]; + return YES; +} + + +- (BOOL)loadCameras:(NSArray *)camerasMap { + if (camerasMap.count == 0) { + _cameras = [NSMutableArray array]; + return YES; + } + + _cameras = [NSMutableArray arrayWithCapacity:camerasMap.count]; + for (NSDictionary *properties in camerasMap) { + GLTFCamera *camera = [[GLTFCamera alloc] init]; + + camera.cameraType = [properties[@"type"] isEqualToString:@"orthographic"] ? GLTFCameraTypeOrthographic : GLTFCameraTypePerspective; + + NSDictionary *params = properties[properties[@"type"]]; + + switch (camera.cameraType) { + case GLTFCameraTypeOrthographic: + camera.xmag = [params[@"xmag"] floatValue]; + camera.ymag = [params[@"ymag"] floatValue]; + break; + case GLTFCameraTypePerspective: + default: { + NSNumber *aspectRatioValue = params[@"aspectRatio"]; + camera.aspectRatio = (aspectRatioValue != nil) ? aspectRatioValue.floatValue : 1.0; + camera.yfov = [params[@"yfov"] floatValue]; + break; + } + } + + camera.znear = [params[@"znear"] floatValue]; + + if (camera.cameraType == GLTFCameraTypePerspective && (params[@"zfar"] == nil)) { + camera.zfar = FLT_MAX; + } else { + camera.zfar = [params[@"zfar"] floatValue]; + } + + camera.extensions = properties[@"extensions"]; + camera.extras = properties[@"extras"]; + + [_cameras addObject: camera]; + } + + return YES; +} + +- (BOOL)loadLights:(NSArray *)lightsMap { + if (lightsMap.count == 0) { + return YES; + } + + _lights = [NSMutableArray arrayWithCapacity:lightsMap.count]; + [lightsMap enumerateObjectsUsingBlock:^(NSDictionary *properties, NSUInteger index, BOOL *stop) { + GLTFKHRLight *light = [GLTFKHRLight new]; + NSString *lightTypeName = properties[@"type"]; + if ([lightTypeName isEqualToString:@"ambient"]) { + light.type = GLTFKHRLightTypeAmbient; + } else if ([lightTypeName isEqualToString:@"directional"]) { + light.type = GLTFKHRLightTypeDirectional; + } else if ([lightTypeName isEqualToString:@"point"]) { + light.type = GLTFKHRLightTypePoint; + } else if ([lightTypeName isEqualToString:@"spot"]) { + light.type = GLTFKHRLightTypeSpot; + } + + NSArray *colorArray = properties[@"color"]; + switch ([colorArray count]) { + case 3: // This is out of spec, but it happens in the wild, so be graceful. + light.color = GLTFVectorFloat4FromArray([colorArray arrayByAddingObject:@(1)]); + break; + case 4: + light.color = GLTFVectorFloat4FromArray(colorArray); + break; + } + + NSNumber *intensityValue = properties[@"intensity"]; + if (intensityValue != nil) { + light.intensity = [intensityValue floatValue]; + } + + if (light.type == GLTFKHRLightTypeSpot) { + NSDictionary *spotProperties = properties[@"spot"]; + NSNumber *innerConeAngleValue = spotProperties[@"innerConeAngle"]; + if (innerConeAngleValue != nil) { + light.innerConeAngle = [innerConeAngleValue floatValue]; + } + NSNumber *outerConeAngleValue = spotProperties[@"outerConeAngle"]; + if (outerConeAngleValue != nil) { + light.outerConeAngle = [outerConeAngleValue floatValue]; + } + } + + [_lights addObject:light]; + }]; + + return YES; +} + +- (BOOL)loadMeshes:(NSArray *)meshesMap { + if (meshesMap.count == 0) { + _meshes = @[]; + } + + NSMutableArray *meshes = [NSMutableArray arrayWithCapacity:meshesMap.count]; + for (NSDictionary *properties in meshesMap) { + GLTFMesh *mesh = [[GLTFMesh alloc] init]; + mesh.name = properties[@"name"]; + mesh.extensions = properties[@"extensions"]; + mesh.extras = properties[@"extras"]; + + mesh.defaultMorphTargetWeights = properties[@"weights"] ?: @[]; + + NSArray *submeshesProperties = properties[@"primitives"]; + NSMutableArray *submeshes = [NSMutableArray arrayWithCapacity:submeshesProperties.count]; + for (NSDictionary *submeshProperties in submeshesProperties) { + GLTFSubmesh *submesh = [[GLTFSubmesh alloc] init]; + + NSDictionary *submeshAttributes = submeshProperties[@"attributes"]; + + NSMutableDictionary *attributeAccessors = [NSMutableDictionary dictionaryWithCapacity:submeshAttributes.count]; + [submeshAttributes enumerateKeysAndObjectsUsingBlock:^(NSString *attributeName, NSNumber *accessorIndexValue, BOOL *stop) { + NSUInteger accessorIndex = accessorIndexValue.unsignedIntegerValue; + if (accessorIndex < _accessors.count) { + GLTFAccessor *accessor = _accessors[accessorIndex]; + attributeAccessors[attributeName] = accessor; + } + }]; + + submesh.accessorsForAttributes = attributeAccessors; + + NSUInteger materialIndex = [submeshProperties[@"material"] intValue]; + if (materialIndex < _materials.count) { + submesh.material = _materials[materialIndex]; + } else { + submesh.material = _defaultMaterial; + } + + NSUInteger indexAccessorIndex = [submeshProperties[@"indices"] intValue]; + if (indexAccessorIndex < _accessors.count) { + GLTFAccessor *indexAccessor = _accessors[indexAccessorIndex]; + if (indexAccessor.componentType == GLTFTextureTypeUChar) { + // Fix up 8-bit indices, since they're unsupported in modern APIs + uint8_t *sourceIndices = indexAccessor.bufferView.buffer.contents + indexAccessor.offset + indexAccessor.bufferView.offset; + + id shortBuffer = [_bufferAllocator newBufferWithLength:indexAccessor.count * sizeof(uint16_t)]; + uint16_t *destIndices = shortBuffer.contents; + for (int i = 0; i < indexAccessor.count; ++i) { + destIndices[i] = (uint16_t)sourceIndices[i]; + } + _buffers = [_buffers arrayByAddingObject:shortBuffer]; + + GLTFBufferView *shortBufferView = [GLTFBufferView new]; + shortBufferView.buffer = shortBuffer; + shortBufferView.offset = 0; + shortBufferView.stride = 0; + _bufferViews = [_bufferViews arrayByAddingObject:shortBufferView]; + + GLTFAccessor *shortAccessor = [GLTFAccessor new]; + shortAccessor.bufferView = shortBufferView; + shortAccessor.componentType = GLTFDataTypeUShort; + shortAccessor.dimension = GLTFDataDimensionScalar; + shortAccessor.count = indexAccessor.count; + shortAccessor.offset = 0; + shortAccessor.valueRange = indexAccessor.valueRange; + _accessors = [_accessors arrayByAddingObject:shortAccessor]; + + indexAccessor = shortAccessor; + } + submesh.indexAccessor = indexAccessor; + } + + if (submeshProperties[@"mode"]) { + submesh.primitiveType = (GLTFPrimitiveType)[submeshProperties[@"mode"] intValue]; + } + + NSMutableArray *morphTargets = [NSMutableArray array]; + for (NSDictionary *targetProperties in submeshProperties[@"targets"]) { + GLTFMorphTarget *morphTarget = [GLTFMorphTarget new]; + NSMutableDictionary *attributeAccessors = [NSMutableDictionary dictionaryWithCapacity:submeshAttributes.count]; + [targetProperties enumerateKeysAndObjectsUsingBlock:^(NSString *attributeName, NSNumber *accessorIndexValue, BOOL *stop) { + NSUInteger accessorIndex = accessorIndexValue.unsignedIntegerValue; + if (accessorIndex < _accessors.count) { + GLTFAccessor *accessor = _accessors[accessorIndex]; + attributeAccessors[attributeName] = accessor; + } + }]; + morphTarget.accessorsForAttributes = [attributeAccessors copy]; + [morphTargets addObject:morphTarget]; + } + submesh.morphTargets = [morphTargets copy]; + + [submeshes addObject:submesh]; + } + + mesh.submeshes = [submeshes copy]; + + [meshes addObject:mesh]; + } + + _meshes = [meshes copy]; + return YES; +} + + +- (BOOL)loadMaterials:(NSArray *)materialsMap { + if (materialsMap.count == 0) { + _materials = @[]; + return YES; + } + + NSMutableArray *materials = [NSMutableArray arrayWithCapacity:materialsMap.count]; + for (NSDictionary *properties in materialsMap) { + GLTFMaterial *material = [[GLTFMaterial alloc] init]; + + NSDictionary *pbrValuesMap = properties[@"pbrMetallicRoughness"]; + if (pbrValuesMap) { + NSDictionary *baseColorTextureMap = pbrValuesMap[@"baseColorTexture"]; + NSNumber *baseColorTextureIndexValue = baseColorTextureMap[@"index"]; + if (baseColorTextureIndexValue != nil) { + material.baseColorTexture = [[GLTFTextureInfo alloc] init]; + NSUInteger baseColorTextureIndex = baseColorTextureIndexValue.integerValue; + if (baseColorTextureIndex < _textures.count) { + material.baseColorTexture.texture = _textures[baseColorTextureIndex]; + } + } + NSNumber *baseColorTexCoordValue = baseColorTextureMap[@"texCoord"]; + if (baseColorTexCoordValue != nil) { + material.baseColorTexture.texCoord = baseColorTexCoordValue.integerValue; + } + + material.baseColorTexture.extras = baseColorTextureMap[@"extras"]; + material.baseColorTexture.extensions = baseColorTextureMap[@"extensions"]; + + NSArray *baseColorFactorComponents = pbrValuesMap[@"baseColorFactor"]; + if (baseColorFactorComponents.count == 4) { + material.baseColorFactor = GLTFVectorFloat4FromArray(baseColorFactorComponents); + } + + NSNumber *metallicFactor = pbrValuesMap[@"metallicFactor"]; + if (metallicFactor != nil) { + material.metalnessFactor = metallicFactor.floatValue; + } + + NSNumber *roughnessFactor = pbrValuesMap[@"roughnessFactor"]; + if (roughnessFactor != nil) { + material.roughnessFactor = roughnessFactor.floatValue; + } + + NSDictionary *metallicRoughnessTextureMap = pbrValuesMap[@"metallicRoughnessTexture"]; + NSNumber *metallicRoughnessTextureIndexValue = metallicRoughnessTextureMap[@"index"]; + if (metallicRoughnessTextureIndexValue != nil) { + material.metallicRoughnessTexture = [[GLTFTextureInfo alloc] init]; + NSUInteger metallicRoughnessTextureIndex = metallicRoughnessTextureIndexValue.integerValue; + if (metallicRoughnessTextureIndex < _textures.count) { + material.metallicRoughnessTexture.texture = _textures[metallicRoughnessTextureIndex]; + } + } + + NSNumber *metallicRoughnessTexCoordValue = metallicRoughnessTextureMap[@"texCoord"]; + if (metallicRoughnessTexCoordValue != nil) { + material.metallicRoughnessTexture.texCoord = metallicRoughnessTexCoordValue.integerValue; + } + + material.metallicRoughnessTexture.extras = metallicRoughnessTextureMap[@"extras"]; + material.metallicRoughnessTexture.extensions = metallicRoughnessTextureMap[@"extensions"]; + } + + NSDictionary *normalTextureMap = properties[@"normalTexture"]; + if (normalTextureMap) { + material.normalTexture = [[GLTFTextureInfo alloc] init]; + NSNumber *normalTextureIndexValue = normalTextureMap[@"index"]; + NSUInteger normalTextureIndex = normalTextureIndexValue.integerValue; + if (normalTextureIndex < _textures.count) { + material.normalTexture.texture = _textures[normalTextureIndex]; + } + NSNumber *normalTextureScaleValue = normalTextureMap[@"scale"]; + material.normalTextureScale = (normalTextureScaleValue != nil) ? normalTextureScaleValue.floatValue : 1.0; + + NSNumber *normalTexCoordValue = normalTextureMap[@"texCoord"]; + if (normalTexCoordValue != nil) { + material.normalTexture.texCoord = normalTexCoordValue.integerValue; + } + + material.normalTexture.extras = normalTextureMap[@"extras"]; + material.normalTexture.extensions = normalTextureMap[@"extensions"]; + } + + NSDictionary *emissiveTextureMap = properties[@"emissiveTexture"]; + if (emissiveTextureMap) { + material.emissiveTexture = [[GLTFTextureInfo alloc] init]; + NSNumber *emissiveTextureIndexValue = emissiveTextureMap[@"index"]; + NSUInteger emissiveTextureIndex = emissiveTextureIndexValue.integerValue; + if (emissiveTextureIndex < _textures.count) { + material.emissiveTexture.texture = _textures[emissiveTextureIndex]; + } + NSNumber *emissiveTexCoordValue = emissiveTextureMap[@"texCoord"]; + if (emissiveTexCoordValue != nil) { + material.emissiveTexture.texCoord = emissiveTexCoordValue.integerValue; + } + + material.emissiveTexture.extras = emissiveTextureMap[@"extras"]; + material.emissiveTexture.extensions = emissiveTextureMap[@"extensions"]; + } + + NSArray *emissiveFactorArray = properties[@"emissiveFactor"]; + if (emissiveFactorArray.count == 3) { + material.emissiveFactor = GLTFVectorFloat3FromArray(emissiveFactorArray); + } + + NSDictionary *occlusionTextureMap = properties[@"occlusionTexture"]; + if (occlusionTextureMap) { + material.occlusionTexture = [[GLTFTextureInfo alloc] init]; + NSNumber *occlusionTextureIndexValue = occlusionTextureMap[@"index"]; + NSUInteger occlusionTextureIndex = occlusionTextureIndexValue.integerValue; + if (occlusionTextureIndex < _textures.count) { + material.occlusionTexture.texture = _textures[occlusionTextureIndex]; + } + NSNumber *occlusionTexCoordValue = occlusionTextureMap[@"texCoord"]; + if (occlusionTexCoordValue != nil) { + material.occlusionTexture.texCoord = occlusionTexCoordValue.integerValue; + } + NSNumber *occlusionStrengthValue = occlusionTextureMap[@"strength"]; + if (occlusionStrengthValue != nil) { + material.occlusionStrength = occlusionStrengthValue.floatValue; + } + + material.occlusionTexture.extras = occlusionTextureMap[@"extras"]; + material.occlusionTexture.extensions = occlusionTextureMap[@"extensions"]; + } + + NSNumber *doubleSidedValue = properties[@"doubleSided"]; + material.doubleSided = (doubleSidedValue == nil) || (doubleSidedValue != nil && doubleSidedValue.boolValue); + + NSString *alphaMode = properties[@"alphaMode"]; + if ([alphaMode isEqualToString:@"BLEND"]) { + material.alphaMode = GLTFAlphaModeBlend; + } else if ([alphaMode isEqualToString:@"MASK"]) { + material.alphaMode = GLTFAlphaModeMask; + } else { + material.alphaMode = GLTFAlphaModeOpaque; + } + + NSNumber *alphaCutoffValue = properties[@"alphaCutoff"]; + if (alphaCutoffValue != nil) { + material.alphaCutoff = alphaCutoffValue.floatValue; + } + + material.name = properties[@"name"]; + material.extensions = properties[@"extensions"]; + material.extras = properties[@"extras"]; + + if (_usesPBRSpecularGlossiness) { + NSDictionary *pbrSpecularGlossinessProperties = material.extensions[GLTFExtensionKHRMaterialsPBRSpecularGlossiness]; + if (pbrSpecularGlossinessProperties != nil) { + NSDictionary *diffuseTextureMap = pbrSpecularGlossinessProperties[@"diffuseTexture"]; + if (diffuseTextureMap != nil) { + material.baseColorTexture = [[GLTFTextureInfo alloc] init]; + + NSNumber *diffuseTextureIndexValue = diffuseTextureMap[@"index"]; + if (diffuseTextureIndexValue != nil) { + NSUInteger diffuseTextureIndex = diffuseTextureIndexValue.integerValue; + if (diffuseTextureIndex < _textures.count) { + material.baseColorTexture.texture = _textures[diffuseTextureIndex]; + } + } + NSNumber *diffuseTexCoordValue = diffuseTextureMap[@"texCoord"]; + if (diffuseTexCoordValue != nil) { + material.baseColorTexture.texCoord = diffuseTexCoordValue.integerValue; + } + } + + // TODO: Support specularGlossinessTexture + + // TODO: Support texture transform of specular-glossiness map + + NSArray *diffuseFactorComponents = pbrSpecularGlossinessProperties[@"diffuseFactor"]; + if (diffuseFactorComponents.count == 4) { + material.baseColorFactor = GLTFVectorFloat4FromArray(diffuseFactorComponents); + } + + NSNumber *glossinessFactorValue = pbrSpecularGlossinessProperties[@"glossinessFactor"]; + material.glossinessFactor = (glossinessFactorValue != nil) ? glossinessFactorValue.floatValue : 0.0; + + NSArray *specularFactorComponents = pbrSpecularGlossinessProperties[@"specularFactor"]; + if (specularFactorComponents.count == 3) { + material.specularFactor = GLTFVectorFloat3FromArray(specularFactorComponents); + } + } + } + + if (_usesKHRMaterialsUnlit) { + NSDictionary *unlitMap = material.extensions[GLTFExtensionKHRMaterialsUnlit]; + if (unlitMap != nil) { + material.unlit = YES; + } + } + + if (_usesKHRTextureTransform) { + [self _fixMaterialTextureTransforms:material]; + } + + [materials addObject: material]; + } + + _materials = [materials copy]; + + return YES; +} + +- (GLTFTextureTransform)_textureTransformWithProperties:(NSDictionary *)properties { + GLTFTextureTransform transform = GLTFTextureTransformMakeIdentity(); + NSArray *offsetArray = properties[@"offset"]; + if (offsetArray != nil && offsetArray.count == 2) { + transform.offset = GLTFVectorFloat2FromArray(offsetArray); + } + NSNumber *rotationValue = properties[@"rotation"]; + if (rotationValue != nil) { + transform.rotation = rotationValue.floatValue; + } + NSArray *scaleArray = properties[@"scale"]; + if (scaleArray != nil && scaleArray.count == 2) { + transform.scale = GLTFVectorFloat2FromArray(scaleArray); + } + return transform; +} + +- (void)_fixMaterialTextureTransforms:(GLTFMaterial *)material { + NSDictionary *baseColorTransformProperties = material.baseColorTexture.extensions[GLTFExtensionKHRTextureTransform]; + if (baseColorTransformProperties != nil) { + material.baseColorTexture.transform = [self _textureTransformWithProperties:baseColorTransformProperties]; + NSNumber *texCoordValue = baseColorTransformProperties[@"texCoord"]; + if (texCoordValue != nil) { + material.baseColorTexture.texCoord = texCoordValue.intValue; + } + } + NSDictionary *normalTransformProperties = material.normalTexture.extensions[GLTFExtensionKHRTextureTransform]; + if (normalTransformProperties != nil) { + material.normalTexture.transform = [self _textureTransformWithProperties:normalTransformProperties]; + NSNumber *texCoordValue = normalTransformProperties[@"texCoord"]; + if (texCoordValue != nil) { + material.normalTexture.texCoord = texCoordValue.intValue; + } + } + NSDictionary *metallicRoughnessTransformProperties = material.metallicRoughnessTexture.extensions[GLTFExtensionKHRTextureTransform]; + if (metallicRoughnessTransformProperties != nil) { + material.metallicRoughnessTexture.transform = [self _textureTransformWithProperties:metallicRoughnessTransformProperties]; + NSNumber *texCoordValue = metallicRoughnessTransformProperties[@"texCoord"]; + if (texCoordValue != nil) { + material.metallicRoughnessTexture.texCoord = texCoordValue.intValue; + } + } + NSDictionary *occlusionTransformProperties = material.occlusionTexture.extensions[GLTFExtensionKHRTextureTransform]; + if (occlusionTransformProperties != nil) { + material.occlusionTexture.transform = [self _textureTransformWithProperties:occlusionTransformProperties]; + NSNumber *texCoordValue = occlusionTransformProperties[@"texCoord"]; + if (texCoordValue != nil) { + material.occlusionTexture.texCoord = texCoordValue.intValue; + } + } + NSDictionary *emissiveTransformProperties = material.emissiveTexture.extensions[GLTFExtensionKHRTextureTransform]; + if (emissiveTransformProperties != nil) { + material.emissiveTexture.transform = [self _textureTransformWithProperties:emissiveTransformProperties]; + NSNumber *texCoordValue = emissiveTransformProperties[@"texCoord"]; + if (texCoordValue != nil) { + material.emissiveTexture.texCoord = texCoordValue.intValue; + } + } + + material.hasTextureTransforms = YES; +} + +- (BOOL)loadNodes:(NSArray *)nodesMap { + if (nodesMap.count == 0) { + _nodes = @[]; + return YES; + } + + NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:nodesMap.count]; + for (NSDictionary *properties in nodesMap) { + GLTFNode *node = [[GLTFNode alloc] init]; + + NSString *cameraIdentifierString = properties[@"camera"]; + if (cameraIdentifierString) { + NSUInteger cameraIndex = cameraIdentifierString.integerValue; + if (cameraIndex < _cameras.count) { + GLTFCamera *camera = _cameras[cameraIndex]; + node.camera = camera; + camera.referencingNodes = [camera.referencingNodes arrayByAddingObject:node]; + } + } + + // Copy array of indices for now; we fix this up later in another pass once all nodes are in memory. + node.children = [properties[@"children"] copy]; + + NSNumber *skinIndexValue = properties[@"skin"]; + if (skinIndexValue != nil) { + NSUInteger skinIndex = skinIndexValue.integerValue; + if (skinIndex < _skins.count) { + node.skin = _skins[skinIndex]; + } + } + + node.jointName = properties[@"jointName"]; + + NSNumber *meshIndexValue = properties[@"mesh"]; + if (meshIndexValue != nil) { + NSUInteger meshIndex = meshIndexValue.integerValue; + if (meshIndex < _meshes.count) { + node.mesh = _meshes[meshIndex]; + } + } + + NSArray *matrixArray = properties[@"matrix"]; + if (matrixArray) { + node.localTransform = GLTFMatrixFloat4x4FromArray(matrixArray); + } + + NSArray *rotationArray = properties[@"rotation"]; + if (rotationArray) { + node.rotationQuaternion = GLTFQuaternionFromArray(rotationArray); + } + + NSArray *scaleArray = properties[@"scale"]; + if (scaleArray) { + node.scale = GLTFVectorFloat3FromArray(scaleArray); + } + + NSArray *translationArray = properties[@"translation"]; + if (translationArray) { + node.translation = GLTFVectorFloat3FromArray(translationArray); + } + + node.name = properties[@"name"]; + node.extensions = properties[@"extensions"]; + node.extras = properties[@"extras"]; + + if (_usesKHRLights) { + NSDictionary *lightProperties = node.extensions[GLTFExtensionKHRLights]; + NSNumber *lightIdentifierValue = lightProperties[@"light"]; + if (lightIdentifierValue && lightIdentifierValue.integerValue < _lights.count) { + node.light = _lights[lightIdentifierValue.integerValue]; + } + } + + [nodes addObject: node]; + } + + _nodes = [nodes copy]; + + return [self fixNodeRelationships]; +} + +- (BOOL)fixNodeRelationships { + for (GLTFNode *node in _nodes) { + NSArray *childIdentifiers = node.children; + NSMutableArray *children = [NSMutableArray arrayWithCapacity:childIdentifiers.count]; + for (NSNumber *childIndexValue in childIdentifiers) { + NSUInteger childIndex = childIndexValue.integerValue; + if (childIndex < _nodes.count) { + GLTFNode *child = _nodes[childIndex]; + child.parent = node; + [children addObject:child]; + } + } + node.children = children; + } + + for (GLTFSkin *skin in _skins) { + NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:skin.jointNodes.count]; + for (NSInteger i = 0; i < skin.jointNodes.count; ++i) { + NSNumber *jointIndexValue = (NSNumber *)skin.jointNodes[i]; + if (jointIndexValue != nil && jointIndexValue.intValue < _nodes.count) { + [nodes addObject:_nodes[jointIndexValue.intValue]]; + } + } + skin.jointNodes = [nodes copy]; + + NSNumber *skeletonIndexValue = (NSNumber *)skin.skeletonRootNode; + if (skeletonIndexValue != nil && skeletonIndexValue.intValue < _nodes.count) { + skin.skeletonRootNode = _nodes[skeletonIndexValue.intValue]; + } + } + + return YES; +} + +- (BOOL)loadAnimations:(NSArray *)animationsMap { + if (animationsMap.count == 0) { + _animations = @[]; + return YES; + } + + NSArray *interpolationModes = @[ @"STEP", @"LINEAR", @"CUBICSPLINE" ]; + + NSMutableArray *animations = [NSMutableArray arrayWithCapacity:animationsMap.count]; + + for (NSDictionary *properties in animationsMap) { + GLTFAnimation *animation = [[GLTFAnimation alloc] init]; + + NSArray *samplersProperties = properties[@"samplers"]; + NSMutableArray *samplers = [NSMutableArray arrayWithCapacity:samplersProperties.count]; + [samplersProperties enumerateObjectsUsingBlock:^(NSDictionary *samplerProperties, NSUInteger index, BOOL *stop) { + GLTFAnimationSampler *sampler = [[GLTFAnimationSampler alloc] init]; + NSNumber *inputIndexValue = samplerProperties[@"input"]; + if (inputIndexValue && inputIndexValue.integerValue < _accessors.count) { + sampler.inputAccessor = _accessors[inputIndexValue.integerValue]; + } + NSNumber *outputIndexValue = samplerProperties[@"output"]; + if (outputIndexValue && outputIndexValue.integerValue < _accessors.count) { + sampler.outputAccessor = _accessors[outputIndexValue.integerValue]; + } + if (samplerProperties[@"interpolation"]) { + sampler.interpolationMode = (GLTFInterpolationMode)[interpolationModes indexOfObject:samplerProperties[@"interpolation"]]; + } + [samplers addObject:sampler]; + }]; + + animation.samplers = [samplers copy]; + + NSArray *channelsProperties = properties[@"channels"]; + NSMutableArray *channels = [NSMutableArray arrayWithCapacity:channelsProperties.count]; + [channelsProperties enumerateObjectsUsingBlock:^(NSDictionary *channelProperties, NSUInteger index, BOOL *stop) { + GLTFAnimationChannel *channel = [GLTFAnimationChannel new]; + NSNumber *samplerIndexValue = channelProperties[@"sampler"]; + if (samplerIndexValue && samplerIndexValue.integerValue < samplers.count) { + channel.sampler = samplers[samplerIndexValue.integerValue]; + } + NSDictionary *targetProperties = channelProperties[@"target"]; + NSNumber *targetNodeIndexValue = targetProperties[@"node"]; + if (targetNodeIndexValue && targetNodeIndexValue.integerValue < _nodes.count) { + channel.targetNode = _nodes[targetNodeIndexValue.integerValue]; + } + channel.targetPath = targetProperties[@"path"]; + [channels addObject:channel]; + }]; + + animation.channels = [channels copy]; + + animation.name = properties[@"name"]; + animation.extensions = properties[@"extensions"]; + animation.extras = properties[@"extras"]; + + [animations addObject: animation]; + } + + _animations = [animations copy]; + + return YES; +} + +- (BOOL)loadSkins:(NSArray *)skinsMap { + if (skinsMap.count == 0) { + _skins = @[]; + return YES; + } + + NSMutableArray *skins = [NSMutableArray arrayWithCapacity:skinsMap.count]; + for (NSDictionary *properties in skinsMap) { + GLTFSkin *skin = [[GLTFSkin alloc] init]; + + NSNumber *inverseBindMatricesAccessorIndexValue = properties[@"inverseBindMatrices"]; + if (inverseBindMatricesAccessorIndexValue != nil) { + NSInteger inverseBindMatricesAccessorIndex = inverseBindMatricesAccessorIndexValue.integerValue; + if (inverseBindMatricesAccessorIndex < _accessors.count) { + skin.inverseBindMatricesAccessor = _accessors[inverseBindMatricesAccessorIndex]; + } + } + + NSArray *jointIndices = properties[@"joints"]; + if (jointIndices.count > 0) { + skin.jointNodes = [jointIndices copy]; + } + + NSNumber *skeletonIndexValue = properties[@"skeleton"]; + if (skeletonIndexValue != nil) { + skin.skeletonRootNode = (id)skeletonIndexValue; + } + + skin.name = properties[@"name"]; + skin.extensions = properties[@"extensions"]; + skin.extras = properties[@"extras"]; + + [skins addObject:skin]; + } + + _skins = [skins copy]; + + return YES; +} + +- (BOOL)loadScenes:(NSArray *)scenesMap { + if (scenesMap.count == 0) { + _scenes = @[]; + return YES; + } + + NSMutableArray *scenes = [NSMutableArray arrayWithCapacity:scenesMap.count]; + for (NSDictionary *properties in scenesMap) { + GLTFScene *scene = [[GLTFScene alloc] init]; + + NSArray *rootNodeIndices = properties[@"nodes"]; + NSMutableArray *rootNodes = [NSMutableArray arrayWithCapacity:rootNodeIndices.count]; + for (NSNumber *nodeIndexValue in rootNodeIndices) { + NSUInteger nodeIndex = nodeIndexValue.integerValue; + if (nodeIndex < _nodes.count) { + GLTFNode *node = _nodes[nodeIndex]; + [rootNodes addObject:node]; + } + } + scene.nodes = [rootNodes copy]; + + scene.name = properties[@"name"]; + scene.extensions = properties[@"extensions"]; + scene.extras = properties[@"extras"]; + + if (_usesKHRLights) { + NSDictionary *lightProperties = scene.extensions[GLTFExtensionKHRLights]; + NSNumber *lightIdentifierValue = lightProperties[@"light"]; + if (lightIdentifierValue != nil && lightIdentifierValue.integerValue < _lights.count) { + scene.ambientLight = _lights[lightIdentifierValue.integerValue]; + } + } + + [scenes addObject:scene]; + } + + _scenes = [scenes copy]; + + return YES; +} + +- (BOOL)loadDefaultScene:(NSNumber *)defaultSceneIndexValue +{ + if (defaultSceneIndexValue != nil) { + NSUInteger defaultSceneIndex = defaultSceneIndexValue.integerValue; + if (defaultSceneIndex < _scenes.count) { + _defaultScene = _scenes[defaultSceneIndex]; + } + } else { + _defaultScene = _scenes.firstObject; + } + + return YES; +} + +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.h b/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.h new file mode 100644 index 000000000000..593b8329f29d --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import + +extern const UInt32 GLTFBinaryMagic; + +typedef NS_ENUM(NSInteger, GLTFChunkType) { + GLTFChunkTypeJSON = 0x4E4F534A, + GLTFChunkTypeBinary = 0x004E4942 +}; + +typedef struct { + UInt32 magic; + UInt32 version; + UInt32 length; +} GLTFBinaryHeader; + +@interface GLTFBinaryChunk : NSObject +@property (nonatomic, assign) GLTFChunkType chunkType; +@property (nonatomic, strong) NSData *data; +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.m b/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.m new file mode 100644 index 000000000000..415273fddf3c --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.m @@ -0,0 +1,23 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFBinaryChunk.h" + +const UInt32 GLTFBinaryMagic = 0x46546C67; + +@implementation GLTFBinaryChunk +@end + diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBuffer.h b/platform/darwin/src/gltf/gltfkit/GLTFBuffer.h new file mode 100644 index 000000000000..0be3d201b020 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFBuffer.h @@ -0,0 +1,30 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFObject.h" + +NS_ASSUME_NONNULL_BEGIN + +@protocol GLTFBuffer + +@property (nonatomic, readonly) NSInteger length; + +/// The actual data associated with this buffer. If uri is a data URI, this is populated when loading; else it is nil +@property (nonatomic, readonly) void *contents; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBufferAllocator.h b/platform/darwin/src/gltf/gltfkit/GLTFBufferAllocator.h new file mode 100644 index 000000000000..126168d7032b --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFBufferAllocator.h @@ -0,0 +1,29 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFBuffer.h" + +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol GLTFBufferAllocator ++ (uint64_t)liveAllocationSize; +- (id)newBufferWithLength:(NSInteger)length; +- (id)newBufferWithData:(NSData *)data; +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBufferView.h b/platform/darwin/src/gltf/gltfkit/GLTFBufferView.h new file mode 100644 index 000000000000..2b41ec2f46c7 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFBufferView.h @@ -0,0 +1,32 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFObject.h" +#import "GLTFEnums.h" + +NS_ASSUME_NONNULL_BEGIN + +@protocol GLTFBuffer; + +@interface GLTFBufferView : GLTFObject +@property (nonatomic, weak) id buffer; +@property (nonatomic, assign) GLTFTarget target; +@property (nonatomic, assign) NSInteger length; +@property (nonatomic, assign) NSInteger offset; +@property (nonatomic, assign) NSInteger stride; +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBufferView.m b/platform/darwin/src/gltf/gltfkit/GLTFBufferView.m new file mode 100644 index 000000000000..3d4ba74ec15a --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFBufferView.m @@ -0,0 +1,26 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFBufferView.h" + +@implementation GLTFBufferView + +- (NSString *)description { + return [NSString stringWithFormat:@"GLTFBufferView: length: %d, offset: %d, stride: %d, target: %d, buffer: %@", + (int)self.length, (int)self.offset, (int)self.stride, (int)self.target, self.buffer]; +} + +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFCamera.h b/platform/darwin/src/gltf/gltfkit/GLTFCamera.h new file mode 100644 index 000000000000..2d710a7ffcb6 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFCamera.h @@ -0,0 +1,42 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFObject.h" +#import "GLTFEnums.h" + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class GLTFNode; + +@interface GLTFCamera : GLTFObject +@property (nonatomic, assign) GLTFCameraType cameraType; + +@property (nonatomic, assign) float aspectRatio; // Only applicable when type is perspective +@property (nonatomic, assign) float yfov; // Only applicable when type is perspective +@property (nonatomic, assign) float xmag; // Only applicable when type is orthographic +@property (nonatomic, assign) float ymag; // Only applicable when type is orthographic +@property (nonatomic, assign) float znear; +@property (nonatomic, assign) float zfar; + +@property (nonatomic, assign) simd_float4x4 projectionMatrix; + +@property (nonatomic, copy) NSArray *referencingNodes; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFCamera.m b/platform/darwin/src/gltf/gltfkit/GLTFCamera.m new file mode 100644 index 000000000000..fd2d9c27a169 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFCamera.m @@ -0,0 +1,115 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFCamera.h" + +@interface GLTFCamera () +@property (nonatomic, assign, getter=projectionMatrixIsDirty) BOOL projectionMatrixDirty; +@end + +@implementation GLTFCamera + +@synthesize projectionMatrix=_projectionMatrix; + +- (instancetype)init { + if ((self = [super init])) { + _referencingNodes = @[]; + } + return self; +} + +- (void)setCameraType:(GLTFCameraType)cameraType { + _cameraType = cameraType; + _projectionMatrixDirty = YES; +} + +- (void)setAspectRatio:(float)aspectRatio { + _aspectRatio = aspectRatio; + _projectionMatrixDirty = YES; +} + +- (void)setYfov:(float)yfov { + _yfov = yfov; + _projectionMatrixDirty = YES; +} + +- (void)setXmag:(float)xmag { + _xmag = xmag; + _projectionMatrixDirty = YES; +} + +- (void)setYmag:(float)ymag { + _ymag = ymag; + _projectionMatrixDirty = YES; +} + +- (void)setZnear:(float)znear { + _znear = znear; + _projectionMatrixDirty = YES; +} + +- (void)setZfar:(float)zfar { + _zfar = zfar; + _projectionMatrixDirty = YES; +} + +- (void)setProjectionMatrix:(simd_float4x4)projectionMatrix { + _projectionMatrix = projectionMatrix; + _projectionMatrixDirty = NO; +} + +- (simd_float4x4)projectionMatrix { + if (self.projectionMatrixIsDirty) { + [self _buildProjectionMatrix]; + } + return _projectionMatrix; +} + +- (void)_buildProjectionMatrix { + switch (_cameraType) { + case GLTFCameraTypeOrthographic: { + simd_float4 X = (simd_float4){ 1 / _xmag, 0, 0, 0 }; + simd_float4 Y = (simd_float4){ 0, 1 / _ymag, 0, 0 }; + simd_float4 Z = (simd_float4){ 0, 0, 2 / (_znear - _zfar), 0 }; + simd_float4 W = (simd_float4){ 0, 0, (_zfar + _znear) / (_znear - _zfar), 1 }; + _projectionMatrix = (simd_float4x4){ { X, Y, Z, W } }; + break; + } + case GLTFCameraTypePerspective: + default: { + simd_float4 X = (simd_float4){ 1 / (_aspectRatio * tanf(0.5 * _yfov)), 0, 0, 0 }; + simd_float4 Y = (simd_float4){ 0, 1 / tanf(0.5 * _yfov), 0, 0 }; + simd_float4 Z = (simd_float4){ 0, 0, -1, -1 }; + simd_float4 W = (simd_float4){ 0, 0, -2 * _znear, 0 }; + if (_zfar != FLT_MAX) { + Z = (simd_float4){ 0, 0, (_zfar + _znear) / (_znear - _zfar), -1 }; + W = (simd_float4){ 0, 0, (2 * _zfar * _znear) / (_znear - _zfar), 0 }; + } + _projectionMatrix = (simd_float4x4){ { X, Y, Z, W } }; + break; + } + } + simd_float4x4 glToMetal = (simd_float4x4){{ + { 1, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 0, 0, 0.5, 0 }, + { 0, 0, 0.5, 1 }, + }}; + _projectionMatrix = simd_mul(glToMetal, _projectionMatrix); + _projectionMatrixDirty = NO; +} + +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.h b/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.h new file mode 100644 index 000000000000..8382ba773a9f --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.h @@ -0,0 +1,27 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import + +#import "GLTFBufferAllocator.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface GLTFDefaultBufferAllocator : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.m b/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.m new file mode 100644 index 000000000000..d27ceba2cbfb --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.m @@ -0,0 +1,93 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFDefaultBufferAllocator.h" + +static uint64_t _liveAllocationSize; + +@interface GLTFDefaultBufferAllocator () ++ (void)incrementLiveAllocationSizeByLength:(uint64_t)length; ++ (void)decrementLiveAllocationSizeByLength:(uint64_t)length; +@end + +@interface GLTFMemoryBuffer: NSObject +@property (nonatomic, assign) void *bytes; +@property (nonatomic, assign) NSInteger length; +- (instancetype)initWithLength:(NSInteger)length; +- (instancetype)initWithData:(NSData *)data; +@end + +@implementation GLTFMemoryBuffer + +@synthesize name; +@synthesize extras; +@synthesize extensions; + +- (instancetype)initWithLength:(NSInteger)length { + if ((self = [super init])) { + _bytes = malloc(length); + _length = length; + [GLTFDefaultBufferAllocator incrementLiveAllocationSizeByLength:_length]; + } + return self; +} + +- (instancetype)initWithData:(NSData *)data { + if ((self = [super init])) { + _length = data.length; + _bytes = malloc(_length); + memcpy(_bytes, data.bytes, _length); + [GLTFDefaultBufferAllocator incrementLiveAllocationSizeByLength:_length]; + } + return self; +} + +- (void)dealloc { + free(_bytes); + [GLTFDefaultBufferAllocator decrementLiveAllocationSizeByLength:_length]; +} + +- (void *)contents NS_RETURNS_INNER_POINTER { + return self.bytes; +} + +@end + +@implementation GLTFDefaultBufferAllocator + ++ (void)incrementLiveAllocationSizeByLength:(uint64_t)length { + _liveAllocationSize += length; +} + ++ (void)decrementLiveAllocationSizeByLength:(uint64_t)length { + _liveAllocationSize -= length; +} + ++ (uint64_t)liveAllocationSize { + return _liveAllocationSize; +} + +- (id)newBufferWithLength:(NSInteger)length { + GLTFMemoryBuffer *buffer = [[GLTFMemoryBuffer alloc] initWithLength:length]; + return buffer; +} + +- (id)newBufferWithData:(NSData *)data { + GLTFMemoryBuffer *buffer = [[GLTFMemoryBuffer alloc] initWithData:data]; + return buffer; +} + +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFEnums.h b/platform/darwin/src/gltf/gltfkit/GLTFEnums.h new file mode 100644 index 000000000000..dbf5177be5fb --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFEnums.h @@ -0,0 +1,178 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import + +typedef NS_ENUM(NSInteger, GLTFDataType) { + GLTFBaseTypeUnknown, + GLTFDataTypeChar = 0x1400, + GLTFDataTypeUChar = 0x1401, + GLTFDataTypeShort = 0x1402, + GLTFDataTypeUShort = 0x1403, + GLTFDataTypeInt = 0x1404, + GLTFDataTypeUInt = 0x1405, + GLTFDataTypeFloat = 0x1406, + + GLTFDataTypeFloat2 = 0x8B50, + GLTFDataTypeFloat3 = 0x8B51, + GLTFDataTypeFloat4 = 0x8B52, + GLTFDataTypeInt2 = 0x8B53, + GLTFDataTypeInt3 = 0x8B54, + GLTFDataTypeInt4 = 0x8B55, + GLTFDataTypeBool = 0x8B56, + GLTFDataTypeBool2 = 0x8B57, + GLTFDataTypeBool3 = 0x8B58, + GLTFDataTypeBool4 = 0x8B59, + GLTFDataTypeFloat2x2 = 0x8B5A, + GLTFDataTypeFloat3x3 = 0x8B5B, + GLTFDataTypeFloat4x4 = 0x8B5C, + GLTFDataTypeSampler2D = 0x8B5E, +}; + +typedef NS_ENUM(NSInteger, GLTFDataDimension) { + GLTFDataDimensionUnknown, + GLTFDataDimensionScalar, + GLTFDataDimensionVector2, + GLTFDataDimensionVector3, + GLTFDataDimensionVector4, + GLTFDataDimensionMatrix2x2, + GLTFDataDimensionMatrix3x3, + GLTFDataDimensionMatrix4x4, +}; + +typedef NS_ENUM(NSInteger, GLTFTarget) { + GLTFTargetUnknown, + GLTFTargetArrayBuffer = 0x8892, + GLTFTargetElementArrayBuffer = 0x8893, +}; + +typedef NS_ENUM(NSInteger, GLTFPrimitiveType) { + GLTFPrimitiveTypePoints, + GLTFPrimitiveTypeLines, + GLTFPrimitiveTypeLineLoop, + GLTFPrimitiveTypeLineStrip, + GLTFPrimitiveTypeTriangles, + GLTFPrimitiveTypeTriangleStrip, + GLTFPrimitiveTypeTriangleFan, +}; + +typedef NS_ENUM(NSInteger, GLTFCameraType) { + GLTFCameraTypePerspective, + GLTFCameraTypeOrthographic, +}; + +typedef NS_ENUM(NSInteger, GLTFTextureTarget) { + GLTFTextureTargetTexture2D = 0x0DE1, +}; + +typedef NS_ENUM(NSInteger, GLTFTextureFormat) { + GLTFTextureFormatUnknown, + GLTFTextureFormatAlpha = 0x1906, + GLTFTextureFormatRGB = 0x1907, + GLTFTextureFormatRGBA = 0x1908, + GLTFTextureFormatLuminance = 0x1909, + GLTFTextureFormatLuminanceAlpha = 0x190A, +}; + +typedef NS_ENUM(NSInteger, GLTFTextureType) { + GLTFTextureTypeUnknown, + GLTFTextureTypeUChar = 0x1401, + GLTFTextureTypeUShort565 = 0x8363, + GLTFTextureTypeUShort4444 = 0x8033, + GLTFTextureTypeUShort5551 = 0x8034, +}; + +typedef NS_ENUM(NSInteger, GLTFShaderType) { + GLTFShaderTypeVertex = 0x8B31, + GLTFShaderTypeFragment = 0x8B30, +}; + +typedef NS_ENUM(NSInteger, GLTFSamplingFilter) { + GLTFSamplingFilterUnknown, + GLTFSamplingFilterNearest = 0x2600, + GLTFSamplingFilterLinear = 0x2601, + GLTFSamplingFilterNearestMipNearest = 0x2700, + GLTFSamplingFilterLinearMipNearest = 0x2701, + GLTFSamplingFilterNearestMipLinear = 0x2702, + GLTFSamplingLinearMipLinear = 0x2703, +}; + +typedef NS_ENUM(NSInteger, GLTFAddressMode) { + GLTFAddressModeUnknown, + GLTFAddressModeClampToEdge = 0x812F, + GLTFAddressModeMirroredRepeat = 0x8370, + GLTFAddressModeRepeat = 0x2901, +}; + +typedef NS_ENUM(NSInteger, GLTFComparisonFunc) { + GLTFComparisonFuncLess = 0x0201, + GLTFComparisonFuncEqual = 0x0202, + GLTFComparisonFuncLessEqual = 0x0203, + GLTFComparisonFuncGreater = 0x0204, + GLTFComparisonFuncNotEqual = 0x0205, + GLTFComparisonFuncGreaterEqual = 0x0206, + GLTFComparisonFuncAlways = 0x0207, +}; + +typedef NS_ENUM(NSInteger, GLTFFace) { + GLTFFaceFront = 0x0404, + GLTFFaceBack = 0x405, + GLTFFaceFrontAndBack = 0x408, +}; + +typedef NS_ENUM(NSInteger, GLTFWinding) { + GLTFWindingClockwise = 0x900, + GLTFWindingCounterclockwise = 0x0901, +}; + +typedef NS_ENUM(NSInteger, GLTFState) { + GLTFStateBlendingEnabled = 0x0BE2, + GLTFStateCullFaceEnabled = 0x0B44, + GLTFStateDepthTestEnabled = 0x0B71, + GLTFStatePolygonOffsetFillEnabled = 0x8037, + GLTFStateAlphaToCoverageEnabled = 0x809E, + GLTFStateScissorTestEnabled = 0x0C11, +}; + +typedef NS_ENUM(NSInteger, GLTFBlendFunction) { + GLTFBlendFunctionAdd = 0x8006, + GLTFBlendFunctionSubtract = 0x800A, + GLTFBlendFunctionReverseSubtract = 0x800B, +}; + +typedef NS_ENUM(NSInteger, GLTFBlendEquation) { + GLTFBlendEquationZero = 0x0000, + GLTFBlendEquationOne = 0x0001, + GLTFBlendEquationSrcColor = 0x0300, + GLTFBlendEquationOneMinusSrcColor = 0x0301, + GLTFBlendEquationSrcAlpha = 0x0302, + GLTFBlendEquationOneMinusSrcAlpha = 0x0303, + GLTFBlendEquationDestAlpha = 0x0304, + GLTFBlendEquationOneMinusDestAlpha = 0x0305, + GLTFBlendEquationDestColor = 0x0306, + GLTFBlendEquationOneMinusDestColor = 0x0307, + GLTFBlendEquationSrcAlphaSaturate = 0x0308, + GLTFBlendEquationConstantColor = 0x8001, + GLTFBlendEquationOneMinusConstColor = 0x8002, + GLTFBlendEquationConstantAlpha = 0x8003, + GLTFBlendEquationOneMinusConstAlpha = 0x8004, +}; + +typedef NS_ENUM(NSInteger, GLTFInterpolationMode) { + GLTFInterpolationModeStep, + GLTFInterpolationModeLinear, + GLTFInterpolationModeCubic, +}; diff --git a/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.h b/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.h new file mode 100644 index 000000000000..b219b6c004dd --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.h @@ -0,0 +1,23 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import + +extern NSString *const GLTFExtensionKHRMaterialsPBRSpecularGlossiness; +extern NSString *const GLTFExtensionKHRLights; +extern NSString *const GLTFExtensionKHRMaterialsUnlit; +extern NSString *const GLTFExtensionKHRTextureTransform; +extern NSString *const GLTFExtensionEXTPBRAttributes; diff --git a/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.m b/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.m new file mode 100644 index 000000000000..a531b33a8987 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.m @@ -0,0 +1,23 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFExtensionNames.h" + +NSString *const GLTFExtensionKHRMaterialsPBRSpecularGlossiness = @"KHR_materials_pbrSpecularGlossiness"; +NSString *const GLTFExtensionKHRLights = @"KHR_lights"; +NSString *const GLTFExtensionKHRMaterialsUnlit = @"KHR_materials_unlit"; +NSString *const GLTFExtensionKHRTextureTransform = @"KHR_texture_transform"; +NSString *const GLTFExtensionEXTPBRAttributes = @"EXT_pbr_attributes"; diff --git a/platform/darwin/src/gltf/gltfkit/GLTFImage.h b/platform/darwin/src/gltf/gltfkit/GLTFImage.h new file mode 100644 index 000000000000..ce444daff386 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFImage.h @@ -0,0 +1,40 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFObject.h" +#import "GLTFBufferView.h" + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface GLTFImage : GLTFObject + +/// A reference to a buffer view containing image data, if url is nil +@property (nonatomic, strong) GLTFBufferView * _Nullable bufferView; + +/// The MIME type of the data contained in this image's buffer view +@property (nonatomic, copy) NSString * _Nullable mimeType; + +/// A file URL, if the URI was not a decodable data-uri; otherwise nil +@property (nonatomic, copy) NSURL * _Nullable url; + +/// A data object containing the data encoded in the image's data-uri, if present; otherwise nil +@property (nonatomic, strong) NSData *imageData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFImage.m b/platform/darwin/src/gltf/gltfkit/GLTFImage.m new file mode 100644 index 000000000000..b45f287d95e1 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFImage.m @@ -0,0 +1,57 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFImage.h" + +#import + +@implementation GLTFImage + ++ (CGImageRef)newImageForData:(NSData *)data mimeType:(NSString *)mimeType { + CGImageRef image = NULL; + CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data); + if ([mimeType isEqualToString:@"image/jpeg"]) { + image = CGImageCreateWithJPEGDataProvider(provider, NULL, false, kCGRenderingIntentDefault); + } else if ([mimeType isEqualToString:@"image/png"]) { + image = CGImageCreateWithPNGDataProvider(provider, NULL, false, kCGRenderingIntentDefault); + } else { + NSLog(@"Unknown MIME type encountered when decoding image: %@", mimeType); + } + CGDataProviderRelease(provider); + return image; +} + ++ (CGImageRef)newImageForDataURI:(NSString *)uriData { + NSString *prefix = @"data:"; + if ([uriData hasPrefix:prefix]) { + NSInteger prefixEnd = prefix.length; + NSInteger firstComma = [uriData rangeOfString:@","].location; + if (firstComma != NSNotFound) { + NSString *mediaTypeAndTokenString = [uriData substringWithRange:NSMakeRange(prefixEnd, firstComma - prefixEnd)]; + NSArray *mediaTypeAndToken = [mediaTypeAndTokenString componentsSeparatedByString:@";"]; + if (mediaTypeAndToken.count > 0) { + NSString *mediaType = mediaTypeAndToken.firstObject; + NSString *encodedImageData = [uriData substringFromIndex:firstComma + 1]; + NSData *imageData = [[NSData alloc] initWithBase64EncodedString:encodedImageData + options:NSDataBase64DecodingIgnoreUnknownCharacters]; + return [self newImageForData:imageData mimeType:mediaType]; + } + } + } + return NULL; +} + +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.h b/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.h new file mode 100644 index 000000000000..3848b78488bb --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.h @@ -0,0 +1,53 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFObject.h" + +#import + +typedef NS_ENUM(NSInteger, GLTFKHRLightType) { + GLTFKHRLightTypeAmbient, + GLTFKHRLightTypeDirectional, + GLTFKHRLightTypePoint, + GLTFKHRLightTypeSpot, +}; + +@interface GLTFKHRLight : GLTFObject + +@property (nonatomic, assign) GLTFKHRLightType type; + +/// Color of light in a linear RGB color space +@property (nonatomic, assign) simd_float4 color; + +/// Brightness of light. Point and spot lights use luminous intensity in candela (lm/sr), +/// while directional lights use illuminance in lux (lm/m^2). +@property (nonatomic, assign) float intensity; + +/// Distance threshold at which the light's intensity may be considered to have reached zero, +/// expressed in meters. Default is 0, signifying effectively infinite range. +@property (nonatomic, assign) float range; + +/// Angle, in radians, from the center of a spotlight to where falloff begins. +/// Must be greater than or equal to 0, less than or equal to `outerConeAngle`, +/// and less than pi / 2. Default value is 0. +@property (nonatomic, assign) float innerConeAngle; + +/// Angle, in radians, from the center of a spotlight to where falloff ends. +/// Must be greater than or equal to 0, greater than or equal to `innerConeAngle`, +/// and less than pi / 2. Default value is pi / 4. +@property (nonatomic, assign) float outerConeAngle; + +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.m b/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.m new file mode 100644 index 000000000000..eff3be6aeff2 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.m @@ -0,0 +1,33 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFKHRLight.h" + +@implementation GLTFKHRLight + +- (instancetype)init { + if ((self = [super init])) { + _type = GLTFKHRLightTypeDirectional; + _color = (simd_float4){ 1, 1, 1, 1 }; + _intensity = 1; + _range = 0; + _innerConeAngle = 0; + _outerConeAngle = M_PI_4; + } + return self; +} + +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.h b/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.h new file mode 100644 index 000000000000..fe422fe80ec9 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.h @@ -0,0 +1,36 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFBuffer.h" +#import "GLTFBufferAllocator.h" +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface GLTFMTLBuffer : NSObject + +@property (nonatomic, readonly) id buffer; + +@end + +@interface GLTFMTLBufferAllocator : NSObject + +- (instancetype)initWithDevice:(id)device; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.m b/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.m new file mode 100644 index 000000000000..c1bf44f1387d --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.m @@ -0,0 +1,101 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFMTLBufferAllocator.h" + +#import + +static uint64_t _liveAllocationSize; + +@interface GLTFMTLBufferAllocator () ++ (void)incrementLiveAllocationSizeByLength:(uint64_t)length; ++ (void)decrementLiveAllocationSizeByLength:(uint64_t)length; +@end + +@interface GLTFMTLBuffer () +@property (nonatomic, strong) id buffer; + +- (instancetype)initWithBuffer:(id)buffer; + +@end + +@implementation GLTFMTLBuffer + +@synthesize name; +@synthesize extras; +@synthesize extensions; + +- (instancetype)initWithBuffer:(id)buffer { + if ((self = [super init])) { + _buffer = buffer; + [GLTFMTLBufferAllocator incrementLiveAllocationSizeByLength:_buffer.length]; + } + return self; +} + +- (void)dealloc { + [GLTFMTLBufferAllocator decrementLiveAllocationSizeByLength:_buffer.length]; +} + +- (NSInteger)length { + return [self.buffer length]; +} + +- (void *)contents { + return [self.buffer contents]; +} + +@end + +@interface GLTFMTLBufferAllocator () +@property (nonatomic, strong) id device; +@end + +@implementation GLTFMTLBufferAllocator + ++ (void)incrementLiveAllocationSizeByLength:(uint64_t)length { + _liveAllocationSize += length; +} + ++ (void)decrementLiveAllocationSizeByLength:(uint64_t)length { + _liveAllocationSize -= length; +} + ++ (uint64_t)liveAllocationSize { + return _liveAllocationSize; +} + +- (instancetype)initWithDevice:(id)device { + if ((self = [super init])) { + _device = device; + } + return self; +} + +- (id)newBufferWithLength:(NSInteger)length { + MTLResourceOptions options = MTLResourceCPUCacheModeDefaultCache | MTLResourceStorageModeShared; + id underlying = [self.device newBufferWithLength:length options:options]; + return [[GLTFMTLBuffer alloc] initWithBuffer:underlying]; +} + + +- (id)newBufferWithData:(NSData *)data { + MTLResourceOptions options = MTLResourceCPUCacheModeDefaultCache | MTLResourceStorageModeShared; + id underlying = [self.device newBufferWithBytes:data.bytes length:data.length options:options]; + return [[GLTFMTLBuffer alloc] initWithBuffer:underlying]; +} + +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.h b/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.h new file mode 100644 index 000000000000..4e35d6a9f47d --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFMTLUtilities.h" +#import "GLTFMesh.h" + +#import + +// Maximum number of textures supplied by a material; excludes IBL textures, etc. + +NS_ASSUME_NONNULL_BEGIN + +@class GLTFMTLLightingEnvironment; + +@interface GLTFMTLShaderBuilder : NSObject + +- (id)renderPipelineStateForSubmesh:(GLTFSubmesh *)submesh + // lightingEnvironment:(GLTFMTLLightingEnvironment * _Nullable)lightingEnvironment + colorPixelFormat:(MTLPixelFormat)colorPixelFormat + depthStencilPixelFormat:(MTLPixelFormat)depthStencilPixelFormat + sampleCount:(int)sampleCount + device:(id)device; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.m b/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.m new file mode 100644 index 000000000000..835017d4876e --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.m @@ -0,0 +1,246 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + + +#import "GLTFMTLShaderBuilder.h" +#import "GLTFMesh.h" +#import "GLTFMaterial.h" +#import "GLTFVertexDescriptor.h" +#import "GLTFAccessor.h" +#import "../GLTFMath.hpp" + +@implementation GLTFMTLShaderBuilder + +- (id)renderPipelineStateForSubmesh:(GLTFSubmesh *)submesh + // lightingEnvironment:(GLTFMTLLightingEnvironment *)lightingEnvironment + colorPixelFormat:(MTLPixelFormat)colorPixelFormat + depthStencilPixelFormat:(MTLPixelFormat)depthStencilPixelFormat + sampleCount:(int)sampleCount + device:(id)device +{ + NSParameterAssert(submesh); + NSParameterAssert(submesh.material); + NSParameterAssert(submesh.vertexDescriptor); + + NSError *error = nil; + NSString *shaderSource = [self shaderSource]; + + shaderSource = [self rewriteSource:shaderSource forSubmesh:submesh]; + + id library = [device newLibraryWithSource:shaderSource options:nil error:&error]; + if (!library) { + NSLog(@"Error occurred while creating library for material : %@", error); + return nil; + } + + id vertexFunction = nil; + id fragmentFunction = nil; + + for (NSString *functionName in [library functionNames]) { + id function = [library newFunctionWithName:functionName]; + if ([function functionType] == MTLFunctionTypeVertex) { + vertexFunction = function; + } else if ([function functionType] == MTLFunctionTypeFragment) { + fragmentFunction = function; + } + } + + if (!vertexFunction || !fragmentFunction) { + NSLog(@"Failed to find a vertex and fragment function in library source"); + return nil; + } + + MTLVertexDescriptor *vertexDescriptor = [self vertexDescriptorForSubmesh: submesh]; + + MTLRenderPipelineDescriptor *pipelineDescriptor = [MTLRenderPipelineDescriptor new]; + pipelineDescriptor.vertexFunction = vertexFunction; + pipelineDescriptor.fragmentFunction = fragmentFunction; + pipelineDescriptor.vertexDescriptor = vertexDescriptor; + + pipelineDescriptor.colorAttachments[0].pixelFormat = colorPixelFormat; + pipelineDescriptor.sampleCount = sampleCount; + + if (submesh.material.alphaMode == GLTFAlphaModeBlend) { + pipelineDescriptor.colorAttachments[0].blendingEnabled = YES; + pipelineDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; + pipelineDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd; + pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne; + pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne; + pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha; + pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha; + } + + pipelineDescriptor.depthAttachmentPixelFormat = depthStencilPixelFormat; +// pipelineDescriptor.stencilAttachmentPixelFormat = depthStencilPixelFormat; + + id pipeline = [device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:&error]; + if (!pipeline) { + NSLog(@"Error occurred when creating render pipeline state: %@", error); + } + + return pipeline; +} + +- (NSString *)shaderSource { + NSError *error = nil; + // TODO: Figure out why Bazel won't embed the .metal files + NSURL *shaderURL = [[NSBundle mainBundle] URLForResource:@"pbr" withExtension:@"txt"]; + if (shaderURL == nil) { + NSLog(@"ERROR: Shader source not found in main bundle; pipeline states cannot be generated"); + } + return [NSString stringWithContentsOfURL:shaderURL encoding:NSUTF8StringEncoding error:&error]; +} + +- (NSString *)rewriteSource:(NSString *)source + forSubmesh:(GLTFSubmesh *)submesh +{ + GLTFMaterial *material = submesh.material; + + BOOL usePBR = YES; + BOOL useIBL = NO; // lightingEnvironment != nil; + BOOL useDoubleSided = material.isDoubleSided; + BOOL hasTexCoord0 = submesh.accessorsForAttributes[GLTFAttributeSemanticTexCoord0] != nil; + BOOL hasTexCoord1 = submesh.accessorsForAttributes[GLTFAttributeSemanticTexCoord1] != nil; + BOOL hasNormals = submesh.accessorsForAttributes[GLTFAttributeSemanticNormal] != nil; + BOOL hasTangents = submesh.accessorsForAttributes[GLTFAttributeSemanticTangent] != nil; + BOOL hasBaseColorMap = material.baseColorTexture != nil; + BOOL hasOcclusionMap = material.occlusionTexture != nil; + BOOL hasEmissiveMap = material.emissiveTexture != nil; + BOOL hasNormalMap = material.normalTexture != nil; + BOOL hasMetallicRoughnessMap = material.metallicRoughnessTexture != nil; + BOOL hasTextureTransforms = material.hasTextureTransforms; + BOOL hasSkinningData = submesh.accessorsForAttributes[GLTFAttributeSemanticJoints0] != nil && + submesh.accessorsForAttributes[GLTFAttributeSemanticWeights0] != nil; + BOOL hasExtendedSkinning = submesh.accessorsForAttributes[GLTFAttributeSemanticJoints1] != nil && + submesh.accessorsForAttributes[GLTFAttributeSemanticWeights1] != nil; + BOOL hasVertexColor = submesh.accessorsForAttributes[GLTFAttributeSemanticColor0] != nil; + BOOL vertexColorIsRGB = submesh.accessorsForAttributes[GLTFAttributeSemanticColor0].dimension == GLTFDataDimensionVector3; + BOOL hasVertexRoughness = submesh.accessorsForAttributes[GLTFAttributeSemanticRoughness] != nil; + BOOL hasVertexMetallic = submesh.accessorsForAttributes[GLTFAttributeSemanticMetallic] != nil; + BOOL premultiplyBaseColor = material.alphaMode == GLTFAlphaModeBlend; + BOOL materialIsUnlit = material.isUnlit; + BOOL useAlphaTest = material.alphaMode == GLTFAlphaModeMask; + + NSMutableString *shaderFeatures = [NSMutableString string]; + [shaderFeatures appendFormat:@"#define USE_PBR %d\n", usePBR]; + [shaderFeatures appendFormat:@"#define USE_IBL %d\n", useIBL]; + [shaderFeatures appendFormat:@"#define USE_ALPHA_TEST %d\n", useAlphaTest]; + [shaderFeatures appendFormat:@"#define USE_VERTEX_SKINNING %d\n", hasSkinningData]; + [shaderFeatures appendFormat:@"#define USE_EXTENDED_VERTEX_SKINNING %d\n", hasExtendedSkinning]; + [shaderFeatures appendFormat:@"#define USE_DOUBLE_SIDED_MATERIAL %d\n", useDoubleSided]; + [shaderFeatures appendFormat:@"#define HAS_TEXCOORD_0 %d\n", hasTexCoord0]; + [shaderFeatures appendFormat:@"#define HAS_TEXCOORD_1 %d\n", hasTexCoord1]; + [shaderFeatures appendFormat:@"#define HAS_NORMALS %d\n", hasNormals]; + [shaderFeatures appendFormat:@"#define HAS_TANGENTS %d\n", hasTangents]; + [shaderFeatures appendFormat:@"#define HAS_VERTEX_COLOR %d\n", hasVertexColor]; + [shaderFeatures appendFormat:@"#define VERTEX_COLOR_IS_RGB %d\n", vertexColorIsRGB]; + [shaderFeatures appendFormat:@"#define HAS_BASE_COLOR_MAP %d\n", hasBaseColorMap]; + [shaderFeatures appendFormat:@"#define HAS_NORMAL_MAP %d\n", hasNormalMap]; + [shaderFeatures appendFormat:@"#define HAS_METALLIC_ROUGHNESS_MAP %d\n", hasMetallicRoughnessMap]; + [shaderFeatures appendFormat:@"#define HAS_OCCLUSION_MAP %d\n", hasOcclusionMap]; + [shaderFeatures appendFormat:@"#define HAS_EMISSIVE_MAP %d\n", hasEmissiveMap]; + [shaderFeatures appendFormat:@"#define HAS_VERTEX_ROUGHNESS %d\n", hasVertexRoughness]; + [shaderFeatures appendFormat:@"#define HAS_VERTEX_METALLIC %d\n", hasVertexMetallic]; + [shaderFeatures appendFormat:@"#define HAS_TEXTURE_TRANSFORM %d\n", hasTextureTransforms]; + [shaderFeatures appendFormat:@"#define PREMULTIPLY_BASE_COLOR %d\n", premultiplyBaseColor]; + [shaderFeatures appendFormat:@"#define MATERIAL_IS_UNLIT %d\n", materialIsUnlit]; + [shaderFeatures appendFormat:@"#define SPECULAR_ENV_MIP_LEVELS %d\n", 0]; // lightingEnvironment.specularMipLevelCount]; + [shaderFeatures appendFormat:@"#define MAX_LIGHTS %d\n", (int)GLTFMTLMaximumLightCount]; + [shaderFeatures appendFormat:@"#define MAX_MATERIAL_TEXTURES %d\n\n", (int)GLTFMTLMaximumTextureCount]; + + [shaderFeatures appendFormat:@"#define BaseColorTexCoord texCoord%d\n", (int)material.baseColorTexture.texCoord]; + [shaderFeatures appendFormat:@"#define NormalTexCoord texCoord%d\n", (int)material.normalTexture.texCoord]; + [shaderFeatures appendFormat:@"#define MetallicRoughnessTexCoord texCoord%d\n", (int)material.metallicRoughnessTexture.texCoord]; + [shaderFeatures appendFormat:@"#define EmissiveTexCoord texCoord%d\n", (int)material.emissiveTexture.texCoord]; + [shaderFeatures appendFormat:@"#define OcclusionTexCoord texCoord%d\n\n", (int)material.occlusionTexture.texCoord]; + + NSString *preamble = @"struct VertexIn {\n"; + NSString *epilogue = @"\n};"; + + NSMutableArray *attribs = [NSMutableArray array]; + int i = 0; + for (GLTFVertexAttribute *attribute in submesh.vertexDescriptor.attributes) { + if (attribute.componentType == GLTFBaseTypeUnknown) { continue; } + if ([attribute.semantic isEqualToString:GLTFAttributeSemanticPosition]) { + [attribs addObject:[NSString stringWithFormat:@" %@ position [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; + } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticNormal]) { + [attribs addObject:[NSString stringWithFormat:@" %@ normal [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; + } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticTangent]) { + [attribs addObject:[NSString stringWithFormat:@" %@ tangent [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; + } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticTexCoord0]) { + [attribs addObject:[NSString stringWithFormat:@" %@ texCoord0 [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; + } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticTexCoord1]) { + [attribs addObject:[NSString stringWithFormat:@" %@ texCoord1 [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; + } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticColor0]) { + [attribs addObject:[NSString stringWithFormat:@" %@ color [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; + } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticJoints0]) { + [attribs addObject:[NSString stringWithFormat:@" %@ joints0 [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; + } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticJoints1]) { + [attribs addObject:[NSString stringWithFormat:@" %@ joints1 [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; + } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticWeights0]) { + [attribs addObject:[NSString stringWithFormat:@" %@ weights0 [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; + } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticWeights1]) { + [attribs addObject:[NSString stringWithFormat:@" %@ weights1 [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; + } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticRoughness]) { + [attribs addObject:[NSString stringWithFormat:@" %@ roughness [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; + } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticMetallic]) { + [attribs addObject:[NSString stringWithFormat:@" %@ metalness [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; + } + + ++i; + } + + NSString *decls = [NSString stringWithFormat:@"%@%@%@%@", + shaderFeatures, preamble, [attribs componentsJoinedByString:@"\n"], epilogue]; + + NSRange startSigilRange = [source rangeOfString:@"/*%begin_replace_decls%*/"]; + NSRange endSigilRange = [source rangeOfString:@"/*%end_replace_decls%*/"]; + + NSRange declRange = NSUnionRange(startSigilRange, endSigilRange); + + source = [source stringByReplacingCharactersInRange:declRange withString:decls]; + + return source; +} + +- (MTLVertexDescriptor *)vertexDescriptorForSubmesh:(GLTFSubmesh *)submesh { + MTLVertexDescriptor *vertexDescriptor = [MTLVertexDescriptor new]; + + GLTFVertexDescriptor *descriptor = submesh.vertexDescriptor; + + for (NSInteger attributeIndex = 0; attributeIndex < GLTFVertexDescriptorMaxAttributeCount; ++attributeIndex) { + GLTFVertexAttribute *attribute = descriptor.attributes[attributeIndex]; + GLTFBufferLayout *layout = descriptor.bufferLayouts[attributeIndex]; + + if (attribute.componentType == 0) { + continue; + } + + MTLVertexFormat vertexFormat = GLTFMTLVertexFormatForComponentTypeAndDimension(attribute.componentType, attribute.dimension); + + vertexDescriptor.attributes[attributeIndex].offset = 0; + vertexDescriptor.attributes[attributeIndex].format = vertexFormat; + vertexDescriptor.attributes[attributeIndex].bufferIndex = attributeIndex; + + vertexDescriptor.layouts[attributeIndex].stride = layout.stride; + vertexDescriptor.layouts[attributeIndex].stepRate = 1; + vertexDescriptor.layouts[attributeIndex].stepFunction = MTLVertexStepFunctionPerVertex; // MTLStepFunctionPerVertex; + } + + return vertexDescriptor; +} + +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.h b/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.h new file mode 100644 index 000000000000..48682d2f058d --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.h @@ -0,0 +1,32 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + + +#import + +NS_ASSUME_NONNULL_BEGIN + +extern NSString *const GLTFMTLTextureLoaderOptionGenerateMipmaps; +extern NSString *const GLTFMTLTextureLoaderOptionUsageFlags; +extern NSString *const GLTFMTLTextureLoaderOptionSRGB; + +@interface GLTFMTLTextureLoader : NSObject +- (instancetype)initWithDevice:(id)device; +- (id _Nullable)newTextureWithContentsOfURL:(NSURL *)url options:(NSDictionary * _Nullable)options error:(NSError **)error; +- (id _Nullable)newTextureWithData:(NSData *)data options:(NSDictionary * _Nullable)options error:(NSError **)error; +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.m b/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.m new file mode 100644 index 000000000000..ba6f8eb1e046 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.m @@ -0,0 +1,244 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFMTLTextureLoader.h" +#import +#import +#import + +NSString *const GLTFMTLTextureLoaderOptionGenerateMipmaps = @"GLTFMTLTextureLoaderOptionGenerateMipmaps"; +NSString *const GLTFMTLTextureLoaderOptionUsageFlags = @"GLTFMTLTextureLoaderOptionUsageFlags"; +NSString *const GLTFMTLTextureLoaderOptionSRGB = @"GLTFMTLTextureLoaderOptionSRGB"; + +__fp16 *GLTFMTLConvertImageToRGBA16F(CGImageRef image) +{ + size_t width = CGImageGetWidth(image); + size_t height = CGImageGetHeight(image); + + void *dstPixels = malloc(sizeof(__fp16) * 4 * width * height); + size_t dstBytesPerRow = sizeof(__fp16) * 4 * width; + vImage_Buffer dstBuffer = { + .data = dstPixels, + .height = height, + .width = width, + .rowBytes = dstBytesPerRow + }; + + vImage_CGImageFormat srcFormat = { + .bitsPerComponent = (uint32_t)CGImageGetBitsPerComponent(image), + .bitsPerPixel = (uint32_t)CGImageGetBitsPerPixel(image), + .colorSpace = CGImageGetColorSpace(image), + .bitmapInfo = CGImageGetBitmapInfo(image) + }; + + vImage_CGImageFormat dstFormat = { + .bitsPerComponent = sizeof(__fp16) * 8, + .bitsPerPixel = sizeof(__fp16) * 8 * 4, + .colorSpace = CGImageGetColorSpace(image), + .bitmapInfo = kCGBitmapByteOrder16Little | kCGBitmapFloatComponents | kCGImageAlphaLast + }; + + vImage_Error error = kvImageNoError; + CGFloat background[] = { 0, 0, 0, 1 }; + vImageConverterRef converter = vImageConverter_CreateWithCGImageFormat(&srcFormat, + &dstFormat, + background, + kvImageNoFlags, + &error); + + CGDataProviderRef dataProvider = CGImageGetDataProvider(image); + CFDataRef srcData = CGDataProviderCopyData(dataProvider); + + const void *srcPixels = CFDataGetBytePtr(srcData); + size_t srcBytesPerRow = CGImageGetBytesPerRow(image); + + vImage_Buffer srcBuffer = { + .data = (void *)srcPixels, + .height = height, + .width = width, + .rowBytes = srcBytesPerRow + }; + + error = vImageConvert_AnyToAny(converter, &srcBuffer, &dstBuffer, NULL, kvImageNoFlags); + + vImageConverter_Release(converter); + CFRelease(srcData); + + return dstPixels; +} + +unsigned char *GLTFMTLConvertImageToRGBA8U(CGImageRef image) +{ + size_t width = CGImageGetWidth(image); + size_t height = CGImageGetHeight(image); + + CGColorSpaceRef srcColorSpace = CGImageGetColorSpace(image); + + vImage_CGImageFormat srcFormat = { + .bitsPerComponent = (uint32_t)CGImageGetBitsPerComponent(image), + .bitsPerPixel = (uint32_t)CGImageGetBitsPerPixel(image), + .colorSpace = srcColorSpace, + .bitmapInfo = CGImageGetBitmapInfo(image) + }; + + void *dstPixels = malloc(sizeof(unsigned char) * 4 * width * height); + vImage_Buffer dstBuffer = { + .data = dstPixels, + .height = height, + .width = width, + .rowBytes = sizeof(unsigned char) * 4 * width + }; + + CGColorSpaceRef dstColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); + + vImage_CGImageFormat dstFormat = { + .bitsPerComponent = sizeof(unsigned char) * 8, + .bitsPerPixel = sizeof(unsigned char) * 8 * 4, + .colorSpace = dstColorSpace, + .bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaLast + }; + + vImage_Error error = kvImageNoError; + CGFloat background[] = { 0, 0, 0, 1 }; + vImageConverterRef converter = vImageConverter_CreateWithCGImageFormat(&srcFormat, + &dstFormat, + background, + kvImageNoFlags, + &error); + + CGDataProviderRef dataProvider = CGImageGetDataProvider(image); + CFDataRef srcData = CGDataProviderCopyData(dataProvider); + + const void *srcPixels = CFDataGetBytePtr(srcData); + + size_t srcBytesPerPixel = CGImageGetBitsPerPixel(image) / 8; + + vImage_Buffer srcBuffer = { + .data = (void *)srcPixels, + .height = height, + .width = width, + .rowBytes = srcBytesPerPixel * width + }; + + vImageConvert_AnyToAny(converter, &srcBuffer, &dstBuffer, NULL, kvImageNoFlags); + + vImageConverter_Release(converter); + CFRelease(srcData); + + return dstPixels; +} + +@interface GLTFMTLTextureLoader () +@property (nonatomic, strong) id device; +@property (nonatomic, strong) id commandQueue; +@end + +@implementation GLTFMTLTextureLoader + +- (instancetype)initWithDevice:(id)device { + if ((self = [super init])) { + _device = device; + _commandQueue = [device newCommandQueue]; + } + return self; +} + +- (id)newTextureWithContentsOfURL:(NSURL *)url options:(NSDictionary *)options error:(NSError **)error { + if (url == nil) { + return nil; + } + + NSData *data = [NSData dataWithContentsOfURL:url]; + + return [self newTextureWithData:data options:options error:error]; +} + +- (id)newTextureWithData:(NSData *)data options:(NSDictionary *)options error:(NSError **)error { + if (data == nil) { + return nil; + } + + NSNumber *sRGBOption = options[GLTFMTLTextureLoaderOptionSRGB]; + BOOL sRGB = (sRGBOption != nil) ? sRGBOption.boolValue : NO; + + CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, nil); + CGImageRef image = CGImageSourceCreateImageAtIndex(imageSource, 0, nil); + size_t width = CGImageGetWidth(image); + size_t height = CGImageGetHeight(image); + size_t bitsPerComponent = CGImageGetBitsPerComponent(image); + + void *dstBytes = NULL; + MTLPixelFormat pixelFormat = MTLPixelFormatInvalid; + if (bitsPerComponent == 8) { + pixelFormat = sRGB ? MTLPixelFormatRGBA8Unorm_sRGB : MTLPixelFormatRGBA8Unorm; + dstBytes = GLTFMTLConvertImageToRGBA8U(image); + bitsPerComponent = 8; + } else if (bitsPerComponent == 16 || bitsPerComponent == 32) { + pixelFormat = MTLPixelFormatRGBA16Float; + dstBytes = GLTFMTLConvertImageToRGBA16F(image); + bitsPerComponent = 16; + } + + size_t bytesPerRow = (bitsPerComponent / 8) * 4 * width; + NSNumber *mipmapOption = options[GLTFMTLTextureLoaderOptionGenerateMipmaps]; + BOOL mipmapped = (mipmapOption != nil) ? mipmapOption.boolValue : NO; + + MTLTextureDescriptor *descriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pixelFormat + width:width + height:height + mipmapped:mipmapped]; + + id texture = [self newTextureWithBytes:dstBytes + bytesPerRow:bytesPerRow + descriptor:descriptor + options:options + error:error]; + + free(dstBytes); + CGImageRelease(image); + CFRelease(imageSource); + + return texture; +} + +- (id _Nullable)newTextureWithBytes:(const unsigned char *)bytes + bytesPerRow:(size_t)bytesPerRow + descriptor:(MTLTextureDescriptor *)descriptor + options:(NSDictionary * _Nullable)options + error:(NSError **)error +{ + NSNumber *usageOption = options[GLTFMTLTextureLoaderOptionUsageFlags]; + descriptor.usage = (usageOption != nil) ? usageOption.integerValue : MTLTextureUsageShaderRead; + + id texture = [self.device newTextureWithDescriptor:descriptor]; + + [texture replaceRegion:MTLRegionMake2D(0, 0, texture.width, texture.height) + mipmapLevel:0 + withBytes:bytes + bytesPerRow:bytesPerRow]; + + if (texture != nil && (texture.mipmapLevelCount > 1)) { + id commandBuffer = [self.commandQueue commandBuffer]; + id commandEncoder = [commandBuffer blitCommandEncoder]; + [commandEncoder generateMipmapsForTexture:texture]; + [commandEncoder endEncoding]; + [commandBuffer commit]; + } + + return texture; +} + +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.h b/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.h new file mode 100644 index 000000000000..9764472aafde --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.h @@ -0,0 +1,55 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFEnums.h" + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +#ifdef __cplusplus +extern "C" { +#endif + + +extern MTLPrimitiveType GLTFMTLPrimitiveTypeForPrimitiveType(GLTFPrimitiveType gltfType); + +extern MTLBlendOperation GLTFMTLBlendOperationForBlendFunction(GLTFBlendFunction f); + +extern MTLBlendFactor GLTFBlendFactorForBlendEquation(GLTFBlendEquation e); + +extern MTLCompareFunction GLTFMTLCompareFunctionForComparisonFunc(GLTFComparisonFunc f); + +extern MTLWinding GLTFMTLWindingForWinding(GLTFWinding w); + +extern MTLCullMode GLTFMTLCullModeForCullFace(GLTFFace face); + +extern MTLSamplerMinMagFilter GLTFMTLSamplerMinMagFilterForSamplingFilter(GLTFSamplingFilter mode); + +extern MTLSamplerMipFilter GLTFMTLSamplerMipFilterForSamplingFilter(GLTFSamplingFilter mode); + +extern MTLSamplerAddressMode GLTFMTLSamplerAddressModeForSamplerAddressMode(GLTFAddressMode mode); + +extern NSString *GLTFMTLTypeNameForType(GLTFDataType baseType, GLTFDataDimension dimension, BOOL packedIfPossible); + +extern MTLVertexFormat GLTFMTLVertexFormatForComponentTypeAndDimension(GLTFDataType baseType, GLTFDataDimension dimension); + +#ifdef __cplusplus +} +#endif + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.m b/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.m new file mode 100644 index 000000000000..182067e1b400 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.m @@ -0,0 +1,290 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFMTLUtilities.h" + +MTLPrimitiveType GLTFMTLPrimitiveTypeForPrimitiveType(GLTFPrimitiveType gltfType) { + switch (gltfType) { + case GLTFPrimitiveTypePoints: + return MTLPrimitiveTypePoint; + case GLTFPrimitiveTypeLines: + return MTLPrimitiveTypeLine; + case GLTFPrimitiveTypeLineStrip: + return MTLPrimitiveTypeLineStrip; + case GLTFPrimitiveTypeTriangles: + return MTLPrimitiveTypeTriangle; + case GLTFPrimitiveTypeTriangleStrip: + return MTLPrimitiveTypeTriangleStrip; + + // Not supported; need to duplicate first element and restitch into tri strip, respectively + case GLTFPrimitiveTypeLineLoop: + case GLTFPrimitiveTypeTriangleFan: + default: + return -1; + } +} + +MTLBlendOperation GLTFMTLBlendOperationForBlendFunction(GLTFBlendFunction f) { + switch (f) { + case GLTFBlendFunctionAdd: + return MTLBlendOperationAdd; + case GLTFBlendFunctionSubtract: + return MTLBlendOperationSubtract; + case GLTFBlendFunctionReverseSubtract: + return MTLBlendOperationReverseSubtract; + } +} + +MTLBlendFactor GLTFBlendFactorForBlendEquation(GLTFBlendEquation e) { + switch (e) { + case GLTFBlendEquationOne: + return MTLBlendFactorOne; + case GLTFBlendEquationZero: + return MTLBlendFactorZero; + case GLTFBlendEquationSrcAlpha: + return MTLBlendFactorSourceAlpha; + case GLTFBlendEquationSrcColor: + return MTLBlendFactorSourceColor; + case GLTFBlendEquationDestAlpha: + return MTLBlendFactorDestinationAlpha; + case GLTFBlendEquationDestColor: + return MTLBlendFactorDestinationColor; + case GLTFBlendEquationOneMinusSrcAlpha: + return MTLBlendFactorOneMinusSourceAlpha; + case GLTFBlendEquationOneMinusSrcColor: + return MTLBlendFactorOneMinusSourceColor; + case GLTFBlendEquationSrcAlphaSaturate: + return MTLBlendFactorSourceAlphaSaturated; + case GLTFBlendEquationOneMinusDestAlpha: + return MTLBlendFactorOneMinusDestinationAlpha; + case GLTFBlendEquationOneMinusDestColor: + return MTLBlendFactorOneMinusDestinationColor; + case GLTFBlendEquationOneMinusConstAlpha: + return MTLBlendFactorOneMinusDestinationColor; + default: + NSLog(@"Unsupported blend equation %d", (int)e); + return MTLBlendFactorOne; + } +} + +MTLCompareFunction GLTFMTLCompareFunctionForComparisonFunc(GLTFComparisonFunc f) { + switch (f) { + case GLTFComparisonFuncLess: + return MTLCompareFunctionLess; + case GLTFComparisonFuncEqual: + return MTLCompareFunctionEqual; + case GLTFComparisonFuncAlways: + return MTLCompareFunctionAlways; + case GLTFComparisonFuncGreater: + return MTLCompareFunctionGreater; + case GLTFComparisonFuncNotEqual: + return MTLCompareFunctionNotEqual; + case GLTFComparisonFuncLessEqual: + return MTLCompareFunctionLessEqual; + case GLTFComparisonFuncGreaterEqual: + return MTLCompareFunctionGreaterEqual; + default: + NSLog(@"Unsupported comparison function %d", (int)f); + return MTLCompareFunctionLess; + } +} + +MTLWinding GLTFMTLWindingForWinding(GLTFWinding w) { + switch (w) { + case GLTFWindingCounterclockwise: + return MTLWindingCounterClockwise; + case GLTFWindingClockwise: + default: + return MTLWindingClockwise; + } +} + +MTLCullMode GLTFMTLCullModeForCullFace(GLTFFace face) { + switch (face) { + case GLTFFaceBack: + return MTLCullModeBack; + case GLTFFaceFront: + return MTLCullModeFront; + default: + return MTLCullModeBack; + } +} + +MTLSamplerMinMagFilter GLTFMTLSamplerMinMagFilterForSamplingFilter(GLTFSamplingFilter mode) { + switch (mode) { + case GLTFSamplingFilterNearest: + return MTLSamplerMinMagFilterNearest; + default: + return MTLSamplerMinMagFilterLinear; + } +} + +MTLSamplerMipFilter GLTFMTLSamplerMipFilterForSamplingFilter(GLTFSamplingFilter mode) { + switch (mode) { + case GLTFSamplingFilterNearest: + case GLTFSamplingFilterLinear: + return MTLSamplerMipFilterNotMipmapped; + case GLTFSamplingFilterNearestMipNearest: + case GLTFSamplingFilterLinearMipNearest: + return MTLSamplerMipFilterNearest; + default: + return MTLSamplerMipFilterLinear; + } +} + +MTLSamplerAddressMode GLTFMTLSamplerAddressModeForSamplerAddressMode(GLTFAddressMode mode) { + switch (mode) { + case GLTFAddressModeClampToEdge: + return MTLSamplerAddressModeClampToEdge; + case GLTFAddressModeMirroredRepeat: + return MTLSamplerAddressModeMirrorRepeat; + default: + return MTLSamplerAddressModeRepeat; + } +} + +NSString *GLTFMTLTypeNameForType(GLTFDataType baseType, GLTFDataDimension dimension, BOOL packed) { + NSString *typeName = @"float"; + NSString *packingPrefix = @""; + NSString *dimensionSuffix = @""; + + if (packed && (dimension != GLTFDataDimensionScalar)) { + packingPrefix = @"packed_"; + } + + switch (baseType) { + case GLTFDataTypeBool: typeName = @"bool"; break; + case GLTFDataTypeChar: typeName = @"char"; break; + case GLTFDataTypeUChar: typeName = @"uchar"; break; + case GLTFDataTypeShort: typeName = @"short"; break; + case GLTFDataTypeUShort: typeName = @"ushort"; break; + case GLTFDataTypeInt: typeName = @"int"; break; + case GLTFDataTypeUInt: typeName = @"uint"; break; + case GLTFDataTypeFloat: typeName = @"float"; break; + case GLTFDataTypeSampler2D: typeName = @"texture2d"; break; + default: + return @"__UNKNOWN_TYPE__"; + } + + switch (dimension) { + case GLTFDataDimensionScalar: dimensionSuffix = @""; break; + case GLTFDataDimensionVector2: dimensionSuffix = @"2"; break; + case GLTFDataDimensionVector3: dimensionSuffix = @"3"; break; + case GLTFDataDimensionVector4: dimensionSuffix = @"4"; break; + case GLTFDataDimensionMatrix2x2: dimensionSuffix = @"float2x2"; break; + case GLTFDataDimensionMatrix3x3: dimensionSuffix = @"float3x3"; break; + case GLTFDataDimensionMatrix4x4: dimensionSuffix = @"float4x4"; break; + default: + return @"__UNKNOWN_TYPE__"; + } + + return [NSString stringWithFormat:@"%@%@%@", packingPrefix, typeName, dimensionSuffix]; +} + +MTLVertexFormat GLTFMTLVertexFormatForComponentTypeAndDimension(GLTFDataType baseType, GLTFDataDimension dimension) +{ + switch (baseType) { + case GLTFDataTypeChar: + switch (dimension) { + case GLTFDataDimensionVector2: + return MTLVertexFormatChar2; + case GLTFDataDimensionVector3: + return MTLVertexFormatChar3; + case GLTFDataDimensionVector4: + return MTLVertexFormatChar4; + default: + break; + } + case GLTFDataTypeUChar: + switch (dimension) { + case GLTFDataDimensionVector2: + return MTLVertexFormatUChar2; + case GLTFDataDimensionVector3: + return MTLVertexFormatUChar3; + case GLTFDataDimensionVector4: + return MTLVertexFormatUChar4; + default: + break; + } + case GLTFDataTypeShort: + switch (dimension) { + case GLTFDataDimensionVector2: + return MTLVertexFormatShort2; + case GLTFDataDimensionVector3: + return MTLVertexFormatShort3; + case GLTFDataDimensionVector4: + return MTLVertexFormatShort4; + default: + break; + } + case GLTFDataTypeUShort: + switch (dimension) { + case GLTFDataDimensionVector2: + return MTLVertexFormatUShort2; + case GLTFDataDimensionVector3: + return MTLVertexFormatUShort3; + case GLTFDataDimensionVector4: + return MTLVertexFormatUShort4; + default: + break; + } + case GLTFDataTypeInt: + switch (dimension) { + case GLTFDataDimensionScalar: + return MTLVertexFormatInt; + case GLTFDataDimensionVector2: + return MTLVertexFormatInt2; + case GLTFDataDimensionVector3: + return MTLVertexFormatInt3; + case GLTFDataDimensionVector4: + return MTLVertexFormatInt4; + default: + break; + } + case GLTFDataTypeUInt: + switch (dimension) { + case GLTFDataDimensionScalar: + return MTLVertexFormatUInt; + case GLTFDataDimensionVector2: + return MTLVertexFormatUInt2; + case GLTFDataDimensionVector3: + return MTLVertexFormatUInt3; + case GLTFDataDimensionVector4: + return MTLVertexFormatUInt4; + default: + break; + } + case GLTFDataTypeFloat: + switch (dimension) { + case GLTFDataDimensionScalar: + return MTLVertexFormatFloat; + case GLTFDataDimensionVector2: + return MTLVertexFormatFloat2; + case GLTFDataDimensionVector3: + return MTLVertexFormatFloat3; + case GLTFDataDimensionVector4: + return MTLVertexFormatFloat4; + default: + break; + } + default: + break; + } + + return MTLVertexFormatInvalid; +} + + diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMaterial.h b/platform/darwin/src/gltf/gltfkit/GLTFMaterial.h new file mode 100644 index 000000000000..92f1d29b4ff7 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFMaterial.h @@ -0,0 +1,61 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFObject.h" +#import "GLTFTexture.h" + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class GLTFParameter; + +typedef NS_ENUM(NSInteger, GLTFAlphaMode) { + GLTFAlphaModeOpaque, + GLTFAlphaModeMask, + GLTFAlphaModeBlend, +}; + +@interface GLTFMaterial : GLTFObject + +@property (nonatomic, assign) simd_float4 baseColorFactor; +@property (nonatomic, assign) float metalnessFactor; +@property (nonatomic, assign) float roughnessFactor; +@property (nonatomic, assign) float normalTextureScale; +@property (nonatomic, assign) float occlusionStrength; +@property (nonatomic, assign) simd_float3 emissiveFactor; + +@property (nonatomic, assign) float glossinessFactor; // Only used by KHR_materials_pbrSpecularGlossiness extension +@property (nonatomic, assign) simd_float3 specularFactor; // Only used by KHR_materials_pbrSpecularGlossiness extension + +@property (nonatomic, strong) GLTFTextureInfo * _Nullable baseColorTexture; +@property (nonatomic, strong) GLTFTextureInfo * _Nullable metallicRoughnessTexture; +@property (nonatomic, strong) GLTFTextureInfo * _Nullable normalTexture; +@property (nonatomic, strong) GLTFTextureInfo * _Nullable emissiveTexture; +@property (nonatomic, strong) GLTFTextureInfo * _Nullable occlusionTexture; + +@property (nonatomic, assign) BOOL hasTextureTransforms; // Only used when KHR_texture_transform extension is present + +@property (nonatomic, assign, getter=isDoubleSided) BOOL doubleSided; + +@property (nonatomic, assign) GLTFAlphaMode alphaMode; +@property (nonatomic, assign) float alphaCutoff; // Only used when `alphaMode` == GLTFAlphaModeMask + +@property (nonatomic, assign, getter=isUnlit) BOOL unlit; // Only used when KHR_materials_unlit extension is present + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMaterial.m b/platform/darwin/src/gltf/gltfkit/GLTFMaterial.m new file mode 100644 index 000000000000..e8f78a4700ed --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFMaterial.m @@ -0,0 +1,35 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFMaterial.h" + +@implementation GLTFMaterial + +- (instancetype)init { + if ((self = [super init])) { + _baseColorFactor = (simd_float4){ 1, 1, 1, 1 }; + _metalnessFactor = 1.0; + _roughnessFactor = 1.0; + _occlusionStrength = 1.0; + _emissiveFactor = (simd_float3) { 0.0, 0.0, 0.0 }; + _normalTextureScale = 1.0; + _alphaMode = GLTFAlphaModeOpaque; + _alphaCutoff = 0.5; + } + return self; +} + +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMesh.h b/platform/darwin/src/gltf/gltfkit/GLTFMesh.h new file mode 100644 index 000000000000..3bf40f62d258 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFMesh.h @@ -0,0 +1,43 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFObject.h" +#import "GLTFEnums.h" + +NS_ASSUME_NONNULL_BEGIN + +@class GLTFAccessor, GLTFVertexDescriptor, GLTFSubmesh, GLTFMaterial; + +@interface GLTFMesh : GLTFObject +@property (nonatomic, copy) NSArray *submeshes; +@property (nonatomic, copy) NSArray *defaultMorphTargetWeights; +@end + +@interface GLTFMorphTarget : GLTFObject +@property (nonatomic, copy) NSDictionary *accessorsForAttributes; +@end + +@interface GLTFSubmesh : GLTFObject +@property (nonatomic, copy) NSDictionary *accessorsForAttributes; +@property (nonatomic, weak) GLTFAccessor *indexAccessor; +@property (nonatomic, weak) GLTFMaterial *material; +@property (nonatomic, assign) GLTFPrimitiveType primitiveType; +@property (nonatomic, copy) NSArray *morphTargets; + +@property (nonatomic, readonly) GLTFVertexDescriptor *vertexDescriptor; +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMesh.m b/platform/darwin/src/gltf/gltfkit/GLTFMesh.m new file mode 100644 index 000000000000..bc6ae3a88407 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFMesh.m @@ -0,0 +1,69 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFMesh.h" +#import "GLTFVertexDescriptor.h" +#import "GLTFAccessor.h" +#import "GLTFBufferView.h" +#import "GLTFUtilities.h" + +@implementation GLTFMesh +@end + +@implementation GLTFMorphTarget +@end + +@interface GLTFSubmesh () +@property (nonatomic, strong) GLTFVertexDescriptor *cachedVertexDescriptor; +@end + +@implementation GLTFSubmesh + +- (instancetype)init { + if ((self = [super init])) { + _primitiveType = GLTFPrimitiveTypeTriangles; + } + return self; +} + +- (void)setAccessorsForAttributes:(NSDictionary *)accessorsForAttributes { + _accessorsForAttributes = accessorsForAttributes; + _cachedVertexDescriptor = nil; +} + +- (GLTFVertexDescriptor *)vertexDescriptor { + if (self.cachedVertexDescriptor == nil) { + GLTFVertexDescriptor *descriptor = [GLTFVertexDescriptor new]; + __block NSUInteger index = 0; + [self.accessorsForAttributes enumerateKeysAndObjectsUsingBlock:^(NSString *name, GLTFAccessor *accessor, BOOL *stop) { + descriptor.attributes[index].componentType = accessor.componentType; + descriptor.attributes[index].dimension = accessor.dimension; + descriptor.attributes[index].offset = accessor.offset; + descriptor.attributes[index].semantic = name; + if (accessor.bufferView.stride > 0) { + descriptor.bufferLayouts[index].stride = accessor.bufferView.stride; + } else { + descriptor.bufferLayouts[index].stride = GLTFSizeOfComponentTypeWithDimension(accessor.componentType, accessor.dimension); + } + ++index; + }]; + self.cachedVertexDescriptor = descriptor; + } + + return self.cachedVertexDescriptor; +} + +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFNode.h b/platform/darwin/src/gltf/gltfkit/GLTFNode.h new file mode 100644 index 000000000000..3863bb909130 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFNode.h @@ -0,0 +1,49 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFObject.h" +#import "GLTFUtilities.h" +#import "GLTFNodeVisitor.h" +#import + +NS_ASSUME_NONNULL_BEGIN + + +@class GLTFCamera, GLTFSkin, GLTFMesh; +@class GLTFKHRLight; + +@interface GLTFNode : GLTFObject +@property (nonatomic, weak) GLTFCamera * _Nullable camera; +@property (nonatomic, weak) GLTFKHRLight * _Nullable light; +@property (nonatomic, weak) GLTFNode * _Nullable parent; +@property (nonatomic, copy) NSArray *children; +@property (nonatomic, weak) GLTFSkin * _Nullable skin; +@property (nonatomic, copy) NSString * _Nullable jointName; +@property (nonatomic, weak) GLTFMesh * _Nullable mesh; +@property (nonatomic, copy) NSArray *morphTargetWeights; +@property (nonatomic, assign) GLTFQuaternion rotationQuaternion; +@property (nonatomic, assign) simd_float3 scale; +@property (nonatomic, assign) simd_float3 translation; +@property (nonatomic, assign) simd_float4x4 localTransform; +@property (nonatomic, readonly, assign) simd_float4x4 globalTransform; +@property (nonatomic, readonly, assign) GLTFBoundingBox approximateBounds; // axis-aligned; in local coordinates + +- (void)addChildNode:(GLTFNode *)node; +- (void)removeFromParent; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFNode.m b/platform/darwin/src/gltf/gltfkit/GLTFNode.m new file mode 100644 index 000000000000..52dd177fde1a --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFNode.m @@ -0,0 +1,171 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFNode.h" +#import "GLTFAccessor.h" +#import "GLTFMesh.h" +#import "GLTFVertexDescriptor.h" + +@interface GLTFNode () +@property (nonatomic, assign, getter=localTransformIsDirty) BOOL localTransformDirty; +@property (nonatomic, strong) NSMutableArray *mutableChildren; +@end + +@implementation GLTFNode + +@synthesize localTransform=_localTransform; + +- (instancetype)init { + if ((self = [super init])) { + _localTransform = matrix_identity_float4x4; + _rotationQuaternion = simd_quaternion(0.f, 0.f, 0.f, 1.f); + _scale = vector3(1.0f, 1.0f, 1.0f); + _translation = vector3(0.0f, 0.0f, 0.0f); + _morphTargetWeights = @[]; + } + return self; +} + +- (void)setChildren:(NSArray *)children { + _mutableChildren = [children mutableCopy]; +} + +- (NSArray *)children { + return [_mutableChildren copy]; +} + +- (void)addChildNode:(GLTFNode *)node { + if (node.parent) { + [node removeFromParent]; + } + node.parent = self; + [self.mutableChildren addObject:node]; +} + +- (void)removeFromParent { + [self.parent _removeChildNode:self]; +} + +- (void)_removeChildNode:(GLTFNode *)child { + [self.mutableChildren removeObject:child]; + child.parent = nil; +} + +- (void)setScale:(simd_float3)scale { + _scale = scale; + _localTransformDirty = YES; +} + +- (void)setRotationQuaternion:(GLTFQuaternion)rotationQuaternion { + _rotationQuaternion = rotationQuaternion; + _localTransformDirty = YES; +} + +- (void)setTranslation:(simd_float3)translation { + _translation = translation; + _localTransformDirty = YES; +} + +- (simd_float4x4)globalTransform { + simd_float4x4 localTransform = self.localTransform; + simd_float4x4 ancestorTransform = self.parent ? self.parent.globalTransform : matrix_identity_float4x4; + return matrix_multiply(ancestorTransform, localTransform); +} + +- (void)setLocalTransform:(simd_float4x4)localTransform { + _localTransform = localTransform; +} + +- (simd_float4x4)localTransform { + if (self.localTransformIsDirty) { + [self computeLocalTransform]; + } + + return _localTransform; +} + +- (void)computeLocalTransform { + simd_float4x4 translationMatrix = matrix_identity_float4x4; + translationMatrix.columns[3][0] = _translation[0]; + translationMatrix.columns[3][1] = _translation[1]; + translationMatrix.columns[3][2] = _translation[2]; + + simd_float4x4 rotationMatrix = simd_matrix4x4(_rotationQuaternion); + + simd_float4x4 scaleMatrix = matrix_identity_float4x4; + scaleMatrix.columns[0][0] = _scale[0]; + scaleMatrix.columns[1][1] = _scale[1]; + scaleMatrix.columns[2][2] = _scale[2]; + + _localTransform = matrix_multiply(matrix_multiply(translationMatrix, rotationMatrix), scaleMatrix); + _localTransformDirty = NO; +} + +- (GLTFBoundingBox)approximateBounds { + return [self _approximateBoundsRecursive:matrix_identity_float4x4]; +} + +- (GLTFBoundingBox)_approximateBoundsRecursive:(simd_float4x4)transform { + GLTFBoundingBox bounds = { 0 }; + + if (self.mesh != nil) { + for (GLTFSubmesh *submesh in self.mesh.submeshes) { + GLTFBoundingBox submeshBounds = { 0 }; + GLTFAccessor *positionAccessor = submesh.accessorsForAttributes[GLTFAttributeSemanticPosition]; + GLTFValueRange positionRange = positionAccessor.valueRange; + submeshBounds.minPoint.x = positionRange.minValue[0]; + submeshBounds.minPoint.y = positionRange.minValue[1]; + submeshBounds.minPoint.z = positionRange.minValue[2]; + submeshBounds.maxPoint.x = positionRange.maxValue[0]; + submeshBounds.maxPoint.y = positionRange.maxValue[1]; + submeshBounds.maxPoint.z = positionRange.maxValue[2]; + GLTFBoundingBoxUnion(&bounds, submeshBounds); + } + } + + simd_float4x4 globalTransform = matrix_multiply(transform, self.localTransform); + + GLTFBoundingBoxTransform(&bounds, globalTransform); + + for (GLTFNode *child in self.children) { + GLTFBoundingBox childBounds = [child _approximateBoundsRecursive:globalTransform]; + GLTFBoundingBoxUnion(&bounds, childBounds); + } + + return bounds; +} + +- (void)acceptVisitor:(GLTFNodeVisitor)visitor strategy:(GLTFVisitationStrategy)strategy { + [self _acceptVisitor:visitor depth:0 strategy:strategy]; +} + +- (void)_acceptVisitor:(GLTFNodeVisitor)visitor depth:(int)depth strategy:(GLTFVisitationStrategy)strategy { + switch (strategy) { + case GLTFVisitationStrategyDepthFirst: + default: + { + BOOL recurse = YES; + visitor(self, depth, &recurse); + if (recurse) { + for (GLTFNode *child in self.children) { + [child _acceptVisitor:visitor depth:(depth + 1) strategy:strategy]; + } + } + } + } +} + +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFNodeVisitor.h b/platform/darwin/src/gltf/gltfkit/GLTFNodeVisitor.h new file mode 100644 index 000000000000..a3bceddb5e3e --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFNodeVisitor.h @@ -0,0 +1,33 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class GLTFNode; + +typedef NS_ENUM(NSInteger, GLTFVisitationStrategy) { + GLTFVisitationStrategyDepthFirst +}; + +typedef void (^GLTFNodeVisitor)(GLTFNode *node, int depth, BOOL *stop); + +@protocol GLTFNodeVisitable +- (void)acceptVisitor:(GLTFNodeVisitor)visitor strategy:(GLTFVisitationStrategy)strategy; +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFObject.h b/platform/darwin/src/gltf/gltfkit/GLTFObject.h new file mode 100644 index 000000000000..c745d543c20e --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFObject.h @@ -0,0 +1,45 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol GLTFObject + +/// The user-defined name of this object. Need not be unique. +@property (nonatomic, copy) NSString * _Nullable name; +/// Data specific to any extensions used in this document +@property (nonatomic, copy) NSDictionary *extensions; +/// Contains application-specific information that is passed through but not parsed +@property (nonatomic, copy) NSDictionary *extras; + +@end + +@interface GLTFObject : NSObject + +/// A unique identifier for this object +@property (nonatomic, readonly) NSUUID *identifier; +/// The user-defined name of this object. Need not be unique. +@property (nonatomic, copy) NSString * _Nullable name; +/// Data specific to any extensions used in this document +@property (nonatomic, copy) NSDictionary *extensions; +/// Contains application-specific information that is passed through but not parsed +@property (nonatomic, copy) NSDictionary *extras; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFObject.m b/platform/darwin/src/gltf/gltfkit/GLTFObject.m new file mode 100644 index 000000000000..42e9e79127aa --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFObject.m @@ -0,0 +1,32 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFObject.h" + +@implementation GLTFObject + +- (instancetype)init { + if ((self = [super init])) { + _identifier = [NSUUID new]; + } + return self; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@; name = %@", super.description, self.name]; +} + +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFScene.h b/platform/darwin/src/gltf/gltfkit/GLTFScene.h new file mode 100644 index 000000000000..cf5ae8480799 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFScene.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFObject.h" +#import "GLTFUtilities.h" +#import "GLTFNodeVisitor.h" + +NS_ASSUME_NONNULL_BEGIN + +@class GLTFNode; +@class GLTFKHRLight; + +@interface GLTFScene : GLTFObject +@property (nonatomic, copy) NSArray *nodes; +@property (nonatomic, weak) GLTFKHRLight * _Nullable ambientLight; +@property (nonatomic, readonly, assign) GLTFBoundingBox approximateBounds; + +- (void)addNode:(GLTFNode *)node; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFScene.m b/platform/darwin/src/gltf/gltfkit/GLTFScene.m new file mode 100644 index 000000000000..3ec31b78f08c --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFScene.m @@ -0,0 +1,57 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFScene.h" +#import "GLTFNode.h" + +@interface GLTFScene () +@property (nonatomic, strong) NSMutableArray *mutableNodes; +@end + +@implementation GLTFScene + +- (void)setNodes:(NSArray *)nodes { + _mutableNodes = [nodes mutableCopy]; +} + +- (NSArray *)nodes { + return [_mutableNodes copy]; +} + +- (void)addNode:(GLTFNode *)node { + if (node.parent) { + [node removeFromParent]; + } + + [_mutableNodes addObject:node]; +} + +- (GLTFBoundingBox)approximateBounds { + GLTFBoundingBox sceneBounds = { 0 }; + for (GLTFNode *node in self.nodes) { + GLTFBoundingBox nodeBounds = node.approximateBounds; + GLTFBoundingBoxUnion(&sceneBounds, nodeBounds); + } + return sceneBounds; +} + +- (void)acceptVisitor:(GLTFNodeVisitor)visitor strategy:(GLTFVisitationStrategy)strategy { + for (GLTFNode *node in self.nodes) { + [node acceptVisitor:visitor strategy:strategy]; + } +} + +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFSkin.h b/platform/darwin/src/gltf/gltfkit/GLTFSkin.h new file mode 100644 index 000000000000..fa5a8aee553e --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFSkin.h @@ -0,0 +1,30 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import +#import "GLTFObject.h" + +NS_ASSUME_NONNULL_BEGIN + +@class GLTFAccessor, GLTFNode; + +@interface GLTFSkin : GLTFObject +@property (nonatomic, strong) GLTFAccessor *inverseBindMatricesAccessor; +@property (nonatomic, copy) NSArray *jointNodes; +@property (nonatomic, assign) GLTFNode *skeletonRootNode; +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFSkin.m b/platform/darwin/src/gltf/gltfkit/GLTFSkin.m new file mode 100644 index 000000000000..c6c5dfbfbdc2 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFSkin.m @@ -0,0 +1,20 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFSkin.h" + +@implementation GLTFSkin +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFTexture.h b/platform/darwin/src/gltf/gltfkit/GLTFTexture.h new file mode 100644 index 000000000000..556ab715cd4d --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFTexture.h @@ -0,0 +1,66 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFObject.h" +#import "GLTFEnums.h" +#import "../GLTFMath.hpp" +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class GLTFTextureSampler, GLTFImage; + +@interface GLTFTexture : GLTFObject + +@property (nonatomic, weak) GLTFTextureSampler *sampler; + +@property (nonatomic, weak) GLTFImage *image; + +// GLTFTextureFormatRGBA +@property (nonatomic, assign) GLTFTextureFormat format; + +// GLTFTextureFormatRGBA +@property (nonatomic, assign) GLTFTextureFormat internalFormat; + +// GLTFTextureTypeUChar +@property (nonatomic, assign) GLTFTextureType type; + +// GLTFTextureTargetTexture2D +@property (nonatomic, assign) GLTFTextureTarget target; + +@end + +@interface GLTFTextureInfo : NSObject + +@property (nonatomic, strong) GLTFTexture *texture; + +@property (nonatomic, assign) NSInteger texCoord; + +// The transform to apply to texture coordinates before sampling from this texture. +// Defaults to the identity transform. Only populated if KHR_texture_transform is included +// as an optional or required extension for the containing asset. +@property (nonatomic, assign) GLTFTextureTransform transform; + +@property (nonatomic, strong) NSDictionary *_Nullable extensions; + +@property (nonatomic, strong) NSDictionary *_Nullable extras; + +@end + + +NS_ASSUME_NONNULL_END + diff --git a/platform/darwin/src/gltf/gltfkit/GLTFTexture.mm b/platform/darwin/src/gltf/gltfkit/GLTFTexture.mm new file mode 100644 index 000000000000..0f5d77fdeb82 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFTexture.mm @@ -0,0 +1,44 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFTexture.h" +#import "GLTFUtilities.h" + + +@implementation GLTFTexture + +- (instancetype)init { + if ((self = [super init])) { + _format = GLTFTextureFormatRGBA; + _internalFormat = GLTFTextureFormatRGBA; + _type = GLTFTextureTypeUChar; + _target = GLTFTextureTargetTexture2D; + } + return self; +} + +@end + +@implementation GLTFTextureInfo + +- (instancetype)init { + if ((self = [super init])) { + _transform = GLTFTextureTransformMakeIdentity(); + } + return self; +} + +@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.h b/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.h new file mode 100644 index 000000000000..a3b372494551 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.h @@ -0,0 +1,34 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFObject.h" +#import "GLTFEnums.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface GLTFTextureSampler : GLTFObject + +// GLTFSamplingFilterLinear +@property (nonatomic, assign) GLTFSamplingFilter magFilter; +// GLTFSamplingFilterNearestMipLinear +@property (nonatomic, assign) GLTFSamplingFilter minFilter; +// GLTFAddressModeRepeat +@property (nonatomic, assign) GLTFAddressMode sAddressMode; +// GLTFAddressModeRepeat +@property (nonatomic, assign) GLTFAddressMode tAddressMode; +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.m b/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.m new file mode 100644 index 000000000000..2078acb52ea4 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.m @@ -0,0 +1,60 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFTextureSampler.h" + +@implementation GLTFTextureSampler + +- (instancetype)init { + if ((self = [super init])) { + _magFilter = GLTFSamplingFilterLinear; + _minFilter = GLTFSamplingFilterNearestMipLinear; + _sAddressMode = GLTFAddressModeRepeat; + _tAddressMode = GLTFAddressModeRepeat; + } + return self; +} + +- (BOOL)isEqual:(id)other { + if (![other isKindOfClass:[GLTFTextureSampler class]]) { + return NO; + } + + GLTFTextureSampler *otherSampler = (GLTFTextureSampler *)other; + BOOL areEqual = + (otherSampler.magFilter == self.magFilter) && + (otherSampler.minFilter == self.minFilter) && + (otherSampler.sAddressMode == self.sAddressMode) && + (otherSampler.tAddressMode == self.tAddressMode); + return areEqual; +} + +- (NSUInteger)hash { + NSUInteger hashValue = ((_sAddressMode << 16) | _tAddressMode) + ((_magFilter << 16) | _minFilter); + return hashValue; +} + +- (id)copyWithZone:(NSZone *)zone { + GLTFTextureSampler *copy = [[GLTFTextureSampler allocWithZone:zone] init]; + copy.magFilter = self.magFilter; + copy.minFilter = self.minFilter; + copy.sAddressMode = self.sAddressMode; + copy.tAddressMode = self.tAddressMode; + return copy; +} + +@end + diff --git a/platform/darwin/src/gltf/gltfkit/GLTFUtilities.h b/platform/darwin/src/gltf/gltfkit/GLTFUtilities.h new file mode 100644 index 000000000000..b23bc2211025 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFUtilities.h @@ -0,0 +1,79 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFEnums.h" + +#import +#import +#import "../GLTFMath.hpp" + +NS_ASSUME_NONNULL_BEGIN + +typedef struct __attribute__((packed)) { + float x, y, z; +} GLTFVector3; + +typedef struct __attribute__((packed)) { + float x, y, z, w; +} GLTFVector4; + +typedef struct __attribute__((packed)) { + GLTFVector4 columns[4]; +} GLTFMatrix4; + +typedef simd_quatf GLTFQuaternion; + + +extern bool GLTFBoundingBoxIsEmpty(GLTFBoundingBox b); + +extern GLTFBoundingBox *GLTFBoundingBoxUnion(GLTFBoundingBox *a, GLTFBoundingBox b); + +extern void GLTFBoundingBoxTransform(GLTFBoundingBox *b, simd_float4x4 transform); + + +extern GLTFQuaternion GLTFQuaternionFromEulerAngles(float pitch, float yaw, float roll); + + + + + +extern simd_float3x3 GLTFMatrixUpperLeft3x3(simd_float4x4); + +extern simd_float4x4 GLTFNormalMatrixFromModelMatrix(simd_float4x4); + + + +extern GLTFDataDimension GLTFDataDimensionForName(NSString *name); + +extern size_t GLTFSizeOfDataType(GLTFDataType type); + +extern size_t GLTFSizeOfComponentTypeWithDimension(GLTFDataType baseType, GLTFDataDimension dimension); + +extern NSInteger GLTFComponentCountForDimension(GLTFDataDimension dimension); + +extern BOOL GLTFDataTypeComponentsAreFloats(GLTFDataType type); + +extern simd_float2 GLTFVectorFloat2FromArray(NSArray *array); + +extern simd_float3 GLTFVectorFloat3FromArray(NSArray *array); + +extern simd_float4 GLTFVectorFloat4FromArray(NSArray *array); + +extern GLTFQuaternion GLTFQuaternionFromArray(NSArray *array); + +extern simd_float4x4 GLTFMatrixFloat4x4FromArray(NSArray *array); + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFUtilities.m b/platform/darwin/src/gltf/gltfkit/GLTFUtilities.m new file mode 100644 index 000000000000..effa58a06690 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFUtilities.m @@ -0,0 +1,261 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFUtilities.h" + +bool GLTFBoundingBoxIsEmpty(GLTFBoundingBox b) { + return (b.minPoint.x == b.maxPoint.x) && (b.minPoint.y == b.maxPoint.y) && (b.minPoint.z == b.maxPoint.z); +} + +GLTFBoundingBox *GLTFBoundingBoxUnion(GLTFBoundingBox *a, GLTFBoundingBox b) { + bool leftEmpty = GLTFBoundingBoxIsEmpty(*a); + bool rightEmpty = GLTFBoundingBoxIsEmpty(b); + + if (leftEmpty) { + if (!rightEmpty) { + *a = b; + } + } else if (!rightEmpty) { + if (b.minPoint.x < a->minPoint.x) { a->minPoint.x = b.minPoint.x; } + if (b.minPoint.y < a->minPoint.y) { a->minPoint.y = b.minPoint.y; } + if (b.minPoint.z < a->minPoint.z) { a->minPoint.z = b.minPoint.z; } + if (b.maxPoint.x > a->maxPoint.x) { a->maxPoint.x = b.maxPoint.x; } + if (b.maxPoint.y > a->maxPoint.y) { a->maxPoint.y = b.maxPoint.y; } + if (b.maxPoint.z > a->maxPoint.z) { a->maxPoint.z = b.maxPoint.z; } + } + + return a; +} + +void GLTFBoundingBoxTransform(GLTFBoundingBox *b, simd_float4x4 transform) { + simd_float4 ltf = (simd_float4) { b->minPoint.x, b->maxPoint.y, b->maxPoint.z, 1 }; + simd_float4 rtf = (simd_float4) { b->maxPoint.x, b->maxPoint.y, b->maxPoint.z, 1 }; + simd_float4 lbf = (simd_float4) { b->minPoint.x, b->minPoint.y, b->maxPoint.z, 1 }; + simd_float4 rbf = (simd_float4) { b->maxPoint.x, b->minPoint.y, b->maxPoint.z, 1 }; + simd_float4 ltb = (simd_float4) { b->minPoint.x, b->maxPoint.y, b->minPoint.z, 1 }; + simd_float4 rtb = (simd_float4) { b->maxPoint.x, b->maxPoint.y, b->minPoint.z, 1 }; + simd_float4 lbb = (simd_float4) { b->minPoint.x, b->minPoint.y, b->minPoint.z, 1 }; + simd_float4 rbb = (simd_float4) { b->maxPoint.x, b->minPoint.y, b->minPoint.z, 1 }; + + ltf = matrix_multiply(transform, ltf); + rtf = matrix_multiply(transform, rtf); + lbf = matrix_multiply(transform, lbf); + rbf = matrix_multiply(transform, rbf); + ltb = matrix_multiply(transform, ltb); + rtb = matrix_multiply(transform, rtb); + lbb = matrix_multiply(transform, lbb); + rbb = matrix_multiply(transform, rbb); + + b->minPoint.x = fmin(fmin(fmin(fmin(fmin(fmin(fmin(ltf.x, rtf.x), lbf.x), rbf.x), ltb.x), rtb.x), lbb.x), rbb.x); + b->minPoint.y = fmin(fmin(fmin(fmin(fmin(fmin(fmin(ltf.y, rtf.y), lbf.y), rbf.y), ltb.y), rtb.y), lbb.y), rbb.y); + b->minPoint.z = fmin(fmin(fmin(fmin(fmin(fmin(fmin(ltf.z, rtf.z), lbf.z), rbf.z), ltb.z), rtb.z), lbb.z), rbb.z); + b->maxPoint.x = fmax(fmax(fmax(fmax(fmax(fmax(fmax(ltf.x, rtf.x), lbf.x), rbf.x), ltb.x), rtb.x), lbb.x), rbb.x); + b->maxPoint.y = fmax(fmax(fmax(fmax(fmax(fmax(fmax(ltf.y, rtf.y), lbf.y), rbf.y), ltb.y), rtb.y), lbb.y), rbb.y); + b->maxPoint.z = fmax(fmax(fmax(fmax(fmax(fmax(fmax(ltf.z, rtf.z), lbf.z), rbf.z), ltb.z), rtb.z), lbb.z), rbb.z); +} + + + +GLTFQuaternion GLTFQuaternionFromEulerAngles(float pitch, float yaw, float roll) { + float cx = cos(pitch / 2); + float sx = sin(pitch / 2); + float cy = cos(yaw / 2); + float sy = sin(yaw / 2); + float cz = cos(roll / 2); + float sz = sin(roll / 2); + + GLTFQuaternion q = simd_quaternion( + sx*cy*cz + cx*sy*sz, + cx*sy*cz + sx*cy*sz, + cx*cy*sz - sx*sy*cz, + cx*cy*cz - sx*sy*sz + ); + return q; +} + + + + + + + + + + + +GLTFDataDimension GLTFDataDimensionForName(NSString *name) { + if ([name isEqualToString:@"SCALAR"]) { + return GLTFDataDimensionScalar; + } else if ([name isEqualToString:@"VEC2"]) { + return GLTFDataDimensionVector2; + } else if ([name isEqualToString:@"VEC2"]) { + return GLTFDataDimensionVector2; + } else if ([name isEqualToString:@"VEC3"]) { + return GLTFDataDimensionVector3; + } else if ([name isEqualToString:@"VEC4"]) { + return GLTFDataDimensionVector4; + } else if ([name isEqualToString:@"MAT2"]) { + return GLTFDataDimensionMatrix2x2; + } else if ([name isEqualToString:@"MAT3"]) { + return GLTFDataDimensionMatrix3x3; + } else if ([name isEqualToString:@"MAT4"]) { + return GLTFDataDimensionMatrix4x4; + } + + return -1; +} + +size_t GLTFSizeOfDataType(GLTFDataType type) { + + switch (type) { + case GLTFDataTypeChar: return sizeof(char); + case GLTFDataTypeUChar: return sizeof(unsigned char); + case GLTFDataTypeShort: return sizeof(short); + case GLTFDataTypeUShort: return sizeof(unsigned short); + case GLTFDataTypeInt: return sizeof(int); + case GLTFDataTypeUInt: return sizeof(unsigned int); + case GLTFDataTypeFloat: return sizeof(float); + case GLTFDataTypeFloat2: return sizeof(float) * 2; + case GLTFDataTypeFloat3: return sizeof(float) * 3; + case GLTFDataTypeFloat4: return sizeof(float) * 4; + case GLTFDataTypeInt2: return sizeof(int) * 2; + case GLTFDataTypeInt3: return sizeof(int) * 3; + case GLTFDataTypeInt4: return sizeof(int) * 4; + case GLTFDataTypeBool: return sizeof(bool); + case GLTFDataTypeBool2: return sizeof(bool) * 2; + case GLTFDataTypeBool3: return sizeof(bool) * 3; + case GLTFDataTypeBool4: return sizeof(bool) * 4; + case GLTFDataTypeFloat2x2: return sizeof(float) * 4; + case GLTFDataTypeFloat3x3: return sizeof(float) * 9; + case GLTFDataTypeFloat4x4: return sizeof(float) * 16; + case GLTFDataTypeSampler2D: return sizeof(size_t); + default: return 0; + } +} + +size_t GLTFSizeOfComponentTypeWithDimension(GLTFDataType baseType, GLTFDataDimension dimension) +{ + switch (baseType) { + case GLTFDataTypeChar: + case GLTFDataTypeUChar: + switch (dimension) { + case GLTFDataDimensionVector2: + return 2; + case GLTFDataDimensionVector3: + return 3; + case GLTFDataDimensionVector4: + return 4; + default: + break; + } + case GLTFDataTypeShort: + case GLTFDataTypeUShort: + switch (dimension) { + case GLTFDataDimensionVector2: + return 4; + case GLTFDataDimensionVector3: + return 6; + case GLTFDataDimensionVector4: + return 8; + default: + break; + } + case GLTFDataTypeInt: + case GLTFDataTypeUInt: + case GLTFDataTypeFloat: + switch (dimension) { + case GLTFDataDimensionScalar: + return 4; + case GLTFDataDimensionVector2: + return 8; + case GLTFDataDimensionVector3: + return 12; + case GLTFDataDimensionVector4: + case GLTFDataDimensionMatrix2x2: + return 16; + case GLTFDataDimensionMatrix3x3: + return 36; + case GLTFDataDimensionMatrix4x4: + return 64; + default: + break; + } + default: + break; + } + return 0; +} + +NSInteger GLTFComponentCountForDimension(GLTFDataDimension dimension) { + switch (dimension) { + case GLTFDataDimensionScalar: + return 1; + case GLTFDataDimensionVector2: + return 2; + case GLTFDataDimensionVector3: + return 3; + case GLTFDataDimensionVector4: + return 4; + case GLTFDataDimensionMatrix2x2: + return 4; + case GLTFDataDimensionMatrix3x3: + return 9; + case GLTFDataDimensionMatrix4x4: + return 16; + default: + return 0; + } +} + +BOOL GLTFDataTypeComponentsAreFloats(GLTFDataType type) { + switch (type) { + case GLTFDataTypeFloat: + case GLTFDataTypeFloat2: + case GLTFDataTypeFloat3: + case GLTFDataTypeFloat4: + case GLTFDataTypeFloat2x2: + case GLTFDataTypeFloat3x3: + case GLTFDataTypeFloat4x4: + return YES; + default: + return NO; + } +} + +simd_float2 GLTFVectorFloat2FromArray(NSArray *array) { + return (simd_float2){ [array[0] floatValue], [array[1] floatValue] }; +} + +simd_float3 GLTFVectorFloat3FromArray(NSArray *array) { + return (simd_float3){ [array[0] floatValue], [array[1] floatValue], [array[2] floatValue] }; +} + +simd_float4 GLTFVectorFloat4FromArray(NSArray *array) { + return (simd_float4){ [array[0] floatValue], [array[1] floatValue], [array[2] floatValue], [array[3] floatValue] }; +} + +GLTFQuaternion GLTFQuaternionFromArray(NSArray *array) { + return simd_quaternion([array[0] floatValue], [array[1] floatValue], [array[2] floatValue], [array[3] floatValue]); +} + +simd_float4x4 GLTFMatrixFloat4x4FromArray(NSArray *array) { + return (simd_float4x4){ { + { [array[0] floatValue], [array[1] floatValue], [array[2] floatValue], [array[3] floatValue] }, + { [array[4] floatValue], [array[5] floatValue], [array[6] floatValue], [array[7] floatValue] }, + { [array[8] floatValue], [array[9] floatValue], [array[10] floatValue], [array[11] floatValue] }, + { [array[12] floatValue], [array[13] floatValue], [array[14] floatValue], [array[15] floatValue] } + } }; +} diff --git a/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.h b/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.h new file mode 100644 index 000000000000..4a73f93ef054 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.h @@ -0,0 +1,54 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import +#import "GLTFEnums.h" + +NS_ASSUME_NONNULL_BEGIN + +extern const NSInteger GLTFVertexDescriptorMaxAttributeCount; +extern const NSInteger GLTFVertexDescriptorMaxBufferLayoutCount; + +extern NSString *const GLTFAttributeSemanticPosition; +extern NSString *const GLTFAttributeSemanticTangent; +extern NSString *const GLTFAttributeSemanticNormal; +extern NSString *const GLTFAttributeSemanticTexCoord0; +extern NSString *const GLTFAttributeSemanticTexCoord1; +extern NSString *const GLTFAttributeSemanticColor0; +extern NSString *const GLTFAttributeSemanticJoints0; +extern NSString *const GLTFAttributeSemanticJoints1; +extern NSString *const GLTFAttributeSemanticWeights0; +extern NSString *const GLTFAttributeSemanticWeights1; +extern NSString *const GLTFAttributeSemanticRoughness; +extern NSString *const GLTFAttributeSemanticMetallic; + +@interface GLTFVertexAttribute : NSObject +@property (nonatomic, copy) NSString *semantic; +@property (nonatomic, assign) GLTFDataType componentType; +@property (nonatomic, assign) GLTFDataDimension dimension; +@property (nonatomic, assign) NSInteger offset; +@end + +@interface GLTFBufferLayout : NSObject +@property (nonatomic, assign) NSInteger stride; +@end + +@interface GLTFVertexDescriptor: NSObject +@property (nonatomic, copy) NSArray *attributes; +@property (nonatomic, copy) NSArray *bufferLayouts; +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.m b/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.m new file mode 100644 index 000000000000..599d8706baa9 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.m @@ -0,0 +1,71 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "GLTFVertexDescriptor.h" + +const NSInteger GLTFVertexDescriptorMaxAttributeCount = 16; +const NSInteger GLTFVertexDescriptorMaxBufferLayoutCount = 16; + +NSString *const GLTFAttributeSemanticPosition = @"POSITION"; +NSString *const GLTFAttributeSemanticTangent = @"TANGENT"; +NSString *const GLTFAttributeSemanticNormal = @"NORMAL"; +NSString *const GLTFAttributeSemanticTexCoord0 = @"TEXCOORD_0"; +NSString *const GLTFAttributeSemanticTexCoord1 = @"TEXCOORD_1"; +NSString *const GLTFAttributeSemanticColor0 = @"COLOR_0"; +NSString *const GLTFAttributeSemanticJoints0 = @"JOINTS_0"; +NSString *const GLTFAttributeSemanticJoints1 = @"JOINTS_1"; +NSString *const GLTFAttributeSemanticWeights0 = @"WEIGHTS_0"; +NSString *const GLTFAttributeSemanticWeights1 = @"WEIGHTS_1"; +NSString *const GLTFAttributeSemanticRoughness = @"ROUGHNESS"; +NSString *const GLTFAttributeSemanticMetallic = @"METALLIC"; + +@implementation GLTFVertexAttribute + +- (NSString *)description { + return [NSString stringWithFormat:@"GLTFVertexAttribute: component type: %d, count: %d, offset %d [[%@]]", + (int)self.componentType, (int)self.dimension, (int)self.offset, self.semantic]; +} + +@end + +@implementation GLTFBufferLayout +@end + +@implementation GLTFVertexDescriptor + +- (instancetype)init { + if ((self = [super init])) { + NSMutableArray *mutableAttributes = [NSMutableArray arrayWithCapacity:GLTFVertexDescriptorMaxAttributeCount]; + for (int i = 0; i < GLTFVertexDescriptorMaxAttributeCount; ++i) { + [mutableAttributes addObject: [GLTFVertexAttribute new]]; + } + _attributes = [mutableAttributes copy]; + + NSMutableArray *mutableLayouts = [NSMutableArray arrayWithCapacity:GLTFVertexDescriptorMaxBufferLayoutCount]; + for (int i = 0; i < GLTFVertexDescriptorMaxBufferLayoutCount; ++i) { + [mutableLayouts addObject: [GLTFBufferLayout new]]; + } + _bufferLayouts = [mutableLayouts copy]; + } + return self; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"GLTFVertexDescriptor:\nattributes: %@\nlayouts: %@", + self.attributes, self.bufferLayouts]; +} + +@end diff --git a/platform/darwin/src/gltf/gltfkit/shaders/brdf.metal b/platform/darwin/src/gltf/gltfkit/shaders/brdf.metal new file mode 100644 index 000000000000..1f4e6b732872 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/shaders/brdf.metal @@ -0,0 +1,230 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#include +using namespace metal; + +// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html +static float RadicalInverse_VdC(uint bits) +{ + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 +} + +static float2 Hammersley(uint i, uint N) { + return float2(float(i) / float(N), RadicalInverse_VdC(i)); +} + +// http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf +static float GeometrySchlickGGX(float NdotV, float roughness) { + float a = roughness; + float k = (a * a) / 2.0; + return NdotV / (NdotV * (1.0 - k) + k); +} + +static float GeometrySmith(float NdotL, float NdotV, float roughness) { + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + return ggx1 * ggx2; +} + +static float3 ImportanceSampleGGX(float2 xi, float3 N, float roughness) { + float a = roughness * roughness; + float phi = 2 * M_PI_F * xi.x; + float cosTheta = sqrt((1 - xi.y) / (1 + (a * a - 1) * xi.y)); + float sinTheta = sqrt(1 - cosTheta * cosTheta); + + float3 H(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); + + float3 up = fabs(N.z) < 0.999 ? float3(0, 0, 1) : float3(1, 0, 0); + float3 tangent = normalize(cross(up, N)); + float3 bitangent = cross(N, tangent); + + return normalize(tangent * H.x + bitangent * H.y + N * H.z); +} + +static float2 IntegrateBRDF(float roughness, float NdotV) { + float3 N(0, 0, 1); + float3 V(sqrt(1.0 - NdotV * NdotV), 0, NdotV); + float A = 0; + float B = 0; + + const uint sampleCount = 1024; + for(uint i = 0; i < sampleCount; ++i) { + float2 x = Hammersley(i, sampleCount); + float3 H = ImportanceSampleGGX(x, N, roughness); + float3 L = normalize(2 * dot(V, H) * H - V); + + float NdotL = saturate(L.z); + float NdotH = saturate(H.z); + float VdotH = saturate(dot(V, H)); + + if(NdotL > 0) { + float G = GeometrySmith(NdotL, NdotV, roughness); + float G_Vis = G * VdotH / (NdotH * NdotV); + float Fc = powr(1 - VdotH, 5); + A += (1 - Fc) * G_Vis; + B += Fc * G_Vis; + } + } + + return float2(A, B) / float(sampleCount); +} + +kernel void integrate_brdf(texture2d lookup [[texture(0)]], + uint2 tpig [[thread_position_in_grid]]) +{ + float NdotV = (tpig.x + 1) / float(lookup.get_width()); + float roughness = (tpig.y + 1) / float(lookup.get_height()); + float2 scaleAndBias = IntegrateBRDF(roughness, NdotV); + half4 color(scaleAndBias.x, scaleAndBias.y, 0, 0); + lookup.write(color, tpig); +} + +static float2 CubeToEquirectCoords(float3 v) { + const float2 invAtan(0.1591, 0.3183); + float2 uv = float2(atan2(v.z, v.x), asin(v.y)) * invAtan + 0.5; + return uv; +} + +static float3 CubeDirectionFromUVAndFace(float2 uv, int face) { + float u = uv.x; + float v = uv.y; + float3 dir = float3(0); + switch (face) { + case 0: + dir = float3(-1, v, -u); break; // +X + case 1: + dir = float3( 1, v, u); break; // -X + case 2: + dir = float3(-u, -1, v); break; // +Y + case 3: + dir = float3(-u, 1, -v); break; // -Y + case 4: + dir = float3(-u, v, 1); break; // +Z + case 5: + dir = float3( u, v, -1); break; // -Z + } + + dir = normalize(dir); + return dir; +} + +kernel void equirect_to_cube(texture2d equirectangularMap, + texturecube cubeMap, + uint3 tpig [[thread_position_in_grid]]) +{ + constexpr sampler sampler2d(coord::normalized, filter::linear, address::repeat); + + float cubeSize = cubeMap.get_width(); + float2 cubeUV = ((float2(tpig.xy) / cubeSize) * 2 - 1); + int face = tpig.z; + float3 dir = CubeDirectionFromUVAndFace(cubeUV, face); + float2 rectUV = CubeToEquirectCoords(dir); + half4 color = equirectangularMap.sample(sampler2d, rectUV); + uint2 coords = tpig.xy; + cubeMap.write(color, coords, face); +} + +static float3 ComputeIrradiance(float3 N, texturecube environmentTexture) { + constexpr sampler cubeSampler(coord::normalized, filter::linear); + float3 irradiance = float3(0.0); + + float3 up(0.0, 1.0, 0.0); + float3 right = cross(up, N); + up = cross(N, right); + + float sampleDelta = 0.025; + float sampleCount = 0; + for (float phi = 0.0; phi < M_PI_F * 2; phi += sampleDelta) { + for (float theta = 0.0; theta < M_PI_F * 0.5; theta += sampleDelta) { + // spherical to cartesian (in tangent space) + float3 tangentSample(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); + // tangent space to world + float3 dir = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N; + + irradiance += float3(environmentTexture.sample(cubeSampler, dir).rgb) * cos(theta) * sin(theta); + sampleCount += 1; + } + } + + irradiance = M_PI_F * irradiance * (1.0 / sampleCount); + return irradiance; +} + +kernel void compute_irradiance(texturecube environmentMap, + texturecube irradianceMap, + uint3 tpig [[thread_position_in_grid]]) +{ + float cubeSize = irradianceMap.get_width(); + float2 cubeUV = ((float2(tpig.xy) / cubeSize) * 2 - 1); + int face = tpig.z; + float3 dir = CubeDirectionFromUVAndFace(cubeUV, face); + dir *= float3(-1, -1, 1); + float3 irrad = ComputeIrradiance(dir, environmentMap); + uint2 coords = tpig.xy; + irradianceMap.write(half4(half3(irrad), 1), coords, face); +} + +static float3 PrefilterEnvMap(float roughness, float3 R, texturecube environmentTexture) { + constexpr sampler cubeSampler(coord::normalized, filter::linear, mip_filter::linear); + + float3 N = R; + float3 V = R; + + float3 prefilteredColor(0); + float totalWeight = 0; + float resolution = environmentTexture.get_width(); + float saTexel = 4.0 * M_PI_F / (6.0 * resolution * resolution); + + const uint sampleCount = 512; + for(uint i = 0; i < sampleCount; ++i) { + float2 xi = Hammersley(i, sampleCount); + float3 H = ImportanceSampleGGX(xi, N, roughness); + float3 L = normalize(2 * dot(V, H) * H - V); + float NdotL = saturate(dot(N, L)); + if(NdotL > 0) { + float NdotH = saturate(dot(N, H)); + float HdotV = saturate(dot(H, V)); + float D = GeometrySchlickGGX(NdotH, roughness); + float pdf = (D * NdotH / (4.0 * HdotV)) + 0.0001; + float saSample = 1.0 / (float(sampleCount) * pdf + 0.0001); + float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel); + prefilteredColor += NdotL * float3(environmentTexture.sample(cubeSampler, L, level(mipLevel)).rgb); + totalWeight += NdotL; + } + } + return prefilteredColor / totalWeight; +} + +kernel void compute_prefiltered_specular(texturecube environmentMap, + texturecube specularMap, + constant float &roughness [[buffer(0)]], + uint3 tpig [[thread_position_in_grid]]) +{ + float cubeSize = specularMap.get_width(); + float2 cubeUV = ((float2(tpig.xy) / cubeSize) * 2 - 1); + int face = tpig.z; + float3 dir = CubeDirectionFromUVAndFace(cubeUV, face); + dir *= float3(-1, -1, 1); + float3 irrad = PrefilterEnvMap(roughness, dir, environmentMap); + uint2 coords = tpig.xy; + specularMap.write(half4(half3(irrad), 1), coords, face); +} diff --git a/platform/darwin/src/gltf/gltfkit/shaders/hdr.metal b/platform/darwin/src/gltf/gltfkit/shaders/hdr.metal new file mode 100644 index 000000000000..bb7f505a1a9f --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/shaders/hdr.metal @@ -0,0 +1,123 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#include +using namespace metal; + +constexpr sampler linearSampler(coord::normalized, min_filter::linear, mag_filter::linear); +constexpr sampler nearestSampler(coord::normalized, min_filter::nearest, mag_filter::nearest); + +struct VertexOut { + float4 position [[position]]; + float2 texCoords; +}; + +vertex VertexOut quad_vertex_main(constant packed_float4 *vertices [[buffer(0)]], + uint vid [[vertex_id]]) +{ + VertexOut out; + float4 in = vertices[vid]; + out.position = float4(in.xy, 0, 1); + out.texCoords = in.zw; + return out; +} + +typedef VertexOut FragmentIn; + +static half3 reinhardToneMapping(half3 color) { + half exposure = 1.5; + color *= exposure / (1 + color / exposure); + return color; +} + +fragment half4 tonemap_fragment_main(FragmentIn in [[stage_in]], + texture2d sourceTexture [[texture(0)]]) +{ + // Original, pre-alpha +// half3 color = sourceTexture.sample(linearSampler, in.texCoords).rgb; +// return half4(reinhardToneMapping(color), 1); + + half4 color = sourceTexture.sample(linearSampler, in.texCoords); + return half4(reinhardToneMapping(color.rgb), color.a); + +} + + +fragment half4 bloom_threshold_fragment_main(FragmentIn in [[stage_in]], + texture2d sourceTexture [[texture(0)]]) +{ + const float bloomThreshold = 0.88; + const float bloomIntensity = 2; + half4 color = sourceTexture.sample(linearSampler, in.texCoords); + half luma = dot(color.rgb, half3(0.2126, 0.7152, 0.0722)); + return (luma > bloomThreshold) ? color * bloomIntensity : half4(0, 0, 0, 1); +} + +fragment half4 blur_horizontal7_fragment_main(FragmentIn in [[stage_in]], + texture2d sourceTexture [[texture(0)]]) +{ + float weights[]{ 0.134032, 0.126854, 0.107545, 0.08167, 0.055555, 0.033851, 0.018476, 0.009033 }; + float offset = 1.0 / sourceTexture.get_width(); + half4 color(0); + color += weights[7] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 7, 0)); + color += weights[6] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 6, 0)); + color += weights[5] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 5, 0)); + color += weights[4] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 4, 0)); + color += weights[3] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 3, 0)); + color += weights[2] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 2, 0)); + color += weights[1] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 1, 0)); + color += weights[0] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 0, 0)); + color += weights[1] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 1, 0)); + color += weights[2] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 2, 0)); + color += weights[3] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 3, 0)); + color += weights[4] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 4, 0)); + color += weights[5] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 5, 0)); + color += weights[6] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 6, 0)); + color += weights[7] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 7, 0)); + return color; +} + +fragment half4 blur_vertical7_fragment_main(FragmentIn in [[stage_in]], + texture2d sourceTexture [[texture(0)]]) +{ + float weights[]{ 0.134032, 0.126854, 0.107545, 0.08167, 0.055555, 0.033851, 0.018476, 0.009033 }; + float offset = 1.0 / sourceTexture.get_height(); + half4 color(0); + color += weights[7] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 7)); + color += weights[6] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 6)); + color += weights[5] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 5)); + color += weights[4] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 4)); + color += weights[3] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 3)); + color += weights[2] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 2)); + color += weights[1] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 1)); + color += weights[0] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 0)); + color += weights[1] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 1)); + color += weights[2] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 2)); + color += weights[3] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 3)); + color += weights[4] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 4)); + color += weights[5] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 5)); + color += weights[6] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 6)); + color += weights[7] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 7)); + return color; +} + +fragment half4 additive_blend_fragment_main(FragmentIn in [[stage_in]], + texture2d sourceTexture [[texture(0)]]) +{ + half4 color = sourceTexture.sample(linearSampler, in.texCoords); + return color; +} + diff --git a/platform/darwin/src/gltf/gltfkit/shaders/pbr.metal b/platform/darwin/src/gltf/gltfkit/shaders/pbr.metal new file mode 100644 index 000000000000..ad5ae9409c17 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/shaders/pbr.metal @@ -0,0 +1,463 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#include +using namespace metal; + +constant half minRoughness = 0.04; + +constant int textureIndexBaseColor = 0; +constant int textureIndexNormal = 1; +constant int textureIndexMetallicRoughness = 2; +constant int textureIndexOcclusion = 3; +constant int textureIndexEmissive = 4; +constant int textureIndexDiffuseEnvironment = 5; +constant int textureIndexSpecularEnvironment = 6; +constant int textureIndexBRDFLookup = 7; + +/*%begin_replace_decls%*/ +#define USE_PBR 1 +#define USE_IBL 1 +#define USE_ALPHA_TEST 0 +#define USE_VERTEX_SKINNING 1 +#define USE_EXTENDED_VERTEX_SKINNING 1 +#define USE_DOUBLE_SIDED_MATERIAL 1 +#define HAS_TEXCOORD_0 1 +#define HAS_TEXCOORD_1 1 +#define HAS_VERTEX_COLOR 1 +#define HAS_VERTEX_ROUGHNESS 1 +#define HAS_VERTEX_METALLIC 1 +#define HAS_NORMALS 1 +#define HAS_TANGENTS 1 +#define HAS_BASE_COLOR_MAP 1 +#define HAS_NORMAL_MAP 1 +#define HAS_METALLIC_ROUGHNESS_MAP 1 +#define HAS_OCCLUSION_MAP 1 +#define HAS_EMISSIVE_MAP 1 +#define HAS_TEXTURE_TRANSFORM 1 +#define MATERIAL_IS_UNLIT 0 +#define PREMULTIPLY_BASE_COLOR 1 +#define SPECULAR_ENV_MIP_LEVELS 6 +#define MAX_LIGHTS 3 +#define MAX_MATERIAL_TEXTURES 5 + +#define BaseColorTexCoord texCoord0 +#define NormalTexCoord texCoord0 +#define MetallicRoughnessTexCoord texCoord0 +#define EmissiveTexCoord texCoord0 +#define OcclusionTexCoord texCoord0 + +struct VertexIn { + float3 position [[attribute(0)]]; + float3 normal [[attribute(1)]]; + float4 tangent [[attribute(2)]]; + float2 texCoord0 [[attribute(3)]]; + float2 texCoord1 [[attribute(4)]]; + float4 color [[attribute(5)]]; + float4 weights0 [[attribute(6)]]; + float4 weights1 [[attribute(7)]]; + ushort4 joints0 [[attribute(8)]]; + ushort4 joints1 [[attribute(9)]]; + float roughness [[attribute(10)]]; + float metalness [[attribute(11)]]; +}; +/*%end_replace_decls%*/ + +struct VertexOut { + float4 position [[position]]; + float3 worldPosition; + float2 texCoord0; + float2 texCoord1; + float4 color; + float3 tangent; + float3 bitangent; + float3 normal; + float roughness; + float metalness; +}; + +struct VertexUniforms { + float4x4 modelMatrix; + float4x4 modelViewProjectionMatrix; + float4x4 normalMatrix; +}; + +struct Light { + float4 position; + float4 color; + float intensity; + float innerConeAngle; + float outerConeAngle; + float range; + float4 spotDirection; +}; + +struct FragmentUniforms { + float normalScale; + float3 emissiveFactor; + float occlusionStrength; + float2 metallicRoughnessValues; + float4 baseColorFactor; + float3 camera; + float alphaCutoff; + float envIntensity; + Light ambientLight; + Light lights[MAX_LIGHTS]; + float3x3 textureMatrices[MAX_MATERIAL_TEXTURES]; +}; + +vertex VertexOut vertex_main(VertexIn in [[stage_in]], + constant VertexUniforms &uniforms [[buffer(16)]] +#if USE_VERTEX_SKINNING + , constant float4x4 *jointMatrices [[buffer(17)]] +#endif +) +{ + VertexOut out = { 0 }; + + float4x4 normalMatrix = uniforms.normalMatrix; + + #if USE_VERTEX_SKINNING + ushort4 jointIndices = ushort4(in.joints0); + float4 jointWeights = float4(in.weights0); + + float4x4 skinMatrix = jointWeights[0] * jointMatrices[jointIndices[0]] + + jointWeights[1] * jointMatrices[jointIndices[1]] + + jointWeights[2] * jointMatrices[jointIndices[2]] + + jointWeights[3] * jointMatrices[jointIndices[3]]; + + #if USE_EXTENDED_VERTEX_SKINNING + jointIndices = ushort4(in.joints1); + jointWeights = float4(in.weights1); + + skinMatrix += jointWeights[0] * jointMatrices[jointIndices[0]] + + jointWeights[1] * jointMatrices[jointIndices[1]] + + jointWeights[2] * jointMatrices[jointIndices[2]] + + jointWeights[3] * jointMatrices[jointIndices[3]]; + #endif + + float4 skinnedPosition = skinMatrix * float4(in.position.xyz, 1); + normalMatrix = normalMatrix * skinMatrix; + #else + float4 skinnedPosition = float4(in.position.xyz, 1); + #endif + + float4 position = uniforms.modelMatrix * skinnedPosition; + out.worldPosition = position.xyz / position.w; + + out.position = uniforms.modelViewProjectionMatrix * skinnedPosition; + + #if HAS_NORMALS + #if HAS_TANGENTS + float3 normalW = normalize(float3(normalMatrix * float4(in.normal.xyz, 0.0))); + float3 tangentW = normalize(float3(normalMatrix * float4(in.tangent.xyz, 0.0))); + float3 bitangentW = cross(normalW, tangentW) * in.tangent.w; + out.tangent = tangentW; + out.bitangent = bitangentW; + out.normal = normalW; + #else + out.normal = normalize(float3(normalMatrix * float4(in.normal.xyz, 0.0))); + #endif + #endif + + #if HAS_VERTEX_COLOR + #if VERTEX_COLOR_IS_RGB + out.color = float4(in.color, 1); + #else + out.color = in.color; + #endif + #endif + + #if HAS_VERTEX_ROUGHNESS + out.roughness = in.roughness; + #endif + + #if HAS_VERTEX_METALLIC + out.metalness = in.metalness; + #endif + + #if HAS_TEXCOORD_0 + out.texCoord0 = in.texCoord0; + #endif + + #if HAS_TEXCOORD_1 + out.texCoord1 = in.texCoord1; + #endif + + return out; +} + +static half3 LambertDiffuse(half3 baseColor) +{ + return baseColor / M_PI_F; +} + +static half3 SchlickFresnel(half3 F0, float LdotH) +{ + return F0 + (1 - F0) * pow(1.0 - LdotH, 5.0); +} + +static float SmithGeometric(float NdotL, float NdotV, float roughness) +{ + float k = roughness * 0.5; + float Gl = NdotL / ((NdotL * (1 - k)) + k); + float Gv = NdotV / ((NdotV * (1 - k)) + k); + return Gl * Gv; +} + +static float TrowbridgeReitzNDF(float NdotH, float roughness) +{ + float roughnessSq = roughness * roughness; + float f = NdotH * (NdotH * roughnessSq - NdotH) + 1; + return roughnessSq / (M_PI_F * f * f); +} + +fragment half4 fragment_main(VertexOut in [[stage_in]], +#if HAS_BASE_COLOR_MAP + texture2d baseColorTexture [[texture(textureIndexBaseColor)]], + sampler baseColorSampler [[sampler(textureIndexBaseColor)]], +#endif +#if HAS_NORMAL_MAP + texture2d normalTexture [[texture(textureIndexNormal)]], + sampler normalSampler [[sampler(textureIndexNormal)]], +#endif +#if HAS_EMISSIVE_MAP + texture2d emissiveTexture [[texture(textureIndexEmissive)]], + sampler emissiveSampler [[sampler(textureIndexEmissive)]], +#endif +#if HAS_METALLIC_ROUGHNESS_MAP + texture2d metallicRoughnessTexture [[texture(textureIndexMetallicRoughness)]], + sampler metallicRoughnessSampler [[sampler(textureIndexMetallicRoughness)]], +#endif +#if HAS_OCCLUSION_MAP + texture2d occlusionTexture [[texture(textureIndexOcclusion)]], + sampler occlusionSampler [[sampler(textureIndexOcclusion)]], +#endif +#if USE_IBL + texturecube diffuseEnvTexture [[texture(textureIndexDiffuseEnvironment)]], + texturecube specularEnvTexture [[texture(textureIndexSpecularEnvironment)]], + texture2d brdfLUT [[texture(textureIndexBRDFLookup)]], +#endif + constant FragmentUniforms &uniforms [[buffer(0)]], + bool frontFacing [[front_facing]]) +{ + + #if HAS_TEXTURE_TRANSFORM + float2 baseColorTexCoord = (uniforms.textureMatrices[textureIndexBaseColor] * float3(in.BaseColorTexCoord, 1)).xy; + float2 normalTexCoord = (uniforms.textureMatrices[textureIndexNormal] * float3(in.NormalTexCoord, 1)).xy; + float2 metallicRoughnessTexCoord = (uniforms.textureMatrices[textureIndexMetallicRoughness] * float3(in.MetallicRoughnessTexCoord, 1)).xy; + float2 occlusionTexCoord = (uniforms.textureMatrices[textureIndexOcclusion] * float3(in.OcclusionTexCoord, 1)).xy; + float2 emissiveTexCoord = (uniforms.textureMatrices[textureIndexEmissive] * float3(in.EmissiveTexCoord, 1)).xy; + #else + float2 baseColorTexCoord = in.BaseColorTexCoord; + float2 normalTexCoord = in.NormalTexCoord; + float2 metallicRoughnessTexCoord = in.MetallicRoughnessTexCoord; + float2 occlusionTexCoord = in.OcclusionTexCoord; + float2 emissiveTexCoord = in.EmissiveTexCoord; + #endif + + float3x3 tbn; + #if !HAS_TANGENTS + float3 pos_dx = dfdx(in.worldPosition); + float3 pos_dy = dfdy(in.worldPosition); + float3 tex_dx = dfdx(float3(normalTexCoord, 0)); + float3 tex_dy = dfdy(float3(normalTexCoord, 0)); + float3 t = (tex_dy.y * pos_dx - tex_dx.y * pos_dy) / (tex_dx.x * tex_dy.y - tex_dy.x * tex_dx.y); + + float3 ng(0); + #if HAS_NORMALS + ng = normalize(in.normal); + #else + ng = cross(pos_dx, pos_dy); + #endif + t = normalize(t - ng * dot(ng, t)); + float3 b = normalize(cross(ng, t)); + tbn = float3x3(t, b, ng); + #else + tbn = float3x3(in.tangent, in.bitangent, in.normal); + #endif + + float3 N(0, 0, 1); + #if HAS_NORMAL_MAP + N = normalTexture.sample(normalSampler, normalTexCoord).rgb; + N = normalize(tbn * ((2 * N - 1) * float3(uniforms.normalScale, uniforms.normalScale, 1))); + #else + N = tbn[2].xyz; + #endif + + #if USE_DOUBLE_SIDED_MATERIAL + N *= frontFacing ? 1 : -1; + #endif + + half perceptualRoughness = uniforms.metallicRoughnessValues.y; + half metallic = uniforms.metallicRoughnessValues.x; + + #if HAS_METALLIC_ROUGHNESS_MAP + half4 mrSample = metallicRoughnessTexture.sample(metallicRoughnessSampler, metallicRoughnessTexCoord); + perceptualRoughness = mrSample.g * perceptualRoughness; + metallic = mrSample.b * metallic; + #endif + + #if HAS_VERTEX_ROUGHNESS + perceptualRoughness = in.roughness; + #endif + + #if HAS_VERTEX_METALLIC + metallic = in.metalness; + #endif + + perceptualRoughness = clamp(perceptualRoughness, minRoughness, 1.0h); + metallic = saturate(metallic); + + half4 baseColor; + #if HAS_BASE_COLOR_MAP + baseColor = baseColorTexture.sample(baseColorSampler, baseColorTexCoord); + #if PREMULTIPLY_BASE_COLOR + baseColor.rgb *= baseColor.a; + #endif + baseColor *= half4(uniforms.baseColorFactor); + #else + baseColor = half4(uniforms.baseColorFactor); + #endif + + #if HAS_VERTEX_COLOR + baseColor *= half4(in.color); + #endif + + #if MATERIAL_IS_UNLIT + #if USE_ALPHA_TEST + if (baseColor.a < uniforms.alphaCutoff) { + discard_fragment(); + } + #endif + return baseColor; + #endif + + half3 f0(0.04); + half3 diffuseColor = mix(baseColor.rgb * (1 - f0), half3(0), metallic); + half3 specularColor = mix(f0, baseColor.rgb, metallic); + + half3 F0 = specularColor.rgb; + + float alphaRoughness = perceptualRoughness * perceptualRoughness; + + float3 V = normalize(uniforms.camera - in.worldPosition); + float NdotV = saturate(dot(N, V)); + + float3 reflection = normalize(reflect(V, N)) * float3(-1, -1, 1); + + half3 color(0); + + #if USE_PBR + color += half3(uniforms.ambientLight.color.rgb * uniforms.ambientLight.intensity) * diffuseColor; + + for (int i = 0; i < MAX_LIGHTS; ++i) { + Light light = uniforms.lights[i]; + + float3 L = normalize((light.position.w == 0) ? -light.position.xyz : (light.position.xyz - in.worldPosition)); + float3 H = normalize(L + V); + + float NdotL = saturate(dot(N, L)); + float NdotH = saturate(dot(N, H)); + float VdotH = saturate(dot(V, H)); + + half3 F = SchlickFresnel(F0, VdotH); + float G = SmithGeometric(NdotL, NdotV, alphaRoughness); + float D = TrowbridgeReitzNDF(NdotH, alphaRoughness); + + half3 diffuseContrib(0); + half3 specContrib(0); + if (NdotL > 0) { + diffuseContrib = NdotL * LambertDiffuse(diffuseColor); + specContrib = NdotL * D * F * G / (4.0 * NdotL * NdotV); + } + + half lightDist = length(light.position.xyz - in.worldPosition); + half attenNum = (light.range > 0) ? saturate(1.0 - powr(lightDist / light.range, 4)) : 1; + half atten = (light.position.w == 0) ? 1 : attenNum / powr(lightDist, 2); + + float relativeSpotAngle = acos(dot(-L, normalize(light.spotDirection.xyz))); + float spotAttenParam = 1 - clamp((relativeSpotAngle - light.innerConeAngle) / max(0.001, light.outerConeAngle - light.innerConeAngle), 0.0, 1.0); + float spotAtten = spotAttenParam * spotAttenParam * (3 - 2 * spotAttenParam); + atten *= spotAtten; + + color += half3(light.color.rgb * light.intensity) * atten * (diffuseContrib + specContrib); + } + #endif + +// baseColor = baseColorTexture.sample(baseColorSampler, baseColorTexCoord); + + half3 diffuseLight1 = half3(0.5,0.5,0.5); + diffuseLight1 *= uniforms.envIntensity; + half3 specularLight1(0.5); + specularLight1 *= uniforms.envIntensity; + half3 iblDiffuse1 = diffuseLight1 * diffuseColor; + half3 iblSpecular1 = specularLight1;// * ((specularColor * brdf.x) + brdf.y); + half3 iblColor1 = iblDiffuse1 + iblSpecular1; + color += iblColor1; + color = baseColor.rgb * NdotV; + + + + + return half4(color, baseColor.a); + + + #if USE_IBL + constexpr sampler cubeSampler(coord::normalized, filter::linear, mip_filter::linear); + float mipCount = SPECULAR_ENV_MIP_LEVELS; + float lod = perceptualRoughness * (mipCount - 1); + half2 brdf = brdfLUT.sample(cubeSampler, float2(NdotV, perceptualRoughness)).xy; + half3 diffuseLight = diffuseEnvTexture.sample(cubeSampler, N).rgb; + diffuseLight *= uniforms.envIntensity; + + half3 specularLight(0); + if (mipCount > 1) { + specularLight = specularEnvTexture.sample(cubeSampler, reflection, level(lod)).rgb; + } else { + specularLight = specularEnvTexture.sample(cubeSampler, reflection).rgb; + } + specularLight *= uniforms.envIntensity; + + half3 iblDiffuse = diffuseLight * diffuseColor; + half3 iblSpecular = specularLight * ((specularColor * brdf.x) + brdf.y); + + half3 iblColor = iblDiffuse + iblSpecular; + + color += iblColor; + #endif + + + #if HAS_OCCLUSION_MAP + half ao = occlusionTexture.sample(occlusionSampler, occlusionTexCoord).r; + color = mix(color, color * ao, half(uniforms.occlusionStrength)); + #endif + + #if HAS_EMISSIVE_MAP + half3 emissive = emissiveTexture.sample(emissiveSampler, emissiveTexCoord).rgb; + color += emissive * half3(uniforms.emissiveFactor); + #else + color += half3(uniforms.emissiveFactor); + #endif + + #if USE_ALPHA_TEST + if (baseColor.a < uniforms.alphaCutoff) { + discard_fragment(); + } + #endif + + return half4(color, baseColor.a); +} diff --git a/platform/darwin/src/gltf/gltfkit/shaders/pbr.txt b/platform/darwin/src/gltf/gltfkit/shaders/pbr.txt new file mode 100644 index 000000000000..ad5ae9409c17 --- /dev/null +++ b/platform/darwin/src/gltf/gltfkit/shaders/pbr.txt @@ -0,0 +1,463 @@ +// +// Copyright (c) 2018 Warren Moore. All rights reserved. +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#include +using namespace metal; + +constant half minRoughness = 0.04; + +constant int textureIndexBaseColor = 0; +constant int textureIndexNormal = 1; +constant int textureIndexMetallicRoughness = 2; +constant int textureIndexOcclusion = 3; +constant int textureIndexEmissive = 4; +constant int textureIndexDiffuseEnvironment = 5; +constant int textureIndexSpecularEnvironment = 6; +constant int textureIndexBRDFLookup = 7; + +/*%begin_replace_decls%*/ +#define USE_PBR 1 +#define USE_IBL 1 +#define USE_ALPHA_TEST 0 +#define USE_VERTEX_SKINNING 1 +#define USE_EXTENDED_VERTEX_SKINNING 1 +#define USE_DOUBLE_SIDED_MATERIAL 1 +#define HAS_TEXCOORD_0 1 +#define HAS_TEXCOORD_1 1 +#define HAS_VERTEX_COLOR 1 +#define HAS_VERTEX_ROUGHNESS 1 +#define HAS_VERTEX_METALLIC 1 +#define HAS_NORMALS 1 +#define HAS_TANGENTS 1 +#define HAS_BASE_COLOR_MAP 1 +#define HAS_NORMAL_MAP 1 +#define HAS_METALLIC_ROUGHNESS_MAP 1 +#define HAS_OCCLUSION_MAP 1 +#define HAS_EMISSIVE_MAP 1 +#define HAS_TEXTURE_TRANSFORM 1 +#define MATERIAL_IS_UNLIT 0 +#define PREMULTIPLY_BASE_COLOR 1 +#define SPECULAR_ENV_MIP_LEVELS 6 +#define MAX_LIGHTS 3 +#define MAX_MATERIAL_TEXTURES 5 + +#define BaseColorTexCoord texCoord0 +#define NormalTexCoord texCoord0 +#define MetallicRoughnessTexCoord texCoord0 +#define EmissiveTexCoord texCoord0 +#define OcclusionTexCoord texCoord0 + +struct VertexIn { + float3 position [[attribute(0)]]; + float3 normal [[attribute(1)]]; + float4 tangent [[attribute(2)]]; + float2 texCoord0 [[attribute(3)]]; + float2 texCoord1 [[attribute(4)]]; + float4 color [[attribute(5)]]; + float4 weights0 [[attribute(6)]]; + float4 weights1 [[attribute(7)]]; + ushort4 joints0 [[attribute(8)]]; + ushort4 joints1 [[attribute(9)]]; + float roughness [[attribute(10)]]; + float metalness [[attribute(11)]]; +}; +/*%end_replace_decls%*/ + +struct VertexOut { + float4 position [[position]]; + float3 worldPosition; + float2 texCoord0; + float2 texCoord1; + float4 color; + float3 tangent; + float3 bitangent; + float3 normal; + float roughness; + float metalness; +}; + +struct VertexUniforms { + float4x4 modelMatrix; + float4x4 modelViewProjectionMatrix; + float4x4 normalMatrix; +}; + +struct Light { + float4 position; + float4 color; + float intensity; + float innerConeAngle; + float outerConeAngle; + float range; + float4 spotDirection; +}; + +struct FragmentUniforms { + float normalScale; + float3 emissiveFactor; + float occlusionStrength; + float2 metallicRoughnessValues; + float4 baseColorFactor; + float3 camera; + float alphaCutoff; + float envIntensity; + Light ambientLight; + Light lights[MAX_LIGHTS]; + float3x3 textureMatrices[MAX_MATERIAL_TEXTURES]; +}; + +vertex VertexOut vertex_main(VertexIn in [[stage_in]], + constant VertexUniforms &uniforms [[buffer(16)]] +#if USE_VERTEX_SKINNING + , constant float4x4 *jointMatrices [[buffer(17)]] +#endif +) +{ + VertexOut out = { 0 }; + + float4x4 normalMatrix = uniforms.normalMatrix; + + #if USE_VERTEX_SKINNING + ushort4 jointIndices = ushort4(in.joints0); + float4 jointWeights = float4(in.weights0); + + float4x4 skinMatrix = jointWeights[0] * jointMatrices[jointIndices[0]] + + jointWeights[1] * jointMatrices[jointIndices[1]] + + jointWeights[2] * jointMatrices[jointIndices[2]] + + jointWeights[3] * jointMatrices[jointIndices[3]]; + + #if USE_EXTENDED_VERTEX_SKINNING + jointIndices = ushort4(in.joints1); + jointWeights = float4(in.weights1); + + skinMatrix += jointWeights[0] * jointMatrices[jointIndices[0]] + + jointWeights[1] * jointMatrices[jointIndices[1]] + + jointWeights[2] * jointMatrices[jointIndices[2]] + + jointWeights[3] * jointMatrices[jointIndices[3]]; + #endif + + float4 skinnedPosition = skinMatrix * float4(in.position.xyz, 1); + normalMatrix = normalMatrix * skinMatrix; + #else + float4 skinnedPosition = float4(in.position.xyz, 1); + #endif + + float4 position = uniforms.modelMatrix * skinnedPosition; + out.worldPosition = position.xyz / position.w; + + out.position = uniforms.modelViewProjectionMatrix * skinnedPosition; + + #if HAS_NORMALS + #if HAS_TANGENTS + float3 normalW = normalize(float3(normalMatrix * float4(in.normal.xyz, 0.0))); + float3 tangentW = normalize(float3(normalMatrix * float4(in.tangent.xyz, 0.0))); + float3 bitangentW = cross(normalW, tangentW) * in.tangent.w; + out.tangent = tangentW; + out.bitangent = bitangentW; + out.normal = normalW; + #else + out.normal = normalize(float3(normalMatrix * float4(in.normal.xyz, 0.0))); + #endif + #endif + + #if HAS_VERTEX_COLOR + #if VERTEX_COLOR_IS_RGB + out.color = float4(in.color, 1); + #else + out.color = in.color; + #endif + #endif + + #if HAS_VERTEX_ROUGHNESS + out.roughness = in.roughness; + #endif + + #if HAS_VERTEX_METALLIC + out.metalness = in.metalness; + #endif + + #if HAS_TEXCOORD_0 + out.texCoord0 = in.texCoord0; + #endif + + #if HAS_TEXCOORD_1 + out.texCoord1 = in.texCoord1; + #endif + + return out; +} + +static half3 LambertDiffuse(half3 baseColor) +{ + return baseColor / M_PI_F; +} + +static half3 SchlickFresnel(half3 F0, float LdotH) +{ + return F0 + (1 - F0) * pow(1.0 - LdotH, 5.0); +} + +static float SmithGeometric(float NdotL, float NdotV, float roughness) +{ + float k = roughness * 0.5; + float Gl = NdotL / ((NdotL * (1 - k)) + k); + float Gv = NdotV / ((NdotV * (1 - k)) + k); + return Gl * Gv; +} + +static float TrowbridgeReitzNDF(float NdotH, float roughness) +{ + float roughnessSq = roughness * roughness; + float f = NdotH * (NdotH * roughnessSq - NdotH) + 1; + return roughnessSq / (M_PI_F * f * f); +} + +fragment half4 fragment_main(VertexOut in [[stage_in]], +#if HAS_BASE_COLOR_MAP + texture2d baseColorTexture [[texture(textureIndexBaseColor)]], + sampler baseColorSampler [[sampler(textureIndexBaseColor)]], +#endif +#if HAS_NORMAL_MAP + texture2d normalTexture [[texture(textureIndexNormal)]], + sampler normalSampler [[sampler(textureIndexNormal)]], +#endif +#if HAS_EMISSIVE_MAP + texture2d emissiveTexture [[texture(textureIndexEmissive)]], + sampler emissiveSampler [[sampler(textureIndexEmissive)]], +#endif +#if HAS_METALLIC_ROUGHNESS_MAP + texture2d metallicRoughnessTexture [[texture(textureIndexMetallicRoughness)]], + sampler metallicRoughnessSampler [[sampler(textureIndexMetallicRoughness)]], +#endif +#if HAS_OCCLUSION_MAP + texture2d occlusionTexture [[texture(textureIndexOcclusion)]], + sampler occlusionSampler [[sampler(textureIndexOcclusion)]], +#endif +#if USE_IBL + texturecube diffuseEnvTexture [[texture(textureIndexDiffuseEnvironment)]], + texturecube specularEnvTexture [[texture(textureIndexSpecularEnvironment)]], + texture2d brdfLUT [[texture(textureIndexBRDFLookup)]], +#endif + constant FragmentUniforms &uniforms [[buffer(0)]], + bool frontFacing [[front_facing]]) +{ + + #if HAS_TEXTURE_TRANSFORM + float2 baseColorTexCoord = (uniforms.textureMatrices[textureIndexBaseColor] * float3(in.BaseColorTexCoord, 1)).xy; + float2 normalTexCoord = (uniforms.textureMatrices[textureIndexNormal] * float3(in.NormalTexCoord, 1)).xy; + float2 metallicRoughnessTexCoord = (uniforms.textureMatrices[textureIndexMetallicRoughness] * float3(in.MetallicRoughnessTexCoord, 1)).xy; + float2 occlusionTexCoord = (uniforms.textureMatrices[textureIndexOcclusion] * float3(in.OcclusionTexCoord, 1)).xy; + float2 emissiveTexCoord = (uniforms.textureMatrices[textureIndexEmissive] * float3(in.EmissiveTexCoord, 1)).xy; + #else + float2 baseColorTexCoord = in.BaseColorTexCoord; + float2 normalTexCoord = in.NormalTexCoord; + float2 metallicRoughnessTexCoord = in.MetallicRoughnessTexCoord; + float2 occlusionTexCoord = in.OcclusionTexCoord; + float2 emissiveTexCoord = in.EmissiveTexCoord; + #endif + + float3x3 tbn; + #if !HAS_TANGENTS + float3 pos_dx = dfdx(in.worldPosition); + float3 pos_dy = dfdy(in.worldPosition); + float3 tex_dx = dfdx(float3(normalTexCoord, 0)); + float3 tex_dy = dfdy(float3(normalTexCoord, 0)); + float3 t = (tex_dy.y * pos_dx - tex_dx.y * pos_dy) / (tex_dx.x * tex_dy.y - tex_dy.x * tex_dx.y); + + float3 ng(0); + #if HAS_NORMALS + ng = normalize(in.normal); + #else + ng = cross(pos_dx, pos_dy); + #endif + t = normalize(t - ng * dot(ng, t)); + float3 b = normalize(cross(ng, t)); + tbn = float3x3(t, b, ng); + #else + tbn = float3x3(in.tangent, in.bitangent, in.normal); + #endif + + float3 N(0, 0, 1); + #if HAS_NORMAL_MAP + N = normalTexture.sample(normalSampler, normalTexCoord).rgb; + N = normalize(tbn * ((2 * N - 1) * float3(uniforms.normalScale, uniforms.normalScale, 1))); + #else + N = tbn[2].xyz; + #endif + + #if USE_DOUBLE_SIDED_MATERIAL + N *= frontFacing ? 1 : -1; + #endif + + half perceptualRoughness = uniforms.metallicRoughnessValues.y; + half metallic = uniforms.metallicRoughnessValues.x; + + #if HAS_METALLIC_ROUGHNESS_MAP + half4 mrSample = metallicRoughnessTexture.sample(metallicRoughnessSampler, metallicRoughnessTexCoord); + perceptualRoughness = mrSample.g * perceptualRoughness; + metallic = mrSample.b * metallic; + #endif + + #if HAS_VERTEX_ROUGHNESS + perceptualRoughness = in.roughness; + #endif + + #if HAS_VERTEX_METALLIC + metallic = in.metalness; + #endif + + perceptualRoughness = clamp(perceptualRoughness, minRoughness, 1.0h); + metallic = saturate(metallic); + + half4 baseColor; + #if HAS_BASE_COLOR_MAP + baseColor = baseColorTexture.sample(baseColorSampler, baseColorTexCoord); + #if PREMULTIPLY_BASE_COLOR + baseColor.rgb *= baseColor.a; + #endif + baseColor *= half4(uniforms.baseColorFactor); + #else + baseColor = half4(uniforms.baseColorFactor); + #endif + + #if HAS_VERTEX_COLOR + baseColor *= half4(in.color); + #endif + + #if MATERIAL_IS_UNLIT + #if USE_ALPHA_TEST + if (baseColor.a < uniforms.alphaCutoff) { + discard_fragment(); + } + #endif + return baseColor; + #endif + + half3 f0(0.04); + half3 diffuseColor = mix(baseColor.rgb * (1 - f0), half3(0), metallic); + half3 specularColor = mix(f0, baseColor.rgb, metallic); + + half3 F0 = specularColor.rgb; + + float alphaRoughness = perceptualRoughness * perceptualRoughness; + + float3 V = normalize(uniforms.camera - in.worldPosition); + float NdotV = saturate(dot(N, V)); + + float3 reflection = normalize(reflect(V, N)) * float3(-1, -1, 1); + + half3 color(0); + + #if USE_PBR + color += half3(uniforms.ambientLight.color.rgb * uniforms.ambientLight.intensity) * diffuseColor; + + for (int i = 0; i < MAX_LIGHTS; ++i) { + Light light = uniforms.lights[i]; + + float3 L = normalize((light.position.w == 0) ? -light.position.xyz : (light.position.xyz - in.worldPosition)); + float3 H = normalize(L + V); + + float NdotL = saturate(dot(N, L)); + float NdotH = saturate(dot(N, H)); + float VdotH = saturate(dot(V, H)); + + half3 F = SchlickFresnel(F0, VdotH); + float G = SmithGeometric(NdotL, NdotV, alphaRoughness); + float D = TrowbridgeReitzNDF(NdotH, alphaRoughness); + + half3 diffuseContrib(0); + half3 specContrib(0); + if (NdotL > 0) { + diffuseContrib = NdotL * LambertDiffuse(diffuseColor); + specContrib = NdotL * D * F * G / (4.0 * NdotL * NdotV); + } + + half lightDist = length(light.position.xyz - in.worldPosition); + half attenNum = (light.range > 0) ? saturate(1.0 - powr(lightDist / light.range, 4)) : 1; + half atten = (light.position.w == 0) ? 1 : attenNum / powr(lightDist, 2); + + float relativeSpotAngle = acos(dot(-L, normalize(light.spotDirection.xyz))); + float spotAttenParam = 1 - clamp((relativeSpotAngle - light.innerConeAngle) / max(0.001, light.outerConeAngle - light.innerConeAngle), 0.0, 1.0); + float spotAtten = spotAttenParam * spotAttenParam * (3 - 2 * spotAttenParam); + atten *= spotAtten; + + color += half3(light.color.rgb * light.intensity) * atten * (diffuseContrib + specContrib); + } + #endif + +// baseColor = baseColorTexture.sample(baseColorSampler, baseColorTexCoord); + + half3 diffuseLight1 = half3(0.5,0.5,0.5); + diffuseLight1 *= uniforms.envIntensity; + half3 specularLight1(0.5); + specularLight1 *= uniforms.envIntensity; + half3 iblDiffuse1 = diffuseLight1 * diffuseColor; + half3 iblSpecular1 = specularLight1;// * ((specularColor * brdf.x) + brdf.y); + half3 iblColor1 = iblDiffuse1 + iblSpecular1; + color += iblColor1; + color = baseColor.rgb * NdotV; + + + + + return half4(color, baseColor.a); + + + #if USE_IBL + constexpr sampler cubeSampler(coord::normalized, filter::linear, mip_filter::linear); + float mipCount = SPECULAR_ENV_MIP_LEVELS; + float lod = perceptualRoughness * (mipCount - 1); + half2 brdf = brdfLUT.sample(cubeSampler, float2(NdotV, perceptualRoughness)).xy; + half3 diffuseLight = diffuseEnvTexture.sample(cubeSampler, N).rgb; + diffuseLight *= uniforms.envIntensity; + + half3 specularLight(0); + if (mipCount > 1) { + specularLight = specularEnvTexture.sample(cubeSampler, reflection, level(lod)).rgb; + } else { + specularLight = specularEnvTexture.sample(cubeSampler, reflection).rgb; + } + specularLight *= uniforms.envIntensity; + + half3 iblDiffuse = diffuseLight * diffuseColor; + half3 iblSpecular = specularLight * ((specularColor * brdf.x) + brdf.y); + + half3 iblColor = iblDiffuse + iblSpecular; + + color += iblColor; + #endif + + + #if HAS_OCCLUSION_MAP + half ao = occlusionTexture.sample(occlusionSampler, occlusionTexCoord).r; + color = mix(color, color * ao, half(uniforms.occlusionStrength)); + #endif + + #if HAS_EMISSIVE_MAP + half3 emissive = emissiveTexture.sample(emissiveSampler, emissiveTexCoord).rgb; + color += emissive * half3(uniforms.emissiveFactor); + #else + color += half3(uniforms.emissiveFactor); + #endif + + #if USE_ALPHA_TEST + if (baseColor.a < uniforms.alphaCutoff) { + discard_fragment(); + } + #endif + + return half4(color, baseColor.a); +} From 7bfb3dfe962510493ccd2c72dfe0ee7e819415d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Fri, 13 Dec 2024 12:50:54 -0500 Subject: [PATCH 016/221] Updates --- platform/BUILD.bazel | 1 + platform/darwin/bazel/files.bzl | 1 + platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm | 2 +- platform/darwin/src/gltf/MetalRenderer.mm | 11 ++++++----- platform/ios/BUILD.bazel | 1 + 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/platform/BUILD.bazel b/platform/BUILD.bazel index c0225d4f0c7f..9d961d07115e 100644 --- a/platform/BUILD.bazel +++ b/platform/BUILD.bazel @@ -198,6 +198,7 @@ objc_library( objc_library( name = "ios-sdk", hdrs = [ + "//platform/darwin:darwin_gltf_hdrs", "//platform/darwin:darwin_objc_hdrs", "//platform/darwin:generated_style_public_hdrs", "//platform/ios:ios_sdk_hdrs", diff --git a/platform/darwin/bazel/files.bzl b/platform/darwin/bazel/files.bzl index fde648a6c853..f18243fceb4d 100644 --- a/platform/darwin/bazel/files.bzl +++ b/platform/darwin/bazel/files.bzl @@ -1,4 +1,5 @@ MLN_GLTF_HEADERS = [ + "src/gltf/GLTFModelLayer.h" ] MLN_GLTF_SOURCE = [ diff --git a/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm b/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm index 7524bf3a8e81..b32c097e14f2 100644 --- a/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm +++ b/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm @@ -187,7 +187,7 @@ // - auto modelTranslated = matrix_multiply(modelTilted, translationMatrix); + auto modelTranslated = matrix_multiply(translationMatrix, modelTilted); model->_modelMatrix = modelTranslated; diff --git a/platform/darwin/src/gltf/MetalRenderer.mm b/platform/darwin/src/gltf/MetalRenderer.mm index 9ca0e2563d86..38f1e1eb4797 100644 --- a/platform/darwin/src/gltf/MetalRenderer.mm +++ b/platform/darwin/src/gltf/MetalRenderer.mm @@ -99,8 +99,8 @@ float aspectRatio = (float)_drawableSize.x / (float)_drawableSize.y; simd_float4x4 aspectCorrection = GLTFMatrixFromScale((simd_float3){ 1 / aspectRatio, 1, 1 }); _projectionMatrix = simd_mul(aspectCorrection, _camera->projectionMatrix()); - - + + /* simd_float4x4 tempMatrix = _projectionMatrix; // Set the projection matrix from the incoming environment @@ -117,16 +117,17 @@ // double fov = 0.6435011087932844; // _projectionMatrix = GLTFPerspectiveProjectionMatrixAspectFovRH(fov, aspectRatio, 0.0001, 2); - + */ // The above projection matrix is a perspective matrix. I think we need an ortho matrix float w = ((float)_drawableSize.x) / 2.0; float h = ((float)_drawableSize.y) / 2.0; float aspect = w/h; - _projectionMatrix = GLTFOrthoProjectionMatrix(-w,w,-h*aspect,h*aspect,0.001,250); - _projectionMatrix = GLTFOrthoProjectionMatrix(-1*aspect,1*aspect,-1,1,10,-10); +// _projectionMatrix = GLTFOrthoProjectionMatrix(-w,w,-h*aspect,h*aspect,0.001,250); +// _projectionMatrix = GLTFOrthoProjectionMatrix(-1*aspect,1*aspect,-1,1,10,-10); + // ANother projection matrix test float fov = _renderingEnvironment->_currentFOVDEG * DEG_RAD; // 0.6435011087932844; // Constant that i found in ML simd_float4x4 matrix = GLTFPerspectiveProjectionMatrixAspectFovRH(fov, aspect, 0.01, 250); diff --git a/platform/ios/BUILD.bazel b/platform/ios/BUILD.bazel index a87208953e69..fbeb936482cc 100644 --- a/platform/ios/BUILD.bazel +++ b/platform/ios/BUILD.bazel @@ -85,6 +85,7 @@ info_plist( public_hdrs = [ ":ios_public_hdrs", ":ios_sdk_hdrs", + "//platform/darwin:darwin_gltf_hdrs", "//platform/darwin:darwin_objc_hdrs", "//platform/darwin:generated_style_public_hdrs", ] From 77ca6c2c136ad01f9ccee2088a2c4ccfc17c45ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sat, 14 Dec 2024 11:51:21 -0500 Subject: [PATCH 017/221] Updates for the projection matrix integration --- platform/darwin/src/gltf/Camera.cpp | 10 +- platform/darwin/src/gltf/Camera.hpp | 4 +- .../gltf/GLTFManagerRenderingEnvironment.hpp | 5 +- platform/darwin/src/gltf/GLTFMath.cpp | 73 ++++++-- platform/darwin/src/gltf/GLTFMath.hpp | 27 ++- platform/darwin/src/gltf/GLTFModelLayer.mm | 161 +++++++++--------- .../src/gltf/MetalRenderer+GLTFAsset.mm | 121 +++++++++++-- platform/darwin/src/gltf/MetalRenderer.hpp | 8 +- platform/darwin/src/gltf/MetalRenderer.mm | 51 +++++- 9 files changed, 335 insertions(+), 125 deletions(-) diff --git a/platform/darwin/src/gltf/Camera.cpp b/platform/darwin/src/gltf/Camera.cpp index e7b639152be5..d716830ac504 100644 --- a/platform/darwin/src/gltf/Camera.cpp +++ b/platform/darwin/src/gltf/Camera.cpp @@ -23,10 +23,10 @@ Camera::Camera() { } -simd_float4x4 Camera::projectionMatrix() { +simd_double4x4 Camera::projectionMatrix() { float fov = M_PI / 3; // original fov = 0.6435011087932844; // Constant that i found in ML - simd_float4x4 matrix = GLTFPerspectiveProjectionMatrixAspectFovRH(fov, 1.0, 0.01, 250); + simd_double4x4 matrix = GLTFPerspectiveProjectionMatrixAspectFovRH(fov, 1.0, 0.01, 250); return matrix; } @@ -53,9 +53,9 @@ void Camera::updateWithTimestep(double timestep) { // _distance += _velocity * timestep; _velocity *= GLTFViewerOrbitCameraZoomDrag; - simd_float4x4 pitchRotation = GLTFRotationMatrixFromAxisAngle(GLTFAxisX, -_rotationAngles.y); - simd_float4x4 yawRotation = GLTFRotationMatrixFromAxisAngle(GLTFAxisY, -_rotationAngles.x); - simd_float4x4 translation = GLTFMatrixFromTranslation((simd_float3){ 0, 0, _distance }); + simd_double4x4 pitchRotation = GLTFRotationMatrixFromAxisAngleD(GLTFAxisXD, -_rotationAngles.y); + simd_double4x4 yawRotation = GLTFRotationMatrixFromAxisAngleD(GLTFAxisYD, -_rotationAngles.x); + simd_double4x4 translation = GLTFMatrixFromTranslationD((simd_double3){ 0, 0, _distance }); _viewMatrix = matrix_invert(matrix_multiply(matrix_multiply(yawRotation, pitchRotation), translation)); diff --git a/platform/darwin/src/gltf/Camera.hpp b/platform/darwin/src/gltf/Camera.hpp index e364d1cee6da..05ebba2f6e84 100644 --- a/platform/darwin/src/gltf/Camera.hpp +++ b/platform/darwin/src/gltf/Camera.hpp @@ -20,8 +20,8 @@ class Camera { double _velocity; float _distance; Camera(); - simd_float4x4 projectionMatrix(); - simd_float4x4 _viewMatrix; + simd_double4x4 projectionMatrix(); + simd_double4x4 _viewMatrix; void updateWithTimestep(double timestep); }; diff --git a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp index a434745d5c18..3a8f73b12c05 100644 --- a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp +++ b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp @@ -23,7 +23,10 @@ namespace maplibre { namespace gltf { double _currentFOVDEG = 50; // Environment projection matrix - simd_float4x4 _currentProjectionMatrix; + simd_double4x4 _currentProjectionMatrix; + + // Current zoom level + double _currentZoomLevel = 1; }; diff --git a/platform/darwin/src/gltf/GLTFMath.cpp b/platform/darwin/src/gltf/GLTFMath.cpp index 29b56d65e53d..d7055a03601b 100644 --- a/platform/darwin/src/gltf/GLTFMath.cpp +++ b/platform/darwin/src/gltf/GLTFMath.cpp @@ -16,6 +16,15 @@ simd_float4x4 GLTFMatrixFromScale(const simd_float3 s) { return m; } +simd_double4x4 GLTFMatrixFromScaleD(const simd_double3 s) { + simd_double4x4 m = matrix_identity_double4x4; + m.columns[0].x = s.x; + m.columns[1].y = s.y; + m.columns[2].z = s.z; + return m; +} + + simd_float4x4 GLTFMatrixFromUniformScale(float s) { simd_float4x4 m = matrix_identity_float4x4; m.columns[0].x = s; @@ -24,6 +33,22 @@ simd_float4x4 GLTFMatrixFromUniformScale(float s) { return m; } +simd_double4x4 GLTFMatrixFromUniformScaleD(double s) { + simd_double4x4 m = matrix_identity_double4x4; + m.columns[0].x = s; + m.columns[1].y = s; + m.columns[2].z = s; + return m; +} + + +simd_double4x4 GLTFMatrixFromTranslationD(simd_double3 t) { + simd_double4x4 m = matrix_identity_double4x4; + m.columns[3] = (simd_double4) { t.x, t.y, t.z, 1.0 }; + return m; +} + + simd_float4x4 GLTFMatrixFromTranslation(simd_float3 t) { simd_float4x4 m = matrix_identity_float4x4; m.columns[3] = (simd_float4) { t.x, t.y, t.z, 1.0 }; @@ -32,13 +57,13 @@ simd_float4x4 GLTFMatrixFromTranslation(simd_float3 t) { GLTFBoundingSphere GLTFBoundingSphereFromBox(const GLTFBoundingBox b) { GLTFBoundingSphere s; - float midX = (b.maxPoint.x + b.minPoint.x) * 0.5; - float midY = (b.maxPoint.y + b.minPoint.y) * 0.5; - float midZ = (b.maxPoint.z + b.minPoint.z) * 0.5; + double midX = (b.maxPoint.x + b.minPoint.x) * 0.5; + double midY = (b.maxPoint.y + b.minPoint.y) * 0.5; + double midZ = (b.maxPoint.z + b.minPoint.z) * 0.5; - float r = sqrt(pow(b.maxPoint.x - midX, 2) + pow(b.maxPoint.y - midY, 2) + pow(b.maxPoint.z - midZ, 2)); + double r = sqrt(pow(b.maxPoint.x - midX, 2) + pow(b.maxPoint.y - midY, 2) + pow(b.maxPoint.z - midZ, 2)); - s.center = (simd_float3){ midX, midY, midZ }; + s.center = (simd_double3){ midX, midY, midZ }; s.radius = r; return s; } @@ -57,17 +82,36 @@ simd_float4x4 GLTFRotationMatrixFromAxisAngle(simd_float3 axis, float angle) { return (simd_float4x4){ c0, c1, c2, c3 }; } +simd_double4x4 GLTFRotationMatrixFromAxisAngleD(simd_double3 axis, double angle) { + double x = axis.x, y = axis.y, z = axis.z; + double c = cos(angle); + double s = sin(angle); + double t = 1 - c; + + simd_double4 c0 = { t * x * x + c, t * x * y + z * s, t * x * z - y * s, 0 }; + simd_double4 c1 = { t * x * y - z * s, t * y * y + c, t * y * z + x * s, 0 }; + simd_double4 c2 = { t * x * z + y * s, t * y * z - x * s, t * z * z + c, 0 }; + simd_double4 c3 = { 0, 0, 0, 1 }; + + return (simd_double4x4){ c0, c1, c2, c3 }; +} + + simd_float3 GLTFAxisX = (simd_float3){ 1, 0, 0 }; simd_float3 GLTFAxisY = (simd_float3){ 0, 1, 0 }; simd_float3 GLTFAxisZ = (simd_float3){ 0, 0, 1 }; -simd_float4x4 GLTFPerspectiveProjectionMatrixAspectFovRH(const float fovY, const float aspect, const float nearZ, const float farZ) +simd_double3 GLTFAxisXD = (simd_double3){ 1, 0, 0 }; +simd_double3 GLTFAxisYD = (simd_double3){ 0, 1, 0 }; +simd_double3 GLTFAxisZD = (simd_double3){ 0, 0, 1 }; + +simd_double4x4 GLTFPerspectiveProjectionMatrixAspectFovRH(const double fovY, const double aspect, const double nearZ, const double farZ) { - float yscale = 1 / tanf(fovY * 0.5f); // 1 / tan == cot - float xscale = yscale / aspect; - float q = -farZ / (farZ - nearZ); + double yscale = 1 / tanf(fovY * 0.5f); // 1 / tan == cot + double xscale = yscale / aspect; + double q = -farZ / (farZ - nearZ); - simd_float4x4 m = { + simd_double4x4 m = { .columns[0] = { xscale, 0, 0, 0 }, .columns[1] = { 0, yscale, 0, 0 }, .columns[2] = { 0, 0, q, -1 }, @@ -106,6 +150,15 @@ simd_float3x3 GLTFMatrixUpperLeft3x3(simd_float4x4 m) { return mout; } +simd_double3x3 GLTFMatrixUpperLeft3x3D(simd_double4x4 m) { + simd_double3x3 mout = { { + { m.columns[0][0], m.columns[0][1], m.columns[0][2] }, + { m.columns[1][0], m.columns[1][1], m.columns[1][2] }, + { m.columns[2][0], m.columns[2][1], m.columns[2][2] } + } }; + return mout; +} + GLTFTextureTransform GLTFTextureTransformMakeIdentity(void) { GLTFTextureTransform t = { diff --git a/platform/darwin/src/gltf/GLTFMath.hpp b/platform/darwin/src/gltf/GLTFMath.hpp index 0b8764c1c029..af29606989f6 100644 --- a/platform/darwin/src/gltf/GLTFMath.hpp +++ b/platform/darwin/src/gltf/GLTFMath.hpp @@ -22,8 +22,11 @@ typedef enum { GLTFTextureBindIndexBRDFLookup, } GLTFMTLTextureBindIndex; -#define DEG_RAD 0.0174533 -#define RAD_DEG 57.2958 +#define DEG_RAD (M_PI/180.0) +#define RAD_DEG (180.0/M_PI) + +// 0.0174533 +// 57.2958 #define GLTFMTLMaximumLightCount 3 #define GLTFMTLMaximumTextureCount (GLTFTextureBindIndexEmissive + 1) @@ -35,7 +38,7 @@ typedef struct { } GLTFBoundingBox; typedef struct { - simd_float3 center; + simd_double3 center; float radius; } GLTFBoundingSphere; @@ -84,17 +87,29 @@ extern simd_float3 GLTFAxisX; extern simd_float3 GLTFAxisY; extern simd_float3 GLTFAxisZ; +extern simd_double3 GLTFAxisXD; +extern simd_double3 GLTFAxisYD; +extern simd_double3 GLTFAxisZD; + simd_float4x4 GLTFMatrixFromScale(const simd_float3 s); +simd_double4x4 GLTFMatrixFromScaleD(const simd_double3 s); + simd_float4x4 GLTFMatrixFromUniformScale(float s); -GLTFBoundingSphere GLTFBoundingSphereFromBox(const GLTFBoundingBox b); +simd_double4x4 GLTFMatrixFromUniformScaleD(double s); + +GLTFBoundingSphere GLTFBoundingSphereFromBox(GLTFBoundingBox b); simd_float4x4 GLTFMatrixFromTranslation(simd_float3 t); +simd_double4x4 GLTFMatrixFromTranslationD(simd_double3 t); + simd_float4x4 GLTFRotationMatrixFromAxisAngle(simd_float3 axis, float angle); -simd_float4x4 GLTFPerspectiveProjectionMatrixAspectFovRH(const float fovY, const float aspect, const float nearZ, const float farZ); +simd_double4x4 GLTFRotationMatrixFromAxisAngleD(simd_double3 axis, double angle); + +simd_double4x4 GLTFPerspectiveProjectionMatrixAspectFovRH(const double fovY, const double aspect, const double nearZ, const double farZ); simd_float4x4 GLTFOrthoProjectionMatrix(const float left, const float right, @@ -105,6 +120,8 @@ simd_float4x4 GLTFOrthoProjectionMatrix(const float left, simd_float3x3 GLTFMatrixUpperLeft3x3(simd_float4x4 m); +simd_double3x3 GLTFMatrixUpperLeft3x3D(simd_double4x4 m); + GLTFTextureTransform GLTFTextureTransformMakeIdentity(void); GLTFTextureTransform GLTFTextureTransformMakeSRT(simd_float2 scale, float rotation, simd_float2 offset); diff --git a/platform/darwin/src/gltf/GLTFModelLayer.mm b/platform/darwin/src/gltf/GLTFModelLayer.mm index d9980d7a97ac..65765e460e9b 100644 --- a/platform/darwin/src/gltf/GLTFModelLayer.mm +++ b/platform/darwin/src/gltf/GLTFModelLayer.mm @@ -123,69 +123,6 @@ -(id)initWithIdentifier:(NSString *)identifier { } - (void)didMoveToMapView:(MLNMapView *)mapView { - MLNBackendResource resource = [mapView backendResource]; - - NSString *shaderSource = @ -" #include \n" -" using namespace metal;\n" -" typedef struct\n" -" {\n" -" vector_float2 position;\n" -" vector_float4 color;\n" -" } Vertex;\n" -" struct RasterizerData\n" -" {\n" -" float4 position [[position]];\n" -" float4 color;\n" -" };\n" -" vertex RasterizerData\n" -" vertexShader(uint vertexID [[vertex_id]],\n" -" constant Vertex *vertices [[buffer(0)]],\n" -" constant vector_uint2 *viewportSizePointer [[buffer(1)]])\n" -" {\n" -" RasterizerData out;\n" -" float2 pixelSpacePosition = vertices[vertexID].position.xy;\n" -" vector_float2 viewportSize = vector_float2(*viewportSizePointer);\n" -" out.position = vector_float4(0.0, 0.0, 0.0, 1.0);\n" -" out.position.xy = pixelSpacePosition / (viewportSize / 2.0);\n" -" out.color = vertices[vertexID].color;\n" -" return out;\n" -" }\n" -" fragment float4 fragmentShader(RasterizerData in [[stage_in]])\n" -" {\n" -" return in.color;\n" -" }\n"; - - - NSError *error = nil; - id _device = resource.device; - id library = [_device newLibraryWithSource:shaderSource options:nil error:&error]; - NSAssert(library, @"Error compiling shaders: %@", error); - id vertexFunction = [library newFunctionWithName:@"vertexShader"]; - id fragmentFunction = [library newFunctionWithName:@"fragmentShader"]; - - // Configure a pipeline descriptor that is used to create a pipeline state. - MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; - pipelineStateDescriptor.label = @"Simple Pipeline"; - pipelineStateDescriptor.vertexFunction = vertexFunction; - pipelineStateDescriptor.fragmentFunction = fragmentFunction; - pipelineStateDescriptor.colorAttachments[0].pixelFormat = resource.mtkView.colorPixelFormat; - pipelineStateDescriptor.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; - pipelineStateDescriptor.stencilAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; - - _pipelineState = [_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor - error:&error]; - NSAssert(_pipelineState, @"Failed to create pipeline state: %@", error); - - // Notice that we don't configure the stencilTest property, leaving stencil testing disabled - MTLDepthStencilDescriptor *depthStencilDescriptor = [[MTLDepthStencilDescriptor alloc] init]; - depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways; // Or another value as needed - depthStencilDescriptor.depthWriteEnabled = NO; - - _depthStencilStateWithoutStencil = [_device newDepthStencilStateWithDescriptor:depthStencilDescriptor]; - - - } @@ -290,43 +227,109 @@ - (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingCon tempResult._z = 0; + tempResult._x = 1000; + tempResult._y = 1000; + + tempResult._x = 1112; + tempResult._y = 1112; + + tempResult._x = 111319.49079327357; + tempResult._y = 111325.1428663851; + + tempResult._x = 1113194.9079327357; + tempResult._y = 1118889.9748579594; + + + tempResult._x = 5198170.102753558; + tempResult._y = 2832006.4886368043; + + + + tempResult._x = coordinate._lon * DEG_RAD; + double lat = coordinate._lat * DEG_RAD; +// if (lat < -PoleLimit) lat = -PoleLimit; +// if (lat > PoleLimit) lat = PoleLimit; + tempResult._y = log((1.0f+sin(lat))/cos(lat)); + + double metersScale = 20037508.34; + tempResult._x = tempResult._x * metersScale / M_PI; + tempResult._y = tempResult._y * metersScale / M_PI; + return tempResult; + + + /* + Point3d SphericalMercatorCoordSystem::geographicToLocal3d(const GeoCoord &geo) const + { + Point3d coord; + coord.x() = geo.lon() - originLon; + double lat = geo.lat(); + if (lat < -PoleLimit) lat = -PoleLimit; + if (lat > PoleLimit) lat = PoleLimit; + coord.y() = log((1.0f+sin(lat))/cos(lat)); + coord.z() = 0.0; + + return coord; + } + */ + + + + /* + + + MLNMapProjection *proj = mapView.mapProjection; CGPoint p = [proj convertCoordinate:CLLocationCoordinate2DMake(coordinate._lat, coordinate._lon)]; + //NSLog(@"ZOOM LEVEL: %f",mapView.zoomLevel); //NSLog(@"Meters Per Pixel: %f",proj.metersPerPoint); // The 2.0 is point to pixel scaling - double viewportSizeX = resource.mtkView.drawableSize.width / 2.0; - double viewportSizeY = resource.mtkView.drawableSize.height / 2.0; + double viewportSizeXPoints = resource.mtkView.drawableSize.width / 2.0; + double viewportSizeYPoints = resource.mtkView.drawableSize.height / 2.0; - double halfX = (viewportSizeX / 2.0); - double halfY = (viewportSizeY / 2.0); + double halfX = (viewportSizeXPoints / 2.0); + double halfY = (viewportSizeYPoints / 2.0); double offsetX = p.x - halfX; - double projX = offsetX / viewportSizeX; - double projY = (viewportSizeY - p.y - halfY) / viewportSizeY; + double projX = offsetX / viewportSizeXPoints; + double projY = (viewportSizeYPoints - p.y - halfY) / viewportSizeYPoints; + + double aspect = viewportSizeXPoints / viewportSizeYPoints; + + tempResult._x = projX * 4.0 * aspect; + tempResult._y = projY * 4.0; + + + double x = p.x / viewportSizeXPoints; + double y = p.y / viewportSizeYPoints; + + x = (x * 2) - 1; + y = (y * 2) - 1; + y = -y; + tempResult._x = x; + tempResult._y = y; - double aspect = viewportSizeX / viewportSizeY; - tempResult._x = projX * 2.0 * aspect; - tempResult._y = projY * 2.0; - tempResult._x = projX; - tempResult._y = projY; +// tempResult._x = projX; +// tempResult._y = projY; - NSLog(@"P: %f, %f -> %f, %f", p.x, p.y, projX, projY); + NSLog(@"P: %f, %f -> %f, %f", p.x, p.y, x, y); // projX, projY, x, y); return tempResult; + */ }); loadModels = true; } _metalEnvironment->_currentFOVDEG = context.fieldOfView * RAD_DEG; - _metalEnvironment->_currentProjectionMatrix = toSimdMatrix4F(context.projectionMatrix); + _metalEnvironment->_currentProjectionMatrix = toSimdMatrix4D(context.projectionMatrix); + _metalEnvironment->_currentZoomLevel = context.zoomLevel; _metalEnvironment->_currentCommandEncoder = self.renderEncoder; _metalEnvironment->_currentCommandBuffer = resource.commandBuffer; _metalEnvironment->_metalDevice = resource.mtkView.device; @@ -359,10 +362,10 @@ - (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingCon // Render the image _manager->render(); - + /* return; - #if TEST + @@ -406,7 +409,7 @@ - (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingCon vertexStart:0 vertexCount:3]; } - #endif + */ } diff --git a/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm b/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm index b32c097e14f2..c16c4f4c7537 100644 --- a/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm +++ b/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm @@ -84,8 +84,8 @@ GLTFBoundingSphere bounds = GLTFBoundingSphereFromBox(model->_asset.defaultScene.approximateBounds); model->_boundingSphere = bounds; float scale = (bounds.radius > 0) ? (1 / (bounds.radius)) : 1; - simd_float4x4 centerScale = GLTFMatrixFromUniformScale(scale); - simd_float4x4 centerTranslation = GLTFMatrixFromTranslation(-bounds.center); + simd_double4x4 centerScale = GLTFMatrixFromUniformScaleD(scale); + simd_double4x4 centerTranslation = GLTFMatrixFromTranslationD(-bounds.center); // This regularization matrix centers the model model->_regularizationMatrix = matrix_multiply(centerScale, centerTranslation); @@ -97,9 +97,46 @@ } void MetalRenderer::computeTransforms(std::shared_ptr model) { - // New stuff + auto mdlMatrix = matrix_identity_double4x4; + + // Rotation + auto modelRotation = GLTFRotationMatrixFromAxisAngleD(GLTFAxisYD, (model->_gltfModel->_rotationDeg) * DEG_RAD); + auto modelRotated = matrix_multiply(modelRotation, mdlMatrix); + + // Tilt + // auto modelEnvironmentTilt = GLTFRotationMatrixFromAxisAngle(GLTFAxisX, _tiltDeg * DEG_RAD); +// auto modelTilt = GLTFRotationMatrixFromAxisAngle(GLTFAxisX, -90 * DEG_RAD); +// auto modelTilted = matrix_multiply(modelTilt, modelRotated); + + //auto modelTilted = matrix_identity_float4x4; + + auto modelTilted = GLTFRotationMatrixFromAxisAngleD(GLTFAxisXD, 90 * DEG_RAD); + modelTilted = matrix_multiply(modelTilted, modelRotation); + +// auto modelTilted = matrix_multiply(modelEnvironmentTilt, modelRotated); + + simd_double3 xlateVector = simd_make_double3(model->_gltfModel->_xLateX, + model->_gltfModel->_xLateY, + model->_gltfModel->_xLateZ); + + auto xLateMatrix = GLTFMatrixFromTranslationD(xlateVector); + + + // + auto modelTranslated = matrix_multiply(xLateMatrix, modelTilted); + + model->_modelMatrix = modelTranslated; + + model->_modelViewMatrix = matrix_multiply(_camera->_viewMatrix, + modelTranslated); + + model->_modelViewMatrix = modelTranslated; // matrix_multiply(_camera->_viewMatrix, + //modelTranslated); + + + return; @@ -135,12 +172,15 @@ model->_viewMatrix = matrix_multiply(modelMatrix2, _camera->_viewMatrix); */ + + + /* This is what was working with Steve + // Compute the model matrix: This was the original model->_modelViewMatrix = matrix_multiply(_camera->_viewMatrix, model->_regularizationMatrix); // New news - #if TEST static float rot = 0; rot += 0.01; static float xLate = 0; @@ -153,7 +193,6 @@ } rot = 0; xLate = 0; - #endif simd_float3 translatedVector = simd_make_float3(model->_gltfModel->_xLateX, model->_gltfModel->_xLateY, @@ -173,18 +212,27 @@ modelMatrix = matrix_multiply(scaleMatrix, modelMatrix); // Rotation - auto modelEnvironmentRotation = GLTFRotationMatrixFromAxisAngle(GLTFAxisY, (model->_gltfModel->_rotationDeg -_rotationDeg) * DEG_RAD); + auto modelEnvironmentRotation = GLTFRotationMatrixFromAxisAngle(GLTFAxisY, (model->_gltfModel->_rotationDeg) * DEG_RAD); auto modelRotated = matrix_multiply(modelEnvironmentRotation, modelMatrix); // Tilt - auto modelEnvironmentTilt = GLTFRotationMatrixFromAxisAngle(GLTFAxisX, _tiltDeg * DEG_RAD); + // auto modelEnvironmentTilt = GLTFRotationMatrixFromAxisAngle(GLTFAxisX, _tiltDeg * DEG_RAD); + auto modelEnvironmentTilt = GLTFRotationMatrixFromAxisAngle(GLTFAxisX, -90 * DEG_RAD); auto modelTilted = matrix_multiply(modelEnvironmentTilt, modelRotated); // This was just debug stuff to rotate in the scene // auto modelRotation = GLTFRotationMatrixFromAxisAngle(GLTFAxisY, -rot); // auto modelRotation2 = matrix_multiply(modelRotation, modelMatrix); // + + + modelTilted = matrix_identity_float4x4; + modelTilted = GLTFRotationMatrixFromAxisAngle(GLTFAxisX, 90 * DEG_RAD); + modelTilted = matrix_multiply(modelTilted, modelEnvironmentRotation); + +// auto modelTilted = matrix_multiply(modelEnvironmentTilt, modelRotated); + // auto modelTranslated = matrix_multiply(translationMatrix, modelTilted); @@ -194,8 +242,12 @@ model->_modelViewMatrix = matrix_multiply(_camera->_viewMatrix, modelTranslated); + model->_modelViewMatrix = modelTranslated; // matrix_multiply(_camera->_viewMatrix, + //modelTranslated); + + */ @@ -261,6 +313,39 @@ } } +simd_float4x4 matrix_double_to_float(simd_double4x4 input) { + simd_float4x4 tempResult; + tempResult.columns[0][0] = input.columns[0][0]; + tempResult.columns[0][1] = input.columns[0][1]; + tempResult.columns[0][2] = input.columns[0][2]; + tempResult.columns[0][3] = input.columns[0][3]; + + tempResult.columns[1][0] = input.columns[1][0]; + tempResult.columns[1][1] = input.columns[1][1]; + tempResult.columns[1][2] = input.columns[1][2]; + tempResult.columns[1][3] = input.columns[1][3]; + + tempResult.columns[2][0] = input.columns[2][0]; + tempResult.columns[2][1] = input.columns[2][1]; + tempResult.columns[2][2] = input.columns[2][2]; + tempResult.columns[2][3] = input.columns[2][3]; + + tempResult.columns[3][0] = input.columns[3][0]; + tempResult.columns[3][1] = input.columns[3][1]; + tempResult.columns[3][2] = input.columns[3][2]; + tempResult.columns[3][3] = input.columns[3][3]; + + return tempResult; +} + +simd_float3 double3_to_float3(simd_double3 input) { + simd_float3 tempResult; + tempResult.x = input.x; + tempResult.y = input.y; + tempResult.z = input.z; + return tempResult; + +} void MetalRenderer::buildRenderListRecursive(std::shared_ptr model, GLTFNode *node, @@ -273,14 +358,24 @@ for (GLTFSubmesh *submesh in mesh.submeshes) { GLTFMaterial *material = submesh.material; - simd_float3x3 viewAffine = simd_inverse(GLTFMatrixUpperLeft3x3(model->_modelViewMatrix)); - simd_float3 cameraPos = model->_modelViewMatrix.columns[3].xyz; - simd_float3 cameraWorldPos = matrix_multiply(viewAffine, -cameraPos); - + simd_double3x3 viewAffine = simd_inverse(GLTFMatrixUpperLeft3x3D(model->_modelViewMatrix)); + simd_double3 cameraPos = model->_modelViewMatrix.columns[3].xyz; + simd_double3 cameraWorldPos = matrix_multiply(viewAffine, -cameraPos); + simd_float3 cameraWorldPosF = double3_to_float3(cameraWorldPos); + VertexUniforms vertexUniforms; vertexUniforms.modelMatrix = modelMatrix; - vertexUniforms.modelViewProjectionMatrix = matrix_multiply(matrix_multiply(_projectionMatrix, model->_modelViewMatrix), modelMatrix); +// vertexUniforms.modelViewProjectionMatrix = mvpF; vertexUniforms.normalMatrix = GLTFNormalMatrixFromModelMatrix(modelMatrix); + + // TODO: MT: Review this.. + auto mvp = matrix_multiply(_projectionMatrix, model->_modelViewMatrix); + auto mvpF = matrix_double_to_float(mvp); + vertexUniforms.modelViewProjectionMatrix = mvpF; + + + + FragmentUniforms fragmentUniforms = { 0 }; fragmentUniforms.normalScale = material.normalTextureScale; @@ -288,7 +383,7 @@ fragmentUniforms.occlusionStrength = material.occlusionStrength; fragmentUniforms.metallicRoughnessValues = (simd_float2){ material.metalnessFactor, material.roughnessFactor }; fragmentUniforms.baseColorFactor = material.baseColorFactor; - fragmentUniforms.camera = cameraWorldPos; + fragmentUniforms.camera = cameraWorldPosF; fragmentUniforms.alphaCutoff = material.alphaCutoff; fragmentUniforms.envIntensity = 2; // self.lightingEnvironment.intensity; diff --git a/platform/darwin/src/gltf/MetalRenderer.hpp b/platform/darwin/src/gltf/MetalRenderer.hpp index 25aeeb160a39..228b6a660b84 100644 --- a/platform/darwin/src/gltf/MetalRenderer.hpp +++ b/platform/darwin/src/gltf/MetalRenderer.hpp @@ -39,14 +39,14 @@ namespace maplibre { namespace gltf { double _scaling = 1; // Scaling from // This is the model matrix (rotation, scaling and transformation applied) - simd_float4x4 _modelMatrix; + simd_double4x4 _modelMatrix; // This is the model matrix combined with the camera's view matrix - simd_float4x4 _modelViewMatrix; + simd_double4x4 _modelViewMatrix; // We probably won't need this in the final thing. Used to normalize the model to the // viewport size - simd_float4x4 _regularizationMatrix; + simd_double4x4 _regularizationMatrix; // GLTFBoundingSphere _boundingSphere; @@ -87,7 +87,7 @@ namespace maplibre { namespace gltf { private: // Rendering environment variables - simd_float4x4 _projectionMatrix; + simd_double4x4 _projectionMatrix; int _sampleCount = 1; MTLPixelFormat _colorPixelFormat; MTLPixelFormat _depthStencilPixelFormat; diff --git a/platform/darwin/src/gltf/MetalRenderer.mm b/platform/darwin/src/gltf/MetalRenderer.mm index 38f1e1eb4797..47d9beb95f45 100644 --- a/platform/darwin/src/gltf/MetalRenderer.mm +++ b/platform/darwin/src/gltf/MetalRenderer.mm @@ -97,9 +97,9 @@ // Compute the projection matrix float aspectRatio = (float)_drawableSize.x / (float)_drawableSize.y; - simd_float4x4 aspectCorrection = GLTFMatrixFromScale((simd_float3){ 1 / aspectRatio, 1, 1 }); + simd_double4x4 aspectCorrection = GLTFMatrixFromScaleD((simd_double3){ 1 / aspectRatio, 1, 1 }); _projectionMatrix = simd_mul(aspectCorrection, _camera->projectionMatrix()); - + /* simd_float4x4 tempMatrix = _projectionMatrix; @@ -119,22 +119,61 @@ */ + /* Stuff with Steve + auto environmentMVP = _metalRenderingEnvironment->_currentProjectionMatrix; + double tileSize = 256.0; + double zoom = _metalRenderingEnvironment->_currentZoomLevel; + double scaleFactor = (20037508.34); // M_PI + double worldSize = tileSize / scaleFactor * pow(2.0,zoom); + simd_float4x4 scaleMatrix = GLTFMatrixFromScale(simd_make_float3(worldSize, -worldSize, 1.0)); + simd_float4x4 xlateMatrix = GLTFMatrixFromTranslation(simd_make_float3(20037508.34,-20037508.34,0.0)); + + auto m1 = matrix_multiply(scaleMatrix, xlateMatrix); + auto m2 = matrix_multiply(environmentMVP, m1); + _projectionMatrix = m2; + */ + + + auto environmentMVP = _metalRenderingEnvironment->_currentProjectionMatrix; + double tileSize = 256.0; + double zoom = _metalRenderingEnvironment->_currentZoomLevel; + double scaleFactor = (20037508.34); // M_PI + double worldSize = tileSize / scaleFactor * pow(2.0,zoom); + simd_double4x4 scaleMatrix = GLTFMatrixFromScaleD(simd_make_double3(worldSize, -worldSize, 1.0)); + simd_double4x4 xlateMatrix = GLTFMatrixFromTranslationD(simd_make_double3(20037508.34,-20037508.34,0.0)); + + auto m1 = matrix_multiply(scaleMatrix, xlateMatrix); + auto m2 = matrix_multiply(environmentMVP, m1); + _projectionMatrix = m2; + + + + + // Apply a scale to our data first + // Note: Can see something with this +// const Eigen::Affine3d scaleTrans(Eigen::Scaling(worldSize,-worldSize,1.0)); +// const Eigen::Affine3d transTrans(Eigen::Translation3d(20037508.34,-20037508.34,0.0)); +// Eigen::Matrix4d mvp = (inMvp * (scaleTrans * transTrans) ).matrix(); +// + + /* + + // The above projection matrix is a perspective matrix. I think we need an ortho matrix float w = ((float)_drawableSize.x) / 2.0; float h = ((float)_drawableSize.y) / 2.0; float aspect = w/h; // _projectionMatrix = GLTFOrthoProjectionMatrix(-w,w,-h*aspect,h*aspect,0.001,250); -// _projectionMatrix = GLTFOrthoProjectionMatrix(-1*aspect,1*aspect,-1,1,10,-10); + _projectionMatrix = GLTFOrthoProjectionMatrix(-1*aspect,1*aspect,-1,1,10,-10); - // ANother projection matrix test float fov = _renderingEnvironment->_currentFOVDEG * DEG_RAD; // 0.6435011087932844; // Constant that i found in ML simd_float4x4 matrix = GLTFPerspectiveProjectionMatrixAspectFovRH(fov, aspect, 0.01, 250); _projectionMatrix = matrix; - + */ @@ -364,7 +403,7 @@ _metalLibrary = [_metalDevice newDefaultLibrary]; //_viewMatrix = matrix_identity_float4x4; - _projectionMatrix = matrix_identity_float4x4; + _projectionMatrix = matrix_identity_double4x4; _colorPixelFormat = MTLPixelFormatBGRA8Unorm; _depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8; _sampleCount = 1; From 8410f29730f801df1dc092212c59841d1a5d69a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sun, 15 Dec 2024 14:11:46 -0500 Subject: [PATCH 018/221] Updates to lighting a bit --- platform/darwin/src/gltf/GLTFMath.cpp | 11 +++++++++++ platform/darwin/src/gltf/GLTFMath.hpp | 2 ++ platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm | 2 ++ 3 files changed, 15 insertions(+) diff --git a/platform/darwin/src/gltf/GLTFMath.cpp b/platform/darwin/src/gltf/GLTFMath.cpp index d7055a03601b..97f5821e9035 100644 --- a/platform/darwin/src/gltf/GLTFMath.cpp +++ b/platform/darwin/src/gltf/GLTFMath.cpp @@ -202,3 +202,14 @@ simd_float4x4 GLTFNormalMatrixFromModelMatrix(simd_float4x4 m) { } }; return mout; } + +simd_double4x4 GLTFNormalMatrixFromModelMatrixD(simd_double4x4 m) { + simd_double3x3 nm = simd_inverse(simd_transpose(GLTFMatrixUpperLeft3x3D(m))); + simd_double4x4 mout = { { + { nm.columns[0][0], nm.columns[0][1], nm.columns[0][2], 0 }, + { nm.columns[1][0], nm.columns[1][1], nm.columns[1][2], 0 }, + { nm.columns[2][0], nm.columns[2][1], nm.columns[2][2], 0 }, + { 0, 0, 0, 1 } + } }; + return mout; +} diff --git a/platform/darwin/src/gltf/GLTFMath.hpp b/platform/darwin/src/gltf/GLTFMath.hpp index af29606989f6..288217479559 100644 --- a/platform/darwin/src/gltf/GLTFMath.hpp +++ b/platform/darwin/src/gltf/GLTFMath.hpp @@ -130,6 +130,8 @@ simd_float3x3 GLTFTextureMatrixFromTransform(GLTFTextureTransform transform); simd_float4x4 GLTFNormalMatrixFromModelMatrix(simd_float4x4 m); +simd_double4x4 GLTFNormalMatrixFromModelMatrixD(simd_double4x4 m); + #ifdef __cplusplus } diff --git a/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm b/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm index c16c4f4c7537..5695f386a394 100644 --- a/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm +++ b/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm @@ -372,6 +372,8 @@ simd_float3 double3_to_float3(simd_double3 input) { auto mvp = matrix_multiply(_projectionMatrix, model->_modelViewMatrix); auto mvpF = matrix_double_to_float(mvp); vertexUniforms.modelViewProjectionMatrix = mvpF; + auto normalMatrix = GLTFNormalMatrixFromModelMatrixD( model->_modelViewMatrix); + vertexUniforms.normalMatrix = matrix_double_to_float(normalMatrix); From 64e63523a0ceeb66c27455a412b2fc62569dc542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Tue, 14 Jan 2025 14:24:17 -0500 Subject: [PATCH 019/221] Updates for lighting and support for JSON model loading --- .../gltf/GLTFManagerRenderingEnvironment.hpp | 3 + platform/darwin/src/gltf/GLTFMath.hpp | 3 + platform/darwin/src/gltf/GLTFModel.hpp | 3 + platform/darwin/src/gltf/GLTFModelLayer.h | 6 +- platform/darwin/src/gltf/GLTFModelLayer.mm | 61 +++++++++++++++++-- .../src/gltf/MetalRenderer+GLTFAsset.mm | 8 ++- platform/darwin/src/gltf/MetalRenderer.hpp | 3 +- 7 files changed, 80 insertions(+), 7 deletions(-) diff --git a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp index 3a8f73b12c05..f6059e166df9 100644 --- a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp +++ b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp @@ -28,6 +28,9 @@ namespace maplibre { namespace gltf { // Current zoom level double _currentZoomLevel = 1; + // + simd_float3 _lightDirection; + }; }} diff --git a/platform/darwin/src/gltf/GLTFMath.hpp b/platform/darwin/src/gltf/GLTFMath.hpp index 288217479559..eae5a828c560 100644 --- a/platform/darwin/src/gltf/GLTFMath.hpp +++ b/platform/darwin/src/gltf/GLTFMath.hpp @@ -47,6 +47,9 @@ typedef struct { simd_float4x4 modelMatrix; simd_float4x4 modelViewProjectionMatrix; simd_float4x4 normalMatrix; + float scaleFactor; + float brightness; + simd_float3 lightDirection; } VertexUniforms; typedef struct { diff --git a/platform/darwin/src/gltf/GLTFModel.hpp b/platform/darwin/src/gltf/GLTFModel.hpp index 0158e5d8ccdd..a09e05b56e5b 100644 --- a/platform/darwin/src/gltf/GLTFModel.hpp +++ b/platform/darwin/src/gltf/GLTFModel.hpp @@ -29,6 +29,9 @@ namespace maplibre { namespace gltf { // The URL for the model, used by the loader std::string _modelURL; + // The brightness + float _brightness = 1.0; + // This is a hack to deal with passing in the translation vector. // NEed to reconcile this with the renderable model's version of it double _xLateX = 0; diff --git a/platform/darwin/src/gltf/GLTFModelLayer.h b/platform/darwin/src/gltf/GLTFModelLayer.h index ab22715c4a9f..15cbbbde2a23 100644 --- a/platform/darwin/src/gltf/GLTFModelLayer.h +++ b/platform/darwin/src/gltf/GLTFModelLayer.h @@ -11,10 +11,14 @@ NS_ASSUME_NONNULL_BEGIN @interface GLTFModelLayer : MLNCustomStyleLayer +-(void)loadModelFromJSON:(NSString *)modelMetadataFilename; + -(void)loadModel:(NSString *)appResourceFilename lat:(double)lat lon:(double)lon - rotationDeg:(double)rotationDeg; + rotationDeg:(double)rotationDeg + scaleFactor:(float)scaleFactor + brightness:(float)brightness; @end diff --git a/platform/darwin/src/gltf/GLTFModelLayer.mm b/platform/darwin/src/gltf/GLTFModelLayer.mm index 65765e460e9b..09d78674550c 100644 --- a/platform/darwin/src/gltf/GLTFModelLayer.mm +++ b/platform/darwin/src/gltf/GLTFModelLayer.mm @@ -24,9 +24,18 @@ @interface GLTFModelMetadata : NSObject @property CLLocationCoordinate2D modelCoordinate; @property double modelRotation; @property BOOL modelLoaded; +@property float modelScale; +@property float brightness; + @end @implementation GLTFModelMetadata +-(id)init { + if (self = [super init]) { + self.brightness = 1.0; + } + return self; +} @end @interface GLTFModelLayer () { @@ -162,15 +171,55 @@ -(void)loadModels { } +-(void)loadModelFromJSON:(NSString *)modelMetadataFilename { + + NSError *error = nil; + NSData *dat = [NSData dataWithContentsOfFile:modelMetadataFilename]; + NSDictionary *d = [NSJSONSerialization JSONObjectWithData:dat + options:0 + error:&error]; + NSArray *models = [d objectForKey:@"models"]; + for (NSDictionary *model in models) { + + NSString *modelFilename = [model objectForKey:@"name"]; + double lat = [[model objectForKey:@"lat"] doubleValue]; + double lon = [[model objectForKey:@"lon"] doubleValue]; + double rot = [[model objectForKey:@"rot"] doubleValue]; + double scale = [[model objectForKey:@"scale_factor"] doubleValue]; + double brightnessCoefficient = [[model objectForKey:@"brightness"] doubleValue]; + if (brightnessCoefficient == 0) { + brightnessCoefficient = 1.0; + } + //NSString *bundleFilename = [[NSBundle mainBundle] pathForResource:modelFilename ofType:nil]; + [self loadModel:modelFilename + lat:lat + lon:lon + rotationDeg:rot + scaleFactor:scale + brightness:brightnessCoefficient]; + } + +} + + -(void)loadModel:(NSString *)appResourceFilename lat:(double)lat lon:(double)lon - rotationDeg:(double)rotationDeg { + rotationDeg:(double)rotationDeg + scaleFactor:(float)scaleFactor + brightness:(float)brightness { + + if (brightness == 0) { + brightness = 1.0; + } GLTFModelMetadata *modelMetadata = [[GLTFModelMetadata alloc] init]; modelMetadata.modelPath = appResourceFilename; modelMetadata.modelCoordinate = CLLocationCoordinate2DMake(lat, lon); - modelMetadata.modelRotation = rotationDeg; + modelMetadata.modelRotation = -rotationDeg; + modelMetadata.modelScale = scaleFactor; + modelMetadata.brightness = brightness; + [self.models addObject:modelMetadata]; if (self.managerCreated) { @@ -180,6 +229,7 @@ -(void)loadModel:(NSString *)appResourceFilename } + -(void)addModel:(GLTFModelMetadata *)modelMetadata { if (modelMetadata.modelLoaded) { @@ -195,7 +245,9 @@ -(void)addModel:(GLTFModelMetadata *)modelMetadata { model->_referenceLon = modelMetadata.modelCoordinate.longitude; model->_modelURL = modelURL; model->_rotationDeg = modelMetadata.modelRotation; - model->_scaleFactor = 1.0; // Models are in meters + model->_brightness = modelMetadata.brightness; + model->_scaleFactor = modelMetadata.modelScale; +// model->_scaleFactor = 1.0; // Models are in meters _manager->addModel(model); @@ -335,7 +387,8 @@ - (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingCon _metalEnvironment->_metalDevice = resource.mtkView.device; _metalEnvironment->_currentDrawable = resource.mtkView.currentDrawable; _metalEnvironment->_currentRenderPassDescriptor = resource.mtkView.currentRenderPassDescriptor; - + _metalEnvironment->_lightDirection = simd_make_float3(000.0, 10000.0, 10000.0); + // TODO: Remove this.. This is legacy _manager->setRenderingEnvironmentVariables(_metalEnvironment); diff --git a/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm b/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm index 5695f386a394..e3537787de61 100644 --- a/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm +++ b/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm @@ -53,7 +53,9 @@ std::shared_ptr tempResult = std::make_shared(); tempResult->_asset = asset; tempResult->_gltfModel = model; - + tempResult->_scaling = model->_scaleFactor; + tempResult->_brightness = model->_brightness; + computeRegularizationMatrix(tempResult); computeTransforms(tempResult); addDefaultLights(tempResult); @@ -375,6 +377,10 @@ simd_float3 double3_to_float3(simd_double3 input) { auto normalMatrix = GLTFNormalMatrixFromModelMatrixD( model->_modelViewMatrix); vertexUniforms.normalMatrix = matrix_double_to_float(normalMatrix); + vertexUniforms.scaleFactor = model->_scaling; + vertexUniforms.brightness = model->_brightness; + vertexUniforms.lightDirection = _renderingEnvironment->_lightDirection; + diff --git a/platform/darwin/src/gltf/MetalRenderer.hpp b/platform/darwin/src/gltf/MetalRenderer.hpp index 228b6a660b84..1e90c154fc8b 100644 --- a/platform/darwin/src/gltf/MetalRenderer.hpp +++ b/platform/darwin/src/gltf/MetalRenderer.hpp @@ -37,7 +37,8 @@ namespace maplibre { namespace gltf { simd_float3 _translationVector; // This might need to be a doubles vector double _rotationDeg = 0; // Rotation around the zAxis (if applicable) double _scaling = 1; // Scaling from - + float _brightness = 1.0; // Brightness + // This is the model matrix (rotation, scaling and transformation applied) simd_double4x4 _modelMatrix; From 53639af64cccc3ae6022abd0c097e6c606ef1cdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Thu, 16 Jan 2025 10:04:26 -0500 Subject: [PATCH 020/221] Added ability to set light position on the model layer and some cleanup --- .../gltf/GLTFManagerRenderingEnvironment.hpp | 4 + platform/darwin/src/gltf/GLTFModelLayer.h | 4 + platform/darwin/src/gltf/GLTFModelLayer.mm | 167 +++--------------- 3 files changed, 37 insertions(+), 138 deletions(-) diff --git a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp index f6059e166df9..0be4b4046486 100644 --- a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp +++ b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp @@ -31,6 +31,10 @@ namespace maplibre { namespace gltf { // simd_float3 _lightDirection; + GLTFManagerRenderingEnvironment() { + _lightDirection = simd_make_float3(0.0, 10000.0, 10000.0); + } + }; }} diff --git a/platform/darwin/src/gltf/GLTFModelLayer.h b/platform/darwin/src/gltf/GLTFModelLayer.h index 15cbbbde2a23..d9715474eb86 100644 --- a/platform/darwin/src/gltf/GLTFModelLayer.h +++ b/platform/darwin/src/gltf/GLTFModelLayer.h @@ -11,6 +11,10 @@ NS_ASSUME_NONNULL_BEGIN @interface GLTFModelLayer : MLNCustomStyleLayer +// This sets the relative light position for all the models being rendered +// The light position is in meters from the origin of the model. +-(void)setLightPositionX:(float)x y:(float)y z:(float)z; + -(void)loadModelFromJSON:(NSString *)modelMetadataFilename; -(void)loadModel:(NSString *)appResourceFilename diff --git a/platform/darwin/src/gltf/GLTFModelLayer.mm b/platform/darwin/src/gltf/GLTFModelLayer.mm index 09d78674550c..51b3b59d3ded 100644 --- a/platform/darwin/src/gltf/GLTFModelLayer.mm +++ b/platform/darwin/src/gltf/GLTFModelLayer.mm @@ -47,6 +47,12 @@ @interface GLTFModelLayer () { @property NSMutableArray *models; @property BOOL managerCreated; +// Would be nice to change this to a vec3 or something similar at some point +@property BOOL lightSet; +@property float lightX; +@property float lightY; +@property float lightZ; + @end @@ -135,6 +141,22 @@ - (void)didMoveToMapView:(MLNMapView *)mapView { } +// This sets the relative light position for all the models being rendered +// The light position is in meters from the origin of the model. +-(void)setLightPositionX:(float)x y:(float)y z:(float)z { + + self.lightSet = YES; + self.lightX = x; + self.lightY = y; + self.lightZ = z; + + if (_metalEnvironment != nullptr) { + _metalEnvironment->_lightDirection = simd_make_float3(_lightX, _lightY, _lightZ); + } + +} + + -(void)loadModels { // This goes through the model array and loads whatever hasn't been loaded already @@ -267,6 +289,10 @@ - (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingCon // Setup the metal environment for the model rendering _metalEnvironment = std::make_shared(); + if (self.lightSet) { + _metalEnvironment->_lightDirection = simd_make_float3(_lightX, _lightY, _lightZ); + } + // Create the GLTF Manager _manager = std::make_shared(RenderingEnvironmentMetal); _manager->setRenderingEnvironmentVariables(_metalEnvironment); @@ -278,25 +304,6 @@ - (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingCon tempResult._y = 0; tempResult._z = 0; - - tempResult._x = 1000; - tempResult._y = 1000; - - tempResult._x = 1112; - tempResult._y = 1112; - - tempResult._x = 111319.49079327357; - tempResult._y = 111325.1428663851; - - tempResult._x = 1113194.9079327357; - tempResult._y = 1118889.9748579594; - - - tempResult._x = 5198170.102753558; - tempResult._y = 2832006.4886368043; - - - tempResult._x = coordinate._lon * DEG_RAD; double lat = coordinate._lat * DEG_RAD; // if (lat < -PoleLimit) lat = -PoleLimit; @@ -308,72 +315,6 @@ - (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingCon tempResult._y = tempResult._y * metersScale / M_PI; return tempResult; - - /* - Point3d SphericalMercatorCoordSystem::geographicToLocal3d(const GeoCoord &geo) const - { - Point3d coord; - coord.x() = geo.lon() - originLon; - double lat = geo.lat(); - if (lat < -PoleLimit) lat = -PoleLimit; - if (lat > PoleLimit) lat = PoleLimit; - coord.y() = log((1.0f+sin(lat))/cos(lat)); - coord.z() = 0.0; - - return coord; - } - */ - - - - /* - - - - MLNMapProjection *proj = mapView.mapProjection; - CGPoint p = [proj convertCoordinate:CLLocationCoordinate2DMake(coordinate._lat, coordinate._lon)]; - - - //NSLog(@"ZOOM LEVEL: %f",mapView.zoomLevel); - //NSLog(@"Meters Per Pixel: %f",proj.metersPerPoint); - - - // The 2.0 is point to pixel scaling - double viewportSizeXPoints = resource.mtkView.drawableSize.width / 2.0; - double viewportSizeYPoints = resource.mtkView.drawableSize.height / 2.0; - - double halfX = (viewportSizeXPoints / 2.0); - double halfY = (viewportSizeYPoints / 2.0); - - double offsetX = p.x - halfX; - - double projX = offsetX / viewportSizeXPoints; - double projY = (viewportSizeYPoints - p.y - halfY) / viewportSizeYPoints; - - double aspect = viewportSizeXPoints / viewportSizeYPoints; - - tempResult._x = projX * 4.0 * aspect; - tempResult._y = projY * 4.0; - - - double x = p.x / viewportSizeXPoints; - double y = p.y / viewportSizeYPoints; - - x = (x * 2) - 1; - y = (y * 2) - 1; - y = -y; - tempResult._x = x; - tempResult._y = y; - - - -// tempResult._x = projX; -// tempResult._y = projY; - - NSLog(@"P: %f, %f -> %f, %f", p.x, p.y, x, y); // projX, projY, x, y); - - return tempResult; - */ }); loadModels = true; @@ -387,7 +328,9 @@ - (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingCon _metalEnvironment->_metalDevice = resource.mtkView.device; _metalEnvironment->_currentDrawable = resource.mtkView.currentDrawable; _metalEnvironment->_currentRenderPassDescriptor = resource.mtkView.currentRenderPassDescriptor; - _metalEnvironment->_lightDirection = simd_make_float3(000.0, 10000.0, 10000.0); + if (self.lightSet) { + _metalEnvironment->_lightDirection = simd_make_float3(_lightX, _lightY, _lightZ); + } // TODO: Remove this.. This is legacy _manager->setRenderingEnvironmentVariables(_metalEnvironment); @@ -399,10 +342,7 @@ - (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingCon vector_uint2 _viewportSize; _viewportSize.x = resource.mtkView.drawableSize.width; _viewportSize.y = resource.mtkView.drawableSize.height; - _manager->setDrawableSize(_viewportSize.x, _viewportSize.y); - _manager->_metersPerPixel = 0.05; - MLNMapProjection *proj2 = mapView.mapProjection; _manager->_metersPerPixel = proj2.metersPerPoint / 2.0; @@ -412,57 +352,8 @@ - (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingCon float timestep = (1 / 60.0f); _manager->updateScene(timestep); - // Render the image _manager->render(); - /* - return; - - - - - - MLNMapProjection *proj = mapView.mapProjection; - CGPoint p = [proj convertCoordinate:CLLocationCoordinate2DMake(43, -70)]; - NSLog(@"P: %f, %f", p.x, p.y); - - // Use the supplied render command encoder to encode commands - id renderEncoder = self.renderEncoder; - if(renderEncoder != nil) - { - - typedef struct - { - vector_float2 position; - vector_float4 color; - } Vertex; - - static const Vertex triangleVertices[] = - { - // 2D positions, RGBA colors - { { 250, -250 }, { 1, 0, 0, 1 } }, - { { -250, -250 }, { 0, 1, 0, 1 } }, - { { 0, 250 }, { 0, 0, 1, 1 } }, - }; - - [renderEncoder setRenderPipelineState:_pipelineState]; - [renderEncoder setDepthStencilState:_depthStencilStateWithoutStencil]; - - // Pass in the parameter data. - [renderEncoder setVertexBytes:triangleVertices - length:sizeof(triangleVertices) - atIndex:0]; - - [renderEncoder setVertexBytes:&_viewportSize - length:sizeof(_viewportSize) - atIndex:1]; - - // Draw the triangle. - [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle - vertexStart:0 - vertexCount:3]; - } - */ } From a9e414262a020062a95dd2dc5685fbe5669ed02e Mon Sep 17 00:00:00 2001 From: Yousif Date: Sun, 19 Jan 2025 16:56:13 +0300 Subject: [PATCH 021/221] fix build errors related to type mismatch --- .../src/gltf/MetalRenderer+GLTFAsset.mm | 10 +++----- platform/darwin/src/gltf/gltfkit/GLTFAsset.m | 24 +++++++++---------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm b/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm index e3537787de61..d5f2a126d903 100644 --- a/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm +++ b/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm @@ -381,11 +381,7 @@ simd_float3 double3_to_float3(simd_double3 input) { vertexUniforms.brightness = model->_brightness; vertexUniforms.lightDirection = _renderingEnvironment->_lightDirection; - - - - - FragmentUniforms fragmentUniforms = { 0 }; + FragmentUniforms fragmentUniforms; fragmentUniforms.normalScale = material.normalTextureScale; fragmentUniforms.emissiveFactor = material.emissiveFactor; fragmentUniforms.occlusionStrength = material.occlusionStrength; @@ -417,7 +413,7 @@ simd_float3 double3_to_float3(simd_double3 input) { } // TODO: Make this more efficient. Iterating the light list for every submesh is pretty silly. - for (int lightIndex = 0; lightIndex < _currentLightNodes.count; ++lightIndex) { + for (unsigned int lightIndex = 0; lightIndex < _currentLightNodes.count; ++lightIndex) { GLTFNode *lightNode = _currentLightNodes[lightIndex]; GLTFKHRLight *light = lightNode.light; if (light.type == GLTFKHRLightTypeDirectional) { @@ -589,7 +585,7 @@ simd_float3 double3_to_float3(simd_double3 input) { id MetalRenderer::dequeueReusableBufferOfLength(size_t length) { int indexToReuse = -1; - for (int i = 0; i < _bufferPool.count; ++i) { + for (unsigned int i = 0; i < _bufferPool.count; ++i) { if (_bufferPool[i].length >= length) { indexToReuse = i; } diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAsset.m b/platform/darwin/src/gltf/gltfkit/GLTFAsset.m index c375ca1e6463..b54289e4ddeb 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFAsset.m +++ b/platform/darwin/src/gltf/gltfkit/GLTFAsset.m @@ -253,7 +253,7 @@ - (void)readBinaryChunks:(NSData *)assetData { GLTFBinaryHeader header; [assetData getBytes:&header length:sizeof(GLTFBinaryHeader)]; - NSInteger offset = sizeof(GLTFBinaryHeader); + NSUInteger offset = sizeof(GLTFBinaryHeader); while (offset < header.length && offset < assetData.length) { GLTFBinaryChunk *chunk = [GLTFBinaryChunk new]; struct { @@ -355,7 +355,7 @@ - (BOOL)loadBuffers:(NSArray *)buffersMap { NSMutableArray *buffers = [NSMutableArray arrayWithCapacity:buffersMap.count]; for (NSDictionary *properties in buffersMap) { - NSUInteger byteLength = [properties[@"byteLength"] integerValue]; + NSInteger byteLength = [properties[@"byteLength"] integerValue]; NSString *uri = properties[@"uri"]; NSData *data = nil; @@ -1064,7 +1064,7 @@ - (BOOL)loadNodes:(NSArray *)nodesMap { if (_usesKHRLights) { NSDictionary *lightProperties = node.extensions[GLTFExtensionKHRLights]; NSNumber *lightIdentifierValue = lightProperties[@"light"]; - if (lightIdentifierValue && lightIdentifierValue.integerValue < _lights.count) { + if (lightIdentifierValue && lightIdentifierValue.unsignedIntValue < _lights.count) { node.light = _lights[lightIdentifierValue.integerValue]; } } @@ -1094,16 +1094,16 @@ - (BOOL)fixNodeRelationships { for (GLTFSkin *skin in _skins) { NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:skin.jointNodes.count]; - for (NSInteger i = 0; i < skin.jointNodes.count; ++i) { + for (NSUInteger i = 0; i < skin.jointNodes.count; ++i) { NSNumber *jointIndexValue = (NSNumber *)skin.jointNodes[i]; - if (jointIndexValue != nil && jointIndexValue.intValue < _nodes.count) { + if (jointIndexValue != nil && jointIndexValue.unsignedIntegerValue < _nodes.count) { [nodes addObject:_nodes[jointIndexValue.intValue]]; } } skin.jointNodes = [nodes copy]; NSNumber *skeletonIndexValue = (NSNumber *)skin.skeletonRootNode; - if (skeletonIndexValue != nil && skeletonIndexValue.intValue < _nodes.count) { + if (skeletonIndexValue != nil && skeletonIndexValue.unsignedIntegerValue < _nodes.count) { skin.skeletonRootNode = _nodes[skeletonIndexValue.intValue]; } } @@ -1129,11 +1129,11 @@ - (BOOL)loadAnimations:(NSArray *)animationsMap { [samplersProperties enumerateObjectsUsingBlock:^(NSDictionary *samplerProperties, NSUInteger index, BOOL *stop) { GLTFAnimationSampler *sampler = [[GLTFAnimationSampler alloc] init]; NSNumber *inputIndexValue = samplerProperties[@"input"]; - if (inputIndexValue && inputIndexValue.integerValue < _accessors.count) { + if (inputIndexValue && inputIndexValue.unsignedIntegerValue < _accessors.count) { sampler.inputAccessor = _accessors[inputIndexValue.integerValue]; } NSNumber *outputIndexValue = samplerProperties[@"output"]; - if (outputIndexValue && outputIndexValue.integerValue < _accessors.count) { + if (outputIndexValue && outputIndexValue.unsignedIntegerValue < _accessors.count) { sampler.outputAccessor = _accessors[outputIndexValue.integerValue]; } if (samplerProperties[@"interpolation"]) { @@ -1149,12 +1149,12 @@ - (BOOL)loadAnimations:(NSArray *)animationsMap { [channelsProperties enumerateObjectsUsingBlock:^(NSDictionary *channelProperties, NSUInteger index, BOOL *stop) { GLTFAnimationChannel *channel = [GLTFAnimationChannel new]; NSNumber *samplerIndexValue = channelProperties[@"sampler"]; - if (samplerIndexValue && samplerIndexValue.integerValue < samplers.count) { + if (samplerIndexValue && samplerIndexValue.unsignedIntegerValue < samplers.count) { channel.sampler = samplers[samplerIndexValue.integerValue]; } NSDictionary *targetProperties = channelProperties[@"target"]; NSNumber *targetNodeIndexValue = targetProperties[@"node"]; - if (targetNodeIndexValue && targetNodeIndexValue.integerValue < _nodes.count) { + if (targetNodeIndexValue && targetNodeIndexValue.unsignedIntegerValue < _nodes.count) { channel.targetNode = _nodes[targetNodeIndexValue.integerValue]; } channel.targetPath = targetProperties[@"path"]; @@ -1187,7 +1187,7 @@ - (BOOL)loadSkins:(NSArray *)skinsMap { NSNumber *inverseBindMatricesAccessorIndexValue = properties[@"inverseBindMatrices"]; if (inverseBindMatricesAccessorIndexValue != nil) { - NSInteger inverseBindMatricesAccessorIndex = inverseBindMatricesAccessorIndexValue.integerValue; + NSUInteger inverseBindMatricesAccessorIndex = inverseBindMatricesAccessorIndexValue.unsignedIntegerValue; if (inverseBindMatricesAccessorIndex < _accessors.count) { skin.inverseBindMatricesAccessor = _accessors[inverseBindMatricesAccessorIndex]; } @@ -1243,7 +1243,7 @@ - (BOOL)loadScenes:(NSArray *)scenesMap { if (_usesKHRLights) { NSDictionary *lightProperties = scene.extensions[GLTFExtensionKHRLights]; NSNumber *lightIdentifierValue = lightProperties[@"light"]; - if (lightIdentifierValue != nil && lightIdentifierValue.integerValue < _lights.count) { + if (lightIdentifierValue != nil && lightIdentifierValue.unsignedIntegerValue < _lights.count) { scene.ambientLight = _lights[lightIdentifierValue.integerValue]; } } From 0a35556d75a25760b1c9be954594ce753991721c Mon Sep 17 00:00:00 2001 From: Yousif Date: Sun, 19 Jan 2025 17:59:09 +0300 Subject: [PATCH 022/221] convert GLTFRenderer.cpp to objective-c++ --- platform/darwin/bazel/files.bzl | 2 +- platform/darwin/src/gltf/{GLTFRenderer.cpp => GLTFRenderer.mm} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename platform/darwin/src/gltf/{GLTFRenderer.cpp => GLTFRenderer.mm} (98%) diff --git a/platform/darwin/bazel/files.bzl b/platform/darwin/bazel/files.bzl index f18243fceb4d..3e11397755d2 100644 --- a/platform/darwin/bazel/files.bzl +++ b/platform/darwin/bazel/files.bzl @@ -24,7 +24,7 @@ MLN_GLTF_SOURCE = [ "src/gltf/GLTFMTLRenderItem.h", "src/gltf/GLTFMTLRenderItem.m", "src/gltf/GLTFRenderer.hpp", - "src/gltf/GLTFRenderer.cpp", + "src/gltf/GLTFRenderer.mm", "src/gltf/MetalRenderer+GLTFAsset.mm", "src/gltf/gltfkit/GLTFAsset.h", "src/gltf/gltfkit/GLTFAsset.m", diff --git a/platform/darwin/src/gltf/GLTFRenderer.cpp b/platform/darwin/src/gltf/GLTFRenderer.mm similarity index 98% rename from platform/darwin/src/gltf/GLTFRenderer.cpp rename to platform/darwin/src/gltf/GLTFRenderer.mm index f02c711593ab..86fc66be865d 100644 --- a/platform/darwin/src/gltf/GLTFRenderer.cpp +++ b/platform/darwin/src/gltf/GLTFRenderer.mm @@ -25,7 +25,7 @@ void GLTFRenderer::update(float timeSinceLastDraw) { } // Render -void GLTFRenderer::render() { + void GLTFRenderer::render() { // Base class does nothing } From 03ffff02a14386ea5aef785a0174c538cd6693b2 Mon Sep 17 00:00:00 2001 From: Yousif Date: Sun, 19 Jan 2025 18:07:45 +0300 Subject: [PATCH 023/221] cleanup gltf renderer code from comments and unused instructions --- platform/darwin/src/gltf/GLTFModelLayer.mm | 10 +- .../src/gltf/MetalRenderer+GLTFAsset.mm | 148 +----------------- platform/darwin/src/gltf/MetalRenderer.mm | 96 +----------- 3 files changed, 15 insertions(+), 239 deletions(-) diff --git a/platform/darwin/src/gltf/GLTFModelLayer.mm b/platform/darwin/src/gltf/GLTFModelLayer.mm index 51b3b59d3ded..cad7eb62d07b 100644 --- a/platform/darwin/src/gltf/GLTFModelLayer.mm +++ b/platform/darwin/src/gltf/GLTFModelLayer.mm @@ -300,21 +300,18 @@ - (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingCon _manager->setProjectionCallback(^Cartesian3D(const Coordinate2D & coordinate){ Cartesian3D tempResult; - tempResult._x = 0; - tempResult._y = 0; + tempResult._x = 5198170.102753558; + tempResult._y = 2832006.4886368043; tempResult._z = 0; - + tempResult._x = coordinate._lon * DEG_RAD; double lat = coordinate._lat * DEG_RAD; -// if (lat < -PoleLimit) lat = -PoleLimit; -// if (lat > PoleLimit) lat = PoleLimit; tempResult._y = log((1.0f+sin(lat))/cos(lat)); double metersScale = 20037508.34; tempResult._x = tempResult._x * metersScale / M_PI; tempResult._y = tempResult._y * metersScale / M_PI; return tempResult; - }); loadModels = true; @@ -354,7 +351,6 @@ - (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingCon // Render the image _manager->render(); - } - (void)willMoveFromMapView:(MLNMapView *)mapView { diff --git a/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm b/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm index d5f2a126d903..89d169ef21a1 100644 --- a/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm +++ b/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm @@ -100,7 +100,6 @@ void MetalRenderer::computeTransforms(std::shared_ptr model) { // New stuff - auto mdlMatrix = matrix_identity_double4x4; // Rotation @@ -108,16 +107,8 @@ auto modelRotated = matrix_multiply(modelRotation, mdlMatrix); // Tilt - // auto modelEnvironmentTilt = GLTFRotationMatrixFromAxisAngle(GLTFAxisX, _tiltDeg * DEG_RAD); -// auto modelTilt = GLTFRotationMatrixFromAxisAngle(GLTFAxisX, -90 * DEG_RAD); -// auto modelTilted = matrix_multiply(modelTilt, modelRotated); - - //auto modelTilted = matrix_identity_float4x4; - auto modelTilted = GLTFRotationMatrixFromAxisAngleD(GLTFAxisXD, 90 * DEG_RAD); - modelTilted = matrix_multiply(modelTilted, modelRotation); - -// auto modelTilted = matrix_multiply(modelEnvironmentTilt, modelRotated); + modelTilted = matrix_multiply(modelTilted, modelRotated); simd_double3 xlateVector = simd_make_double3(model->_gltfModel->_xLateX, model->_gltfModel->_xLateY, @@ -125,136 +116,13 @@ auto xLateMatrix = GLTFMatrixFromTranslationD(xlateVector); - - // auto modelTranslated = matrix_multiply(xLateMatrix, modelTilted); model->_modelMatrix = modelTranslated; - - model->_modelViewMatrix = matrix_multiply(_camera->_viewMatrix, - modelTranslated); - model->_modelViewMatrix = modelTranslated; // matrix_multiply(_camera->_viewMatrix, - //modelTranslated); + model->_modelViewMatrix = modelTranslated; - return; - - - - - - - - - - - - - // TODO: Someday look into point of view? - /* - if (self.pointOfView == nil) { - self.viewMatrix = matrix_multiply(self.camera.viewMatrix, self.regularizationMatrix); - } else { - self.viewMatrix = self.camera.viewMatrix; - } - */ - - // TODO: Remove this.. just something to show that the translation stuff - // is in there - //model->_rotationDeg = 0; // model->_rotationDeg + 0.75; - - /* - auto rotationMatrix = GLTFRotationMatrixFromAxisAngle(simd_make_float3(0.0, 1.0, 0.0), model->_rotationDeg * DEG_RAD); - auto rotatedModel = matrix_multiply(modelMatrix, rotationMatrix); - auto translatedVector = model->_translationVector + model->_translationDistance; - translatedVector.z = 0; - auto translationMatrix = GLTFMatrixFromTranslation(translatedVector); - auto modelMatrix2 = matrix_multiply(translationMatrix, rotatedModel); - model->_viewMatrix = matrix_multiply(modelMatrix2, _camera->_viewMatrix); -*/ - - - - /* This is what was working with Steve - - // Compute the model matrix: This was the original - model->_modelViewMatrix = matrix_multiply(_camera->_viewMatrix, - model->_regularizationMatrix); - - // New news - static float rot = 0; - rot += 0.01; - static float xLate = 0; - static float xLateDir = 0.01; - xLate = xLate + xLateDir; - if (xLate > 1) { - xLateDir = -0.01; - } else if (xLate < -1) { - xLateDir = 0.01; - } - rot = 0; - xLate = 0; - - simd_float3 translatedVector = simd_make_float3(model->_gltfModel->_xLateX, - model->_gltfModel->_xLateY, - model->_gltfModel->_xLateZ); - - auto translationMatrix = GLTFMatrixFromTranslation(translatedVector); - - - // TODO: This goes away.. Just the regularizating matrix - auto modelMatrix = model->_regularizationMatrix; - - // This will be the first matrix in the future - modelMatrix = matrix_identity_float4x4; - double metersInView = (double)_drawableSize.x * _metersPerPixel; - double scale = 2.0 / metersInView; - auto scaleMatrix = GLTFMatrixFromUniformScale(scale); - modelMatrix = matrix_multiply(scaleMatrix, modelMatrix); - - // Rotation - auto modelEnvironmentRotation = GLTFRotationMatrixFromAxisAngle(GLTFAxisY, (model->_gltfModel->_rotationDeg) * DEG_RAD); - auto modelRotated = matrix_multiply(modelEnvironmentRotation, modelMatrix); - - // Tilt - // auto modelEnvironmentTilt = GLTFRotationMatrixFromAxisAngle(GLTFAxisX, _tiltDeg * DEG_RAD); - auto modelEnvironmentTilt = GLTFRotationMatrixFromAxisAngle(GLTFAxisX, -90 * DEG_RAD); - auto modelTilted = matrix_multiply(modelEnvironmentTilt, modelRotated); - - // This was just debug stuff to rotate in the scene -// auto modelRotation = GLTFRotationMatrixFromAxisAngle(GLTFAxisY, -rot); -// auto modelRotation2 = matrix_multiply(modelRotation, modelMatrix); -// - - - modelTilted = matrix_identity_float4x4; - - modelTilted = GLTFRotationMatrixFromAxisAngle(GLTFAxisX, 90 * DEG_RAD); - modelTilted = matrix_multiply(modelTilted, modelEnvironmentRotation); - -// auto modelTilted = matrix_multiply(modelEnvironmentTilt, modelRotated); - - - // - auto modelTranslated = matrix_multiply(translationMatrix, modelTilted); - - model->_modelMatrix = modelTranslated; - - model->_modelViewMatrix = matrix_multiply(_camera->_viewMatrix, - modelTranslated); - - model->_modelViewMatrix = modelTranslated; // matrix_multiply(_camera->_viewMatrix, - //modelTranslated); - - - - */ - - - - - } void MetalRenderer::renderScene(std::shared_ptr model, @@ -367,14 +235,12 @@ simd_float3 double3_to_float3(simd_double3 input) { VertexUniforms vertexUniforms; vertexUniforms.modelMatrix = modelMatrix; -// vertexUniforms.modelViewProjectionMatrix = mvpF; - vertexUniforms.normalMatrix = GLTFNormalMatrixFromModelMatrix(modelMatrix); // TODO: MT: Review this.. - auto mvp = matrix_multiply(_projectionMatrix, model->_modelViewMatrix); + auto mvp = matrix_multiply(_projectionMatrix, model->_modelMatrix); auto mvpF = matrix_double_to_float(mvp); vertexUniforms.modelViewProjectionMatrix = mvpF; - auto normalMatrix = GLTFNormalMatrixFromModelMatrixD( model->_modelViewMatrix); + auto normalMatrix = GLTFNormalMatrixFromModelMatrixD(model->_modelMatrix); vertexUniforms.normalMatrix = matrix_double_to_float(normalMatrix); vertexUniforms.scaleFactor = model->_scaling; @@ -575,12 +441,6 @@ simd_float3 double3_to_float3(simd_double3 input) { [renderEncoder setFragmentTexture:texture atIndex:GLTFTextureBindIndexOcclusion]; [renderEncoder setFragmentSamplerState:sampler atIndex:GLTFTextureBindIndexOcclusion]; } - -// if (self.lightingEnvironment) { -// [renderEncoder setFragmentTexture:self.lightingEnvironment.specularCube atIndex:GLTFTextureBindIndexSpecularEnvironment]; -// [renderEncoder setFragmentTexture:self.lightingEnvironment.diffuseCube atIndex:GLTFTextureBindIndexDiffuseEnvironment]; -// [renderEncoder setFragmentTexture:self.lightingEnvironment.brdfLUT atIndex:GLTFTextureBindIndexBRDFLookup]; -// } } id MetalRenderer::dequeueReusableBufferOfLength(size_t length) { diff --git a/platform/darwin/src/gltf/MetalRenderer.mm b/platform/darwin/src/gltf/MetalRenderer.mm index 47d9beb95f45..69c626032632 100644 --- a/platform/darwin/src/gltf/MetalRenderer.mm +++ b/platform/darwin/src/gltf/MetalRenderer.mm @@ -95,92 +95,17 @@ // Render void MetalRenderer::render() { - // Compute the projection matrix - float aspectRatio = (float)_drawableSize.x / (float)_drawableSize.y; - simd_double4x4 aspectCorrection = GLTFMatrixFromScaleD((simd_double3){ 1 / aspectRatio, 1, 1 }); - _projectionMatrix = simd_mul(aspectCorrection, _camera->projectionMatrix()); - - /* - simd_float4x4 tempMatrix = _projectionMatrix; - - // Set the projection matrix from the incoming environment - _projectionMatrix = _metalRenderingEnvironment->_currentProjectionMatrix; - - // Remove the translation - _projectionMatrix.columns[3][0] = tempMatrix.columns[3][0]; - _projectionMatrix.columns[3][1] = tempMatrix.columns[3][1]; - _projectionMatrix.columns[3][2] = tempMatrix.columns[3][2]; - _projectionMatrix.columns[3][3] = tempMatrix.columns[3][3]; - - - // Moved this to the camera projectionMatrix -// double fov = 0.6435011087932844; -// _projectionMatrix = GLTFPerspectiveProjectionMatrixAspectFovRH(fov, aspectRatio, 0.0001, 2); - - */ - - /* Stuff with Steve - auto environmentMVP = _metalRenderingEnvironment->_currentProjectionMatrix; - double tileSize = 256.0; - double zoom = _metalRenderingEnvironment->_currentZoomLevel; - double scaleFactor = (20037508.34); // M_PI - double worldSize = tileSize / scaleFactor * pow(2.0,zoom); - simd_float4x4 scaleMatrix = GLTFMatrixFromScale(simd_make_float3(worldSize, -worldSize, 1.0)); - simd_float4x4 xlateMatrix = GLTFMatrixFromTranslation(simd_make_float3(20037508.34,-20037508.34,0.0)); - - auto m1 = matrix_multiply(scaleMatrix, xlateMatrix); - auto m2 = matrix_multiply(environmentMVP, m1); - _projectionMatrix = m2; - */ - - auto environmentMVP = _metalRenderingEnvironment->_currentProjectionMatrix; double tileSize = 256.0; double zoom = _metalRenderingEnvironment->_currentZoomLevel; double scaleFactor = (20037508.34); // M_PI - double worldSize = tileSize / scaleFactor * pow(2.0,zoom); + double worldSize = (tileSize / scaleFactor) * pow(2.0, zoom); simd_double4x4 scaleMatrix = GLTFMatrixFromScaleD(simd_make_double3(worldSize, -worldSize, 1.0)); simd_double4x4 xlateMatrix = GLTFMatrixFromTranslationD(simd_make_double3(20037508.34,-20037508.34,0.0)); auto m1 = matrix_multiply(scaleMatrix, xlateMatrix); auto m2 = matrix_multiply(environmentMVP, m1); _projectionMatrix = m2; - - - - - // Apply a scale to our data first - // Note: Can see something with this -// const Eigen::Affine3d scaleTrans(Eigen::Scaling(worldSize,-worldSize,1.0)); -// const Eigen::Affine3d transTrans(Eigen::Translation3d(20037508.34,-20037508.34,0.0)); -// Eigen::Matrix4d mvp = (inMvp * (scaleTrans * transTrans) ).matrix(); -// - - /* - - - // The above projection matrix is a perspective matrix. I think we need an ortho matrix - float w = ((float)_drawableSize.x) / 2.0; - float h = ((float)_drawableSize.y) / 2.0; - float aspect = w/h; -// _projectionMatrix = GLTFOrthoProjectionMatrix(-w,w,-h*aspect,h*aspect,0.001,250); - _projectionMatrix = GLTFOrthoProjectionMatrix(-1*aspect,1*aspect,-1,1,10,-10); - - - // ANother projection matrix test - float fov = _renderingEnvironment->_currentFOVDEG * DEG_RAD; // 0.6435011087932844; // Constant that i found in ML - simd_float4x4 matrix = GLTFPerspectiveProjectionMatrixAspectFovRH(fov, aspect, 0.01, 250); - _projectionMatrix = matrix; - - - */ - - - - // Check to see if we're drawing directly or using another command buffer - bool _existingCommandBuffer = _metalRenderingEnvironment->_currentCommandBuffer != nullptr; - - id currentDrawable = nil; // Internal command buffer id internalCommandBuffer = [_internalMetalCommandQueue commandBuffer]; @@ -276,9 +201,6 @@ for (auto m: _models) { [renderEncoder pushDebugGroup:@"Draw glTF Scene"]; renderScene(m, m->_asset.defaultScene, commandBuffer, renderEncoder); - // [self.renderer renderScene:self.asset.defaultScene - // commandBuffer:commandBuffer - // commandEncoder:renderEncoder]; [renderEncoder popDebugGroup]; } @@ -402,10 +324,9 @@ _internalMetalCommandQueue = [_metalDevice newCommandQueue]; _metalLibrary = [_metalDevice newDefaultLibrary]; - //_viewMatrix = matrix_identity_float4x4; _projectionMatrix = matrix_identity_double4x4; _colorPixelFormat = MTLPixelFormatBGRA8Unorm; - _depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8; + _depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8; _sampleCount = 1; _drawableSize = {1, 1}; @@ -462,12 +383,12 @@ textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; _colorTexture = [_metalDevice newTextureWithDescriptor:textureDescriptor]; - textureDescriptor.textureType = _sampleCount > 1 ? MTLTextureType2DMultisample : MTLTextureType2D; - textureDescriptor.pixelFormat = _depthStencilPixelFormat; - textureDescriptor.sampleCount = _sampleCount; - textureDescriptor.storageMode = MTLStorageModePrivate; - textureDescriptor.usage = MTLTextureUsageRenderTarget; - _depthStencilTexture = [_metalDevice newTextureWithDescriptor:textureDescriptor]; + textureDescriptor.textureType = _sampleCount > 1 ? MTLTextureType2DMultisample : MTLTextureType2D; + textureDescriptor.pixelFormat = _depthStencilPixelFormat; + textureDescriptor.sampleCount = _sampleCount; + textureDescriptor.storageMode = MTLStorageModePrivate; + textureDescriptor.usage = MTLTextureUsageRenderTarget; + _depthStencilTexture = [_metalDevice newTextureWithDescriptor:textureDescriptor]; textureDescriptor.width = _drawableSize.x / 2; textureDescriptor.height = _drawableSize.y / 2; @@ -593,7 +514,6 @@ if (pipeline == nil) { GLTFMTLShaderBuilder *shaderBuilder = [[GLTFMTLShaderBuilder alloc] init]; pipeline = [shaderBuilder renderPipelineStateForSubmesh: submesh - // lightingEnvironment:self.lightingEnvironment colorPixelFormat:_colorPixelFormat depthStencilPixelFormat:_depthStencilPixelFormat sampleCount:_sampleCount From dd0c472ea18b10f4b340d83924ca794f58b721d3 Mon Sep 17 00:00:00 2001 From: Yousif Date: Mon, 20 Jan 2025 11:28:33 +0300 Subject: [PATCH 024/221] add nearclippedprojmatrix to custom layer context --- include/mbgl/style/layers/custom_layer_render_parameters.hpp | 1 + platform/darwin/src/MLNCustomStyleLayer.h | 1 + platform/darwin/src/MLNCustomStyleLayer.mm | 3 ++- src/mbgl/style/layers/custom_layer_render_parameters.cpp | 3 +++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/mbgl/style/layers/custom_layer_render_parameters.hpp b/include/mbgl/style/layers/custom_layer_render_parameters.hpp index 54eb7d90d413..36be0aec0fbc 100644 --- a/include/mbgl/style/layers/custom_layer_render_parameters.hpp +++ b/include/mbgl/style/layers/custom_layer_render_parameters.hpp @@ -23,6 +23,7 @@ struct CustomLayerRenderParameters { double pitch; double fieldOfView; std::array projectionMatrix; + std::array nearClippedProjMatrix; CustomLayerRenderParameters(const PaintParameters&); }; diff --git a/platform/darwin/src/MLNCustomStyleLayer.h b/platform/darwin/src/MLNCustomStyleLayer.h index d0c57a714d02..fd6247958270 100644 --- a/platform/darwin/src/MLNCustomStyleLayer.h +++ b/platform/darwin/src/MLNCustomStyleLayer.h @@ -32,6 +32,7 @@ typedef struct MLNStyleLayerDrawingContext { CGFloat fieldOfView; /// A 4×4 matrix representing the map view’s current projection state. MLNMatrix4 projectionMatrix; + MLNMatrix4 nearClippedProjMatrix; } MLNStyleLayerDrawingContext; /// A style layer that is rendered by Metal code that you provide. diff --git a/platform/darwin/src/MLNCustomStyleLayer.mm b/platform/darwin/src/MLNCustomStyleLayer.mm index 5e3107bb4c34..b529d0bf79c2 100644 --- a/platform/darwin/src/MLNCustomStyleLayer.mm +++ b/platform/darwin/src/MLNCustomStyleLayer.mm @@ -116,7 +116,8 @@ void render(const mbgl::style::CustomLayerRenderParameters& parameters) { .direction = mbgl::util::wrap(parameters.bearing, 0., 360.), .pitch = static_cast(parameters.pitch), .fieldOfView = static_cast(parameters.fieldOfView), - .projectionMatrix = MLNMatrix4Make(parameters.projectionMatrix) + .projectionMatrix = MLNMatrix4Make(parameters.projectionMatrix), + .nearClippedProjMatrix = MLNMatrix4Make(parameters.nearClippedProjMatrix) }; if (layer.mapView) { diff --git a/src/mbgl/style/layers/custom_layer_render_parameters.cpp b/src/mbgl/style/layers/custom_layer_render_parameters.cpp index 67fb1e93910c..4541234ad821 100644 --- a/src/mbgl/style/layers/custom_layer_render_parameters.cpp +++ b/src/mbgl/style/layers/custom_layer_render_parameters.cpp @@ -18,6 +18,9 @@ CustomLayerRenderParameters::CustomLayerRenderParameters(const mbgl::PaintParame mat4 projMatrix; state.getProjMatrix(projMatrix); projectionMatrix = projMatrix; + + const TransformParameters& params = paintParameters.transformParams; + nearClippedProjMatrix = params.nearClippedProjMatrix; } } // namespace style From b7346274b7bed96a747e87b0d26f29dec12438b0 Mon Sep 17 00:00:00 2001 From: Yousif Date: Mon, 20 Jan 2025 11:30:03 +0300 Subject: [PATCH 025/221] utilize the same render encoder as maplibre-native in gltf metal renderer --- platform/darwin/src/gltf/MetalRenderer.mm | 51 +++---------------- .../src/gltf/gltfkit/GLTFMTLShaderBuilder.m | 2 +- 2 files changed, 9 insertions(+), 44 deletions(-) diff --git a/platform/darwin/src/gltf/MetalRenderer.mm b/platform/darwin/src/gltf/MetalRenderer.mm index 69c626032632..bef2b4356ec8 100644 --- a/platform/darwin/src/gltf/MetalRenderer.mm +++ b/platform/darwin/src/gltf/MetalRenderer.mm @@ -106,9 +106,8 @@ auto m1 = matrix_multiply(scaleMatrix, xlateMatrix); auto m2 = matrix_multiply(environmentMVP, m1); _projectionMatrix = m2; - - // Internal command buffer - id internalCommandBuffer = [_internalMetalCommandQueue commandBuffer]; + + // id internalCommandBuffer = [_internalMetalCommandQueue commandBuffer]; // // if (_existingCommandBuffer) { // commandBuffer = _metalRenderingEnvironment->_currentCommandBuffer; @@ -118,10 +117,10 @@ // currentDrawable = _metalRenderingEnvironment->_currentDrawable; // } // - encodeMainPass(internalCommandBuffer); - if (_useBloomPass) { - encodeBloomPasses(internalCommandBuffer); - } + encodeMainPass(_metalRenderingEnvironment->_currentCommandBuffer); + // if (_useBloomPass) { + // encodeBloomPasses(internalCommandBuffer); + // } // [internalCommandBuffer addCompletedHandler:^(id buffer) { // dispatch_async(dispatch_get_main_queue(), ^{ @@ -129,26 +128,12 @@ // }); // }]; - [internalCommandBuffer commit]; // This will write out the tone mapping //id externalBuffer = _metalRenderingEnvironment->_currentCommandBuffer; //encodeTonemappingPass(externalBuffer); - - // TESTING - [_metalRenderingEnvironment->_currentCommandEncoder pushDebugGroup:@"Post-process (Tonemapping)"]; - [_metalRenderingEnvironment->_currentCommandEncoder setDepthStencilState:_fullscreenTransfterDepthStencilState]; - drawFullscreenPassWithPipeline(_tonemapPipelineState,_metalRenderingEnvironment->_currentCommandEncoder,_colorTexture); - [_metalRenderingEnvironment->_currentCommandEncoder popDebugGroup]; - // [_metalRenderingEnvironment->_currentCommandEncoder endEncoding]; - - - -// if (!_existingCommandBuffer) { -// [commandBuffer presentDrawable:currentDrawable]; -// } - + // Internal command buffer } @@ -177,26 +162,7 @@ // RENDERING void MetalRenderer::encodeMainPass(id commandBuffer) { - MTLRenderPassDescriptor *pass = newRenderPassDescriptor(); - id renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:pass]; - - /* - if (self.lightingEnvironment != nil) { - [renderEncoder pushDebugGroup:@"Draw Backdrop"]; - [self drawSkyboxWithCommandEncoder:renderEncoder]; - [renderEncoder popDebugGroup]; - } - */ - - /* - long timedOut = dispatch_semaphore_wait(_frameBoundarySemaphore, dispatch_time(0, 10 * NSEC_PER_SEC)); - if (timedOut) { - NSLog(@"Failed to receive frame boundary signal before timing out; calling signalFrameCompletion manually. " - "Remember to call signalFrameCompletion on GLTFMTLRenderer from the completion handler of the command buffer " - "into which you encode the work for drawing assets"); - signalFrameCompletion(); - } -*/ + id renderEncoder = _metalRenderingEnvironment->_currentCommandEncoder; for (auto m: _models) { [renderEncoder pushDebugGroup:@"Draw glTF Scene"]; @@ -204,7 +170,6 @@ [renderEncoder popDebugGroup]; } - [renderEncoder endEncoding]; } diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.m b/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.m index 835017d4876e..8045d13e9f1c 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.m +++ b/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.m @@ -84,7 +84,7 @@ @implementation GLTFMTLShaderBuilder } pipelineDescriptor.depthAttachmentPixelFormat = depthStencilPixelFormat; -// pipelineDescriptor.stencilAttachmentPixelFormat = depthStencilPixelFormat; + pipelineDescriptor.stencilAttachmentPixelFormat = depthStencilPixelFormat; id pipeline = [device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:&error]; if (!pipeline) { From fc3b6ad1427de1d29d9000f5dea8fd25938b7324 Mon Sep 17 00:00:00 2001 From: Yousif Date: Mon, 20 Jan 2025 11:30:35 +0300 Subject: [PATCH 026/221] utilize the depth and color textures from the current render pass descriptor --- .../gltf/GLTFManagerRenderingEnvironmentMetal.hpp | 4 ++-- platform/darwin/src/gltf/GLTFModelLayer.mm | 7 +++++-- platform/darwin/src/gltf/MetalRenderer.mm | 14 +++++++------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp index a052fbbaf295..ba73b24973e0 100644 --- a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp +++ b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp @@ -30,8 +30,8 @@ namespace maplibre { namespace gltf { // TBD: These are placeholders as we noodle how to integrate with ML // Depth descriptor: If this is null, then use an internal depth id _depthStencilTexture = nullptr; - - + + id _colorTexture = nullptr; }; }} diff --git a/platform/darwin/src/gltf/GLTFModelLayer.mm b/platform/darwin/src/gltf/GLTFModelLayer.mm index cad7eb62d07b..c88150a4e310 100644 --- a/platform/darwin/src/gltf/GLTFModelLayer.mm +++ b/platform/darwin/src/gltf/GLTFModelLayer.mm @@ -318,17 +318,20 @@ - (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingCon } _metalEnvironment->_currentFOVDEG = context.fieldOfView * RAD_DEG; - _metalEnvironment->_currentProjectionMatrix = toSimdMatrix4D(context.projectionMatrix); + _metalEnvironment->_currentProjectionMatrix = toSimdMatrix4D(context.nearClippedProjMatrix); _metalEnvironment->_currentZoomLevel = context.zoomLevel; _metalEnvironment->_currentCommandEncoder = self.renderEncoder; _metalEnvironment->_currentCommandBuffer = resource.commandBuffer; _metalEnvironment->_metalDevice = resource.mtkView.device; _metalEnvironment->_currentDrawable = resource.mtkView.currentDrawable; _metalEnvironment->_currentRenderPassDescriptor = resource.mtkView.currentRenderPassDescriptor; + _metalEnvironment->_depthStencilTexture = resource.mtkView.currentRenderPassDescriptor.depthAttachment.texture; + _metalEnvironment->_colorTexture = resource.mtkView.currentRenderPassDescriptor.colorAttachments[0].texture; + if (self.lightSet) { _metalEnvironment->_lightDirection = simd_make_float3(_lightX, _lightY, _lightZ); } - + // TODO: Remove this.. This is legacy _manager->setRenderingEnvironmentVariables(_metalEnvironment); diff --git a/platform/darwin/src/gltf/MetalRenderer.mm b/platform/darwin/src/gltf/MetalRenderer.mm index bef2b4356ec8..da659aec2674 100644 --- a/platform/darwin/src/gltf/MetalRenderer.mm +++ b/platform/darwin/src/gltf/MetalRenderer.mm @@ -259,20 +259,20 @@ MTLRenderPassDescriptor *pass = [MTLRenderPassDescriptor renderPassDescriptor]; if (_sampleCount > 1) { pass.colorAttachments[0].texture = _multisampleColorTexture; - pass.colorAttachments[0].resolveTexture = _colorTexture; - pass.colorAttachments[0].loadAction = MTLLoadActionClear; + pass.colorAttachments[0].resolveTexture = _metalRenderingEnvironment->_colorTexture; + pass.colorAttachments[0].loadAction = MTLLoadActionLoad; pass.colorAttachments[0].storeAction = MTLStoreActionMultisampleResolve; pass.colorAttachments[0].clearColor = MTLClearColorMake(1, 0, 0, 0); } else { - pass.colorAttachments[0].texture = _colorTexture; - pass.colorAttachments[0].loadAction = MTLLoadActionClear; + pass.colorAttachments[0].texture = _metalRenderingEnvironment->_colorTexture; + pass.colorAttachments[0].loadAction = MTLLoadActionLoad; pass.colorAttachments[0].storeAction = MTLStoreActionStore; pass.colorAttachments[0].clearColor = MTLClearColorMake(1, 0, 0, 0); } - pass.depthAttachment.texture = _depthStencilTexture; - pass.depthAttachment.loadAction = MTLLoadActionClear; - pass.depthAttachment.storeAction = MTLStoreActionDontCare; + pass.depthAttachment.texture = _metalRenderingEnvironment->_depthStencilTexture; + pass.depthAttachment.loadAction = MTLLoadActionLoad; + pass.depthAttachment.storeAction = MTLStoreActionStore; return pass; } From 021baf3ac35527291359c5dc19935568f8e371c1 Mon Sep 17 00:00:00 2001 From: Yousif Date: Mon, 20 Jan 2025 15:20:34 +0300 Subject: [PATCH 027/221] fix upload artifact name file name duplication Add platform name to pr-number upload artifact action to avoid duplicate names after upgrading to v4 of the upload artifact github action --- .github/actions/get-pr-number/action.yml | 6 +++++- .github/actions/save-pr-number/action.yml | 7 +++++-- .github/workflows/android-ci.yml | 2 ++ .github/workflows/android-device-test.yml | 2 ++ .github/workflows/ios-ci.yml | 2 ++ .github/workflows/linux-ci.yml | 2 ++ .github/workflows/pr-bloaty-ios.yml | 2 ++ .github/workflows/pr-linux-tests.yml | 4 ++++ 8 files changed, 24 insertions(+), 3 deletions(-) diff --git a/.github/actions/get-pr-number/action.yml b/.github/actions/get-pr-number/action.yml index d75aba3a125c..8f687cec227a 100644 --- a/.github/actions/get-pr-number/action.yml +++ b/.github/actions/get-pr-number/action.yml @@ -1,5 +1,9 @@ name: 'get-pr-number' description: 'Gets the PR number from an artifact' +inputs: + platform-name: + description: "Name of the target platform" + required: true outputs: pr-number: description: "PR number or empty string" @@ -9,7 +13,7 @@ runs: steps: - uses: ./.github/actions/download-workflow-run-artifact with: - artifact-name: pr-number + artifact-name: pr-number-${{ inputs.platform-name }} - run: touch ./pr_number shell: bash diff --git a/.github/actions/save-pr-number/action.yml b/.github/actions/save-pr-number/action.yml index bcb94fed3fac..2ae0de1f14a1 100644 --- a/.github/actions/save-pr-number/action.yml +++ b/.github/actions/save-pr-number/action.yml @@ -1,5 +1,9 @@ name: 'save-pr-number' description: 'Saves the current PR number as artifact' +inputs: + platform-name: + description: "Name of the target platform" + required: true runs: using: "composite" steps: @@ -12,6 +16,5 @@ runs: - name: Upload pr_number uses: actions/upload-artifact@v4 with: - name: pr-number + name: pr-number-${{ inputs.platform-name }} path: ./pr_number - overwrite: true diff --git a/.github/workflows/android-ci.yml b/.github/workflows/android-ci.yml index c121ca7bc01d..4121c7388926 100644 --- a/.github/workflows/android-ci.yml +++ b/.github/workflows/android-ci.yml @@ -184,6 +184,8 @@ jobs: - if: github.event_name == 'pull_request' uses: ./.github/actions/save-pr-number + with: + platform-name: "android" - name: Build Instrumentation Tests, copy to platform/android run: | diff --git a/.github/workflows/android-device-test.yml b/.github/workflows/android-device-test.yml index 93c516bb6ae3..3e85fcb2d740 100644 --- a/.github/workflows/android-device-test.yml +++ b/.github/workflows/android-device-test.yml @@ -84,6 +84,8 @@ jobs: - uses: ./.github/actions/get-pr-number id: get-pr-number + with: + platform-name: "android" - name: Generate token id: generate_token diff --git a/.github/workflows/ios-ci.yml b/.github/workflows/ios-ci.yml index 374054c8b993..7559ad6ec16b 100644 --- a/.github/workflows/ios-ci.yml +++ b/.github/workflows/ios-ci.yml @@ -193,6 +193,8 @@ jobs: - if: github.event_name == 'pull_request' uses: ./.github/actions/save-pr-number + with: + platform-name: "ios" - name: Build DocC documentation working-directory: . diff --git a/.github/workflows/linux-ci.yml b/.github/workflows/linux-ci.yml index 4b888d5d947d..f3066e7e29ff 100644 --- a/.github/workflows/linux-ci.yml +++ b/.github/workflows/linux-ci.yml @@ -178,6 +178,8 @@ jobs: - if: github.event_name == 'pull_request' uses: ./.github/actions/save-pr-number + with: + platform-name: "linux-${{ matrix.renderer }}" linux-coverage: runs-on: ubuntu-22.04 diff --git a/.github/workflows/pr-bloaty-ios.yml b/.github/workflows/pr-bloaty-ios.yml index 314df2ce1684..6b3b2747b6e9 100644 --- a/.github/workflows/pr-bloaty-ios.yml +++ b/.github/workflows/pr-bloaty-ios.yml @@ -63,6 +63,8 @@ jobs: - uses: ./.github/actions/get-pr-number id: get-pr-number + with: + platform-name: "ios" - uses: ./.github/actions/download-workflow-run-artifact with: diff --git a/.github/workflows/pr-linux-tests.yml b/.github/workflows/pr-linux-tests.yml index c4dc2ee95984..fbf2b0d57b5d 100644 --- a/.github/workflows/pr-linux-tests.yml +++ b/.github/workflows/pr-linux-tests.yml @@ -37,6 +37,8 @@ jobs: - uses: ./.github/actions/get-pr-number id: get-pr-number + with: + platform-name: "linux-vulkan" - uses: ./.github/actions/download-workflow-run-artifact with: @@ -134,6 +136,8 @@ jobs: - uses: ./.github/actions/get-pr-number id: get-pr-number + with: + platform-name: "linux-vulkan" - uses: ./.github/actions/download-workflow-run-artifact with: From 7cf8bd837e33361320de54f9c06d08ce8d0d58c1 Mon Sep 17 00:00:00 2001 From: Yousif Date: Tue, 21 Jan 2025 10:16:30 +0300 Subject: [PATCH 028/221] revert changing GLTFRenderer.cpp to GLTFRenderer.mm --- platform/darwin/bazel/files.bzl | 2 +- platform/darwin/src/gltf/{GLTFRenderer.mm => GLTFRenderer.cpp} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename platform/darwin/src/gltf/{GLTFRenderer.mm => GLTFRenderer.cpp} (100%) diff --git a/platform/darwin/bazel/files.bzl b/platform/darwin/bazel/files.bzl index 3e11397755d2..f18243fceb4d 100644 --- a/platform/darwin/bazel/files.bzl +++ b/platform/darwin/bazel/files.bzl @@ -24,7 +24,7 @@ MLN_GLTF_SOURCE = [ "src/gltf/GLTFMTLRenderItem.h", "src/gltf/GLTFMTLRenderItem.m", "src/gltf/GLTFRenderer.hpp", - "src/gltf/GLTFRenderer.mm", + "src/gltf/GLTFRenderer.cpp", "src/gltf/MetalRenderer+GLTFAsset.mm", "src/gltf/gltfkit/GLTFAsset.h", "src/gltf/gltfkit/GLTFAsset.m", diff --git a/platform/darwin/src/gltf/GLTFRenderer.mm b/platform/darwin/src/gltf/GLTFRenderer.cpp similarity index 100% rename from platform/darwin/src/gltf/GLTFRenderer.mm rename to platform/darwin/src/gltf/GLTFRenderer.cpp From 371c1aacb32a5bb567b540bbe77896b27ce45e9a Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 22 Jan 2025 19:01:58 +0300 Subject: [PATCH 029/221] disable updating framebuffer size since they aren't used atm --- platform/darwin/src/gltf/MetalRenderer.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/darwin/src/gltf/MetalRenderer.mm b/platform/darwin/src/gltf/MetalRenderer.mm index da659aec2674..4139258e5608 100644 --- a/platform/darwin/src/gltf/MetalRenderer.mm +++ b/platform/darwin/src/gltf/MetalRenderer.mm @@ -41,7 +41,7 @@ return; } _drawableSize = {width, height}; - updateFramebufferSize(); + // updateFramebufferSize(); } // Set the current drawable From 8629fe282c4a17037ca2d9649746e69812b01694 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 23 Jan 2025 13:30:20 +0300 Subject: [PATCH 030/221] increase version to 6.8.2 --- platform/ios/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/VERSION b/platform/ios/VERSION index f867e299309d..166d79d6d6f9 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.12.2 +6.8.2 From fb2a07075e0a0bd341c79d34cc91989b1350f338 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Sun, 26 Jan 2025 16:03:34 +0300 Subject: [PATCH 031/221] increment version for release --- platform/ios/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/VERSION b/platform/ios/VERSION index 166d79d6d6f9..021c9405b1d8 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.8.2 +6.8.3 From 9dfccadb7601c26820a55c86a6e22a93e9bf71b7 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 29 Jan 2025 09:51:37 +0300 Subject: [PATCH 032/221] add clear depth buffer pass after rendering gltf models This is necessary to avoid breaking other layers that depend on the depth buffer for layer sorting. We need to be careful about how we order the layers going forward --- platform/darwin/src/gltf/MetalRenderer.hpp | 388 ++++++++++----------- platform/darwin/src/gltf/MetalRenderer.mm | 56 ++- 2 files changed, 247 insertions(+), 197 deletions(-) diff --git a/platform/darwin/src/gltf/MetalRenderer.hpp b/platform/darwin/src/gltf/MetalRenderer.hpp index 1e90c154fc8b..4dae0c37c19e 100644 --- a/platform/darwin/src/gltf/MetalRenderer.hpp +++ b/platform/darwin/src/gltf/MetalRenderer.hpp @@ -22,209 +22,207 @@ #include #include -namespace maplibre { namespace gltf { +namespace maplibre { +namespace gltf { - class GLTFRenderModel { - public: - // The model metadata - std::shared_ptr _gltfModel = nullptr; - - // The loaded model - GLTFAsset *_asset = nil; - - // Rendering variables - // Translation Vector is the translation of the model from the - simd_float3 _translationVector; // This might need to be a doubles vector - double _rotationDeg = 0; // Rotation around the zAxis (if applicable) - double _scaling = 1; // Scaling from - float _brightness = 1.0; // Brightness +class GLTFRenderModel { +public: + // The model metadata + std::shared_ptr _gltfModel = nullptr; - // This is the model matrix (rotation, scaling and transformation applied) - simd_double4x4 _modelMatrix; + // The loaded model + GLTFAsset *_asset = nil; - // This is the model matrix combined with the camera's view matrix - simd_double4x4 _modelViewMatrix; + // Rendering variables + // Translation Vector is the translation of the model from the + simd_float3 _translationVector; // This might need to be a doubles vector + double _rotationDeg = 0; // Rotation around the zAxis (if applicable) + double _scaling = 1; // Scaling from + float _brightness = 1.0; // Brightness - // We probably won't need this in the final thing. Used to normalize the model to the - // viewport size - simd_double4x4 _regularizationMatrix; - - // - GLTFBoundingSphere _boundingSphere; + // This is the model matrix (rotation, scaling and transformation applied) + simd_double4x4 _modelMatrix; - }; + // This is the model matrix combined with the camera's view matrix + simd_double4x4 _modelViewMatrix; + // We probably won't need this in the final thing. Used to normalize the model to the + // viewport size + simd_double4x4 _regularizationMatrix; + // + GLTFBoundingSphere _boundingSphere; +}; + +// +class MetalRenderer : public GLTFRenderer { +public: + // Constructor + MetalRenderer(); + ~MetalRenderer(); + + void setMetalDevice(id device); + + // Set the drawable size + void setDrawableSize(int width, int height) override; + + // Set the current drawable (used for a metal view) + // void setCurrentDrawable(id drawable); + + // Set the output render pass descriptor (this is for outputting to a metal view) + // void setCurrentOutputRenderPassDescriptor(MTLRenderPassDescriptor *renderPassDescriptor); + + // Update any animations + void update(float timeSinceLastDraw) override; + + // Render + void render() override; + + // Load a model + void loadGLTFModel(std::shared_ptr model) override; + + // Set the rendering environemnt variables + void setRenderingEnvironemnt(std::shared_ptr renderingEnvironment) override; + +private: + // Rendering environment variables + simd_double4x4 _projectionMatrix; + int _sampleCount = 1; + MTLPixelFormat _colorPixelFormat; + MTLPixelFormat _depthStencilPixelFormat; + simd_int2 _drawableSize; + double _globalTime = 0; + int _maxInflightFrames = 3; + + // Current external environment variables + std::shared_ptr _metalRenderingEnvironment = nullptr; + + // id _currentDrawable = nullptr; + // MTLRenderPassDescriptor *_currentOutputRenderPassDescriptor = nullptr; + + dispatch_semaphore_t _frameBoundarySemaphore; + + void encodeMainPass(id commandBuffer); + void encodeBloomPasses(id commandBuffer); + void encodeTonemappingPass(id commandBuffer); + void drawFullscreenPassWithPipeline(id renderPipelineState, + id renderCommandEncoder, + id sourceTexture); + void signalFrameCompletion(); + MTLRenderPassDescriptor *newRenderPassDescriptor(); + +private: + // Per-frame + void computeTransforms(std::shared_ptr model); + +protected: + void loadBloomPipelines() override; + void loadTonemapPipeline() override; + void updateFramebufferSize() override; // Updates the framebuffers based on size + +private: + // Set by the environment + id _metalDevice = nullptr; + + // Created for rendering the model + id _internalMetalCommandQueue = nullptr; + id _metalLibrary = nullptr; + + // Setup the rendering environment. Called after device is set + void setupMetal(); + + // Bloom + id _bloomThresholdPipelineState = nullptr; + id _blurHorizontalPipelineState = nullptr; + id _blurVerticalPipelineState = nullptr; + id _additiveBlendPipelineState = nullptr; + + // Tonemap + id _tonemapPipelineState = nullptr; + + // Render targets + id _multisampleColorTexture = nullptr; + id _colorTexture = nullptr; + id _depthStencilTexture = nullptr; + id _bloomTextureA = nullptr; + id _bloomTextureB = nullptr; + + // Depth Clear + id _depthStencilClearState = nullptr; + id _pipelineDepthClearState = nullptr; + + void loadDepthClearPipeline(); + void clearDepth(id); + +public: + // Encapsulated in GLTFRenderer+GLTFAsset + void setGLTFAsset(GLTFAsset *asset, std::shared_ptr model); + + // + void addGLTFAsset(GLTFAsset *asset, std::shared_ptr model); + + // + id _bufferAllocator; + +private: + std::shared_ptr createRenderModel(GLTFAsset *asset, std::shared_ptr model); + + std::vector> _models; + // GLTFAsset *_asset = nil; + // NSMutableArray *_assets = nil; // - class MetalRenderer : public GLTFRenderer { - public: - // Constructor - MetalRenderer(); - ~MetalRenderer(); - - void setMetalDevice(id device); - - // Set the drawable size - void setDrawableSize(int width, int height) override; - - // Set the current drawable (used for a metal view) - //void setCurrentDrawable(id drawable); - - // Set the output render pass descriptor (this is for outputting to a metal view) - //void setCurrentOutputRenderPassDescriptor(MTLRenderPassDescriptor *renderPassDescriptor); - - // Update any animations - void update(float timeSinceLastDraw) override; - - // Render - void render() override; - - // Load a model - void loadGLTFModel(std::shared_ptr model) override; - - // Set the rendering environemnt variables - void setRenderingEnvironemnt(std::shared_ptr renderingEnvironment) override; - - private: - // Rendering environment variables - simd_double4x4 _projectionMatrix; - int _sampleCount = 1; - MTLPixelFormat _colorPixelFormat; - MTLPixelFormat _depthStencilPixelFormat; - simd_int2 _drawableSize; - double _globalTime = 0; - int _maxInflightFrames = 3; - - // Current external environment variables - std::shared_ptr _metalRenderingEnvironment = nullptr; - - //id _currentDrawable = nullptr; - //MTLRenderPassDescriptor *_currentOutputRenderPassDescriptor = nullptr; - - dispatch_semaphore_t _frameBoundarySemaphore; - - void encodeMainPass(id commandBuffer); - void encodeBloomPasses(id commandBuffer); - void encodeTonemappingPass(id commandBuffer); - void drawFullscreenPassWithPipeline(id renderPipelineState, - id renderCommandEncoder, - id sourceTexture); - void signalFrameCompletion(); - MTLRenderPassDescriptor* newRenderPassDescriptor(); - - private: - // Per-frame - void computeTransforms(std::shared_ptr model); - - protected: - void loadBloomPipelines() override; - void loadTonemapPipeline() override; - void updateFramebufferSize() override; // Updates the framebuffers based on size - - private: - // Set by the environment - id _metalDevice = nullptr; - - // Created for rendering the model - id _internalMetalCommandQueue = nullptr; - id _metalLibrary = nullptr; - - - // Setup the rendering environment. Called after device is set - void setupMetal(); - - // Bloom - id _bloomThresholdPipelineState = nullptr; - id _blurHorizontalPipelineState = nullptr; - id _blurVerticalPipelineState = nullptr; - id _additiveBlendPipelineState = nullptr; - - // Tonemap - id _tonemapPipelineState = nullptr; - - // Render targets - id _multisampleColorTexture = nullptr; - id _colorTexture = nullptr; - id _depthStencilTexture = nullptr; - id _bloomTextureA = nullptr; - id _bloomTextureB = nullptr; - - public: - // Encapsulated in GLTFRenderer+GLTFAsset - void setGLTFAsset(GLTFAsset *asset, std::shared_ptr model); - - // - void addGLTFAsset(GLTFAsset *asset, std::shared_ptr model); - - // - id _bufferAllocator; - - private: - std::shared_ptr createRenderModel(GLTFAsset *asset, std::shared_ptr model); - - std::vector> _models; -// GLTFAsset *_asset = nil; -// NSMutableArray *_assets = nil; - - // - void computeRegularizationMatrix(std::shared_ptr model); - void addDefaultLights(std::shared_ptr model); - - void renderScene(std::shared_ptr model, - GLTFScene *scene, - id commandBuffer, - id renderEncoder); - - void buildLightListRecursive(GLTFNode *node); - - void buildRenderListRecursive(std::shared_ptr model, - GLTFNode *node, - simd_float4x4 modelMatrix, - GLTFKHRLight *defaultAmbientLight); - - void drawRenderList(NSArray *renderList, - id renderEncoder); - - id renderPipelineStateForSubmesh(GLTFSubmesh *submesh); - - void bindTexturesForMaterial(GLTFMaterial *material, - id renderEncoder); - - id dequeueReusableBufferOfLength(size_t length); - - void computeJointsForSubmesh(GLTFSubmesh *submesh, - GLTFNode *node, - id jointBuffer); - - id depthStencilStateForDepthWriteEnabled(bool depthWriteEnabled, - bool depthTestEnabled, - MTLCompareFunction compareFunction); - - id textureForImage(GLTFImage *image, bool sRGB); - id samplerStateForSampler(GLTFTextureSampler *sampler); - - NSMutableArray *_opaqueRenderItems; - NSMutableArray *_transparentRenderItems; - NSMutableArray *_currentLightNodes; - NSMutableArray> *_deferredReusableBuffers; - NSMutableArray> *_bufferPool; - NSMutableDictionary> *_depthStencilStateMap; - - NSMutableDictionary> *_pipelineStatesForSubmeshes; - NSMutableDictionary> *_texturesForImageIdentifiers; - GLTFMTLTextureLoader *_textureLoader; - NSMutableDictionary> *_samplerStatesForSamplers; - - void enqueueReusableBuffer(id buffer); - - - // This is the depth stencil descriptor for overlaying the - id _fullscreenTransfterDepthStencilState = nullptr; - - - }; - -}} + void computeRegularizationMatrix(std::shared_ptr model); + void addDefaultLights(std::shared_ptr model); + + void renderScene(std::shared_ptr model, + GLTFScene *scene, + id commandBuffer, + id renderEncoder); + + void buildLightListRecursive(GLTFNode *node); + + void buildRenderListRecursive(std::shared_ptr model, + GLTFNode *node, + simd_float4x4 modelMatrix, + GLTFKHRLight *defaultAmbientLight); + + void drawRenderList(NSArray *renderList, id renderEncoder); + + id renderPipelineStateForSubmesh(GLTFSubmesh *submesh); + + void bindTexturesForMaterial(GLTFMaterial *material, id renderEncoder); + + id dequeueReusableBufferOfLength(size_t length); + + void computeJointsForSubmesh(GLTFSubmesh *submesh, GLTFNode *node, id jointBuffer); + + id depthStencilStateForDepthWriteEnabled(bool depthWriteEnabled, + bool depthTestEnabled, + MTLCompareFunction compareFunction); + + id textureForImage(GLTFImage *image, bool sRGB); + id samplerStateForSampler(GLTFTextureSampler *sampler); + + NSMutableArray *_opaqueRenderItems; + NSMutableArray *_transparentRenderItems; + NSMutableArray *_currentLightNodes; + NSMutableArray> *_deferredReusableBuffers; + NSMutableArray> *_bufferPool; + NSMutableDictionary> *_depthStencilStateMap; + + NSMutableDictionary> *_pipelineStatesForSubmeshes; + NSMutableDictionary> *_texturesForImageIdentifiers; + GLTFMTLTextureLoader *_textureLoader; + NSMutableDictionary> *_samplerStatesForSamplers; + + void enqueueReusableBuffer(id buffer); + + // This is the depth stencil descriptor for overlaying the + id _fullscreenTransfterDepthStencilState = nullptr; +}; + +} // namespace gltf +} // namespace maplibre #endif /* MetalRenderer_hpp */ diff --git a/platform/darwin/src/gltf/MetalRenderer.mm b/platform/darwin/src/gltf/MetalRenderer.mm index 4139258e5608..9e19202129ff 100644 --- a/platform/darwin/src/gltf/MetalRenderer.mm +++ b/platform/darwin/src/gltf/MetalRenderer.mm @@ -132,9 +132,8 @@ // This will write out the tone mapping //id externalBuffer = _metalRenderingEnvironment->_currentCommandBuffer; //encodeTonemappingPass(externalBuffer); - - // Internal command buffer + clearDepth(_metalRenderingEnvironment->_currentCommandEncoder); } // Load a model @@ -299,6 +298,7 @@ loadBloomPipelines(); loadTonemapPipeline(); + loadDepthClearPipeline(); _opaqueRenderItems = [NSMutableArray array]; _transparentRenderItems = [NSMutableArray array]; @@ -468,6 +468,58 @@ } } +void MetalRenderer::loadDepthClearPipeline() { + MTLDepthStencilDescriptor *depthStencilDescriptor = [[MTLDepthStencilDescriptor alloc] init]; + + depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways; + depthStencilDescriptor.depthWriteEnabled = YES; + depthStencilDescriptor.label = @"depthStencilClear"; + _depthStencilClearState = [_metalDevice newDepthStencilStateWithDescriptor:depthStencilDescriptor]; + + MTLRenderPipelineDescriptor *renderPipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; + + renderPipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; + renderPipelineDescriptor.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; + renderPipelineDescriptor.stencilAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; + renderPipelineDescriptor.rasterSampleCount = _sampleCount; + + renderPipelineDescriptor.vertexFunction = [_metalLibrary newFunctionWithName:@"vertex_depth_clear"]; + renderPipelineDescriptor.vertexFunction.label = @"vertexDepthClear"; + + renderPipelineDescriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"fragment_depth_clear"]; + renderPipelineDescriptor.fragmentFunction.label = @"fragmentDepthClear"; + + MTLVertexDescriptor *vertexDescriptor = [[MTLVertexDescriptor alloc] init]; + vertexDescriptor.attributes[0].format = MTLVertexFormatFloat2; + vertexDescriptor.attributes[0].offset = 0; + vertexDescriptor.attributes[0].bufferIndex = 0; + vertexDescriptor.layouts[0].stepRate = 1; + vertexDescriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex; + vertexDescriptor.layouts[0].stride = 8; + + renderPipelineDescriptor.vertexDescriptor = vertexDescriptor; + + NSError* error = NULL; + renderPipelineDescriptor.label = @"pipelineDepthClear"; + _pipelineDepthClearState = [_metalDevice newRenderPipelineStateWithDescriptor:renderPipelineDescriptor error:&error]; +} + +void MetalRenderer::clearDepth(id renderEncoder) { + [renderEncoder setDepthStencilState:_depthStencilClearState]; + [renderEncoder setRenderPipelineState:_pipelineDepthClearState]; + + const float clearCoords[8] = { + -1, -1, + 1, -1, + -1, 1, + 1, 1 + }; + + [renderEncoder setVertexBytes:clearCoords length:sizeof(float) * 8 atIndex:0]; + [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4]; + +} + void MetalRenderer::enqueueReusableBuffer(id buffer) { [_bufferPool addObject:buffer]; } From 058bc9b7e07a345673e5d586b108209cc5c14cc6 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 29 Jan 2025 10:06:46 +0300 Subject: [PATCH 033/221] increase version for new release --- platform/ios/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/VERSION b/platform/ios/VERSION index 021c9405b1d8..9ffc8cfb6caa 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.8.3 +6.8.4 From 73ddbc75c0d9b70f9bbd0bcf75a6defb05dd330a Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Mon, 10 Feb 2025 16:43:44 +0300 Subject: [PATCH 034/221] reset depth stencil state for render pass Because the depth stencil state of the render pass is no reset correctly after the custom layer is drawn we need to manually do this to ensure that we don't write to the depth or stencil buffers when we shouldn't --- platform/darwin/src/gltf/MetalRenderer.mm | 2 -- 1 file changed, 2 deletions(-) diff --git a/platform/darwin/src/gltf/MetalRenderer.mm b/platform/darwin/src/gltf/MetalRenderer.mm index 9e19202129ff..295035cc0acf 100644 --- a/platform/darwin/src/gltf/MetalRenderer.mm +++ b/platform/darwin/src/gltf/MetalRenderer.mm @@ -132,8 +132,6 @@ // This will write out the tone mapping //id externalBuffer = _metalRenderingEnvironment->_currentCommandBuffer; //encodeTonemappingPass(externalBuffer); - - clearDepth(_metalRenderingEnvironment->_currentCommandEncoder); } // Load a model From 2ca8302bb0634ee8044c12083b4b2042fa79e628 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Tue, 11 Feb 2025 10:59:37 +0300 Subject: [PATCH 035/221] fix upload artifact action with overwrite flag --- .github/actions/get-pr-number/action.yml | 6 +----- .github/actions/save-pr-number/action.yml | 7 ++----- .github/workflows/android-ci.yml | 2 -- .github/workflows/android-device-test.yml | 2 -- .github/workflows/ios-ci.yml | 2 -- .github/workflows/linux-ci.yml | 2 -- .github/workflows/pr-bloaty-ios.yml | 2 -- .github/workflows/pr-linux-tests.yml | 4 ---- 8 files changed, 3 insertions(+), 24 deletions(-) diff --git a/.github/actions/get-pr-number/action.yml b/.github/actions/get-pr-number/action.yml index 8f687cec227a..d75aba3a125c 100644 --- a/.github/actions/get-pr-number/action.yml +++ b/.github/actions/get-pr-number/action.yml @@ -1,9 +1,5 @@ name: 'get-pr-number' description: 'Gets the PR number from an artifact' -inputs: - platform-name: - description: "Name of the target platform" - required: true outputs: pr-number: description: "PR number or empty string" @@ -13,7 +9,7 @@ runs: steps: - uses: ./.github/actions/download-workflow-run-artifact with: - artifact-name: pr-number-${{ inputs.platform-name }} + artifact-name: pr-number - run: touch ./pr_number shell: bash diff --git a/.github/actions/save-pr-number/action.yml b/.github/actions/save-pr-number/action.yml index 2ae0de1f14a1..bcb94fed3fac 100644 --- a/.github/actions/save-pr-number/action.yml +++ b/.github/actions/save-pr-number/action.yml @@ -1,9 +1,5 @@ name: 'save-pr-number' description: 'Saves the current PR number as artifact' -inputs: - platform-name: - description: "Name of the target platform" - required: true runs: using: "composite" steps: @@ -16,5 +12,6 @@ runs: - name: Upload pr_number uses: actions/upload-artifact@v4 with: - name: pr-number-${{ inputs.platform-name }} + name: pr-number path: ./pr_number + overwrite: true diff --git a/.github/workflows/android-ci.yml b/.github/workflows/android-ci.yml index 4121c7388926..c121ca7bc01d 100644 --- a/.github/workflows/android-ci.yml +++ b/.github/workflows/android-ci.yml @@ -184,8 +184,6 @@ jobs: - if: github.event_name == 'pull_request' uses: ./.github/actions/save-pr-number - with: - platform-name: "android" - name: Build Instrumentation Tests, copy to platform/android run: | diff --git a/.github/workflows/android-device-test.yml b/.github/workflows/android-device-test.yml index 3e85fcb2d740..93c516bb6ae3 100644 --- a/.github/workflows/android-device-test.yml +++ b/.github/workflows/android-device-test.yml @@ -84,8 +84,6 @@ jobs: - uses: ./.github/actions/get-pr-number id: get-pr-number - with: - platform-name: "android" - name: Generate token id: generate_token diff --git a/.github/workflows/ios-ci.yml b/.github/workflows/ios-ci.yml index 7559ad6ec16b..374054c8b993 100644 --- a/.github/workflows/ios-ci.yml +++ b/.github/workflows/ios-ci.yml @@ -193,8 +193,6 @@ jobs: - if: github.event_name == 'pull_request' uses: ./.github/actions/save-pr-number - with: - platform-name: "ios" - name: Build DocC documentation working-directory: . diff --git a/.github/workflows/linux-ci.yml b/.github/workflows/linux-ci.yml index f3066e7e29ff..4b888d5d947d 100644 --- a/.github/workflows/linux-ci.yml +++ b/.github/workflows/linux-ci.yml @@ -178,8 +178,6 @@ jobs: - if: github.event_name == 'pull_request' uses: ./.github/actions/save-pr-number - with: - platform-name: "linux-${{ matrix.renderer }}" linux-coverage: runs-on: ubuntu-22.04 diff --git a/.github/workflows/pr-bloaty-ios.yml b/.github/workflows/pr-bloaty-ios.yml index 6b3b2747b6e9..314df2ce1684 100644 --- a/.github/workflows/pr-bloaty-ios.yml +++ b/.github/workflows/pr-bloaty-ios.yml @@ -63,8 +63,6 @@ jobs: - uses: ./.github/actions/get-pr-number id: get-pr-number - with: - platform-name: "ios" - uses: ./.github/actions/download-workflow-run-artifact with: diff --git a/.github/workflows/pr-linux-tests.yml b/.github/workflows/pr-linux-tests.yml index fbf2b0d57b5d..c4dc2ee95984 100644 --- a/.github/workflows/pr-linux-tests.yml +++ b/.github/workflows/pr-linux-tests.yml @@ -37,8 +37,6 @@ jobs: - uses: ./.github/actions/get-pr-number id: get-pr-number - with: - platform-name: "linux-vulkan" - uses: ./.github/actions/download-workflow-run-artifact with: @@ -136,8 +134,6 @@ jobs: - uses: ./.github/actions/get-pr-number id: get-pr-number - with: - platform-name: "linux-vulkan" - uses: ./.github/actions/download-workflow-run-artifact with: From c82f7c0e42dd834677109005c731f6451998af5c Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Tue, 11 Feb 2025 11:00:27 +0300 Subject: [PATCH 036/221] enable iOS tests --- .github/workflows/ios-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ios-ci.yml b/.github/workflows/ios-ci.yml index 374054c8b993..299ccd801197 100644 --- a/.github/workflows/ios-ci.yml +++ b/.github/workflows/ios-ci.yml @@ -92,8 +92,8 @@ jobs: - name: Lint plist files run: bazel run //platform/ios:lint-plists --//:renderer=metal - # - name: Running iOS tests - # run: bazel test //platform/ios/test:ios_test --test_output=errors --//:renderer=metal + - name: Running iOS tests + run: bazel test //platform/ios/test:ios_test --test_output=errors --//:renderer=metal # tsan run fails with 'Interceptors are not working. This may be because ThreadSanitizer is loaded too late...' #- name: Running iOS UI tests (Thread Sanitizer) From 78d7638c54e7bf68ccaa48eb608592b66463dd4e Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Tue, 11 Feb 2025 11:02:58 +0300 Subject: [PATCH 037/221] apply clang-tidy on gltf code --- platform/darwin/src/gltf/Camera.cpp | 22 +- platform/darwin/src/gltf/Camera.hpp | 8 +- platform/darwin/src/gltf/GLTFMTLRenderItem.h | 5 +- platform/darwin/src/gltf/GLTFManager.hpp | 171 +++++++------- .../gltf/GLTFManagerRenderingEnvironment.hpp | 41 ++-- .../GLTFManagerRenderingEnvironmentMetal.hpp | 47 ++-- platform/darwin/src/gltf/GLTFMath.cpp | 147 +++++------- platform/darwin/src/gltf/GLTFMath.hpp | 20 +- platform/darwin/src/gltf/GLTFModel.hpp | 62 ++--- platform/darwin/src/gltf/GLTFModelLayer.h | 16 +- platform/darwin/src/gltf/GLTFModelLoader.h | 7 +- platform/darwin/src/gltf/GLTFRenderer.cpp | 19 +- platform/darwin/src/gltf/GLTFRenderer.hpp | 103 ++++----- .../darwin/src/gltf/gltfkit/GLTFAccessor.h | 6 +- .../darwin/src/gltf/gltfkit/GLTFAnimation.h | 2 +- platform/darwin/src/gltf/gltfkit/GLTFAsset.h | 24 +- .../darwin/src/gltf/gltfkit/GLTFBinaryChunk.h | 10 +- platform/darwin/src/gltf/gltfkit/GLTFBuffer.h | 3 +- .../darwin/src/gltf/gltfkit/GLTFBufferView.h | 2 +- platform/darwin/src/gltf/gltfkit/GLTFCamera.h | 10 +- platform/darwin/src/gltf/gltfkit/GLTFEnums.h | 214 +++++++++--------- platform/darwin/src/gltf/gltfkit/GLTFImage.h | 8 +- .../darwin/src/gltf/gltfkit/GLTFKHRLight.h | 8 +- .../src/gltf/gltfkit/GLTFMTLBufferAllocator.h | 8 +- .../src/gltf/gltfkit/GLTFMTLShaderBuilder.h | 13 +- .../src/gltf/gltfkit/GLTFMTLTextureLoader.h | 9 +- .../src/gltf/gltfkit/GLTFMTLUtilities.h | 7 +- .../darwin/src/gltf/gltfkit/GLTFMaterial.h | 30 +-- platform/darwin/src/gltf/gltfkit/GLTFMesh.h | 2 +- platform/darwin/src/gltf/gltfkit/GLTFNode.h | 20 +- .../darwin/src/gltf/gltfkit/GLTFNodeVisitor.h | 4 +- platform/darwin/src/gltf/gltfkit/GLTFObject.h | 4 +- platform/darwin/src/gltf/gltfkit/GLTFScene.h | 4 +- .../darwin/src/gltf/gltfkit/GLTFTexture.h | 9 +- .../src/gltf/gltfkit/GLTFTextureSampler.h | 2 +- .../darwin/src/gltf/gltfkit/GLTFUtilities.h | 17 +- .../src/gltf/gltfkit/GLTFVertexDescriptor.h | 2 +- .../layers/custom_layer_render_parameters.cpp | 2 +- 38 files changed, 521 insertions(+), 567 deletions(-) diff --git a/platform/darwin/src/gltf/Camera.cpp b/platform/darwin/src/gltf/Camera.cpp index d716830ac504..6dc63dced2f3 100644 --- a/platform/darwin/src/gltf/Camera.cpp +++ b/platform/darwin/src/gltf/Camera.cpp @@ -20,43 +20,35 @@ Camera::Camera() { _rotationVelocity = 0; _velocity = 0; _distance = 4; // 0; // 2; - } simd_double4x4 Camera::projectionMatrix() { - float fov = M_PI / 3; // original + float fov = M_PI / 3; // original fov = 0.6435011087932844; // Constant that i found in ML simd_double4x4 matrix = GLTFPerspectiveProjectionMatrixAspectFovRH(fov, 1.0, 0.01, 250); return matrix; } void Camera::updateWithTimestep(double timestep) { - - _rotationAngles += _rotationVelocity * timestep; static double rot = 0; // rot += 0.03; -// self.rotationAngles = rot; -// _rotationAngles = simd_make_float3(rot, M_PI/4.0, 0); + // self.rotationAngles = rot; + // _rotationAngles = simd_make_float3(rot, M_PI/4.0, 0); _rotationAngles = simd_make_float3(rot, 0, 0); - // Clamp pitch - _rotationAngles = (simd_float3){ _rotationAngles.x, - static_cast(fmax(-M_PI_2, fmin(_rotationAngles.y, M_PI_2))), - 0 }; - + _rotationAngles = (simd_float3){ + _rotationAngles.x, static_cast(fmax(-M_PI_2, fmin(_rotationAngles.y, M_PI_2))), 0}; _rotationVelocity *= GLTFViewerOrbitCameraRotationDrag; // _distance += _velocity * timestep; _velocity *= GLTFViewerOrbitCameraZoomDrag; - + simd_double4x4 pitchRotation = GLTFRotationMatrixFromAxisAngleD(GLTFAxisXD, -_rotationAngles.y); simd_double4x4 yawRotation = GLTFRotationMatrixFromAxisAngleD(GLTFAxisYD, -_rotationAngles.x); - simd_double4x4 translation = GLTFMatrixFromTranslationD((simd_double3){ 0, 0, _distance }); + simd_double4x4 translation = GLTFMatrixFromTranslationD((simd_double3){0, 0, _distance}); _viewMatrix = matrix_invert(matrix_multiply(matrix_multiply(yawRotation, pitchRotation), translation)); - - } diff --git a/platform/darwin/src/gltf/Camera.hpp b/platform/darwin/src/gltf/Camera.hpp index 05ebba2f6e84..89f760c7e035 100644 --- a/platform/darwin/src/gltf/Camera.hpp +++ b/platform/darwin/src/gltf/Camera.hpp @@ -11,7 +11,8 @@ #include #include -namespace maplibre { namespace gltf { +namespace maplibre { +namespace gltf { class Camera { public: @@ -23,10 +24,9 @@ class Camera { simd_double4x4 projectionMatrix(); simd_double4x4 _viewMatrix; void updateWithTimestep(double timestep); - }; -}} - +} // namespace gltf +} // namespace maplibre #endif /* Camera_hpp */ diff --git a/platform/darwin/src/gltf/GLTFMTLRenderItem.h b/platform/darwin/src/gltf/GLTFMTLRenderItem.h index 4b9cc968b0d0..68b0753b1a67 100644 --- a/platform/darwin/src/gltf/GLTFMTLRenderItem.h +++ b/platform/darwin/src/gltf/GLTFMTLRenderItem.h @@ -6,13 +6,12 @@ // #import -#import "gltfkit/GLTFNode.h" #import "gltfkit/GLTFMesh.h" +#import "gltfkit/GLTFNode.h" NS_ASSUME_NONNULL_BEGIN - -@interface GLTFMTLRenderItem: NSObject +@interface GLTFMTLRenderItem : NSObject @property (nonatomic) NSString *label; @property (nonatomic) GLTFNode *node; @property (nonatomic, strong) GLTFSubmesh *submesh; diff --git a/platform/darwin/src/gltf/GLTFManager.hpp b/platform/darwin/src/gltf/GLTFManager.hpp index fcd1061e8ddd..9fce472cb1e2 100644 --- a/platform/darwin/src/gltf/GLTFManager.hpp +++ b/platform/darwin/src/gltf/GLTFManager.hpp @@ -17,91 +17,90 @@ #include "GLTFModel.hpp" #include "GLTFManagerRenderingEnvironment.hpp" -namespace maplibre { namespace gltf { - - // The type of rendering environment we're in - typedef enum { - RenderingEnvironmentUnknown, - RenderingEnvironmentMetal, - RenderingEnvironmentOpenGL, - RenderingEnvironmentVulkan - } RenderingEnvironment; - - struct Coordinate2D { - double _lat; - double _lon; - }; - - struct Cartesian3D { - double _x; - double _y; - double _z; - }; - - - typedef std::function ProjectionCallback; - - // The GLTF Manager class is the top level entry point - // for all things model based - class GLTFManager { - public: - // Set the callback - void setProjectionCallback(ProjectionCallback projectionCallback); - - // Instantiate the manager with the appropriate environment - GLTFManager(RenderingEnvironment renderingEnvironment); - - // Load a model - void addModel(std::shared_ptr model); - - // Remove a model - void removeModel(std::shared_ptr model); - - // Current meter to screen pixel scale - double _metersPerPixel = 1.0; - - // Set the drawable size - void setDrawableSize(int width, int height); - - // Set the tilt deg - void setTiltDeg(double tiltDeg); - - // Set the rotation deg - void setRotationDeg(double rotationDeg); - - // Set the rendering environment variables - void setRenderingEnvironmentVariables(std::shared_ptr environmentVars); - - // Update any animations - void updateScene(float timeSinceLastDraw); - - // Render - void render(); - - private: - RenderingEnvironment _renderingEnvironment = RenderingEnvironmentUnknown; - - // List of models - std::vector> _models; - - // Projection callback - ProjectionCallback _projectionCallback; - - private: - // Rendering environment - void createRenderingEnvironment(); - - // The renderer - std::shared_ptr _renderer = nullptr; - - - int _drawableWidth = 1; - int _drawableHeight = 1; - double _tiltDeg = 0; - double _rotationDeg = 0; - - }; - -}} +namespace maplibre { +namespace gltf { + +// The type of rendering environment we're in +typedef enum { + RenderingEnvironmentUnknown, + RenderingEnvironmentMetal, + RenderingEnvironmentOpenGL, + RenderingEnvironmentVulkan +} RenderingEnvironment; + +struct Coordinate2D { + double _lat; + double _lon; +}; + +struct Cartesian3D { + double _x; + double _y; + double _z; +}; + +typedef std::function ProjectionCallback; + +// The GLTF Manager class is the top level entry point +// for all things model based +class GLTFManager { +public: + // Set the callback + void setProjectionCallback(ProjectionCallback projectionCallback); + + // Instantiate the manager with the appropriate environment + GLTFManager(RenderingEnvironment renderingEnvironment); + + // Load a model + void addModel(std::shared_ptr model); + + // Remove a model + void removeModel(std::shared_ptr model); + + // Current meter to screen pixel scale + double _metersPerPixel = 1.0; + + // Set the drawable size + void setDrawableSize(int width, int height); + + // Set the tilt deg + void setTiltDeg(double tiltDeg); + + // Set the rotation deg + void setRotationDeg(double rotationDeg); + + // Set the rendering environment variables + void setRenderingEnvironmentVariables(std::shared_ptr environmentVars); + + // Update any animations + void updateScene(float timeSinceLastDraw); + + // Render + void render(); + +private: + RenderingEnvironment _renderingEnvironment = RenderingEnvironmentUnknown; + + // List of models + std::vector> _models; + + // Projection callback + ProjectionCallback _projectionCallback; + +private: + // Rendering environment + void createRenderingEnvironment(); + + // The renderer + std::shared_ptr _renderer = nullptr; + + int _drawableWidth = 1; + int _drawableHeight = 1; + double _tiltDeg = 0; + double _rotationDeg = 0; +}; + +} // namespace gltf +} // namespace maplibre #endif /* GLTFManager_hpp */ diff --git a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp index 0be4b4046486..1e37c11260ce 100644 --- a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp +++ b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp @@ -11,31 +11,30 @@ #include #include -namespace maplibre { namespace gltf { +namespace maplibre { +namespace gltf { - // Bsae class does nothing really, just a place holder - class GLTFManagerRenderingEnvironment { - public: - // If the bloom should be used - bool _useBloomPass = false; +// Bsae class does nothing really, just a place holder +class GLTFManagerRenderingEnvironment { +public: + // If the bloom should be used + bool _useBloomPass = false; - // FOV - double _currentFOVDEG = 50; - - // Environment projection matrix - simd_double4x4 _currentProjectionMatrix; - - // Current zoom level - double _currentZoomLevel = 1; + // FOV + double _currentFOVDEG = 50; - // - simd_float3 _lightDirection; + // Environment projection matrix + simd_double4x4 _currentProjectionMatrix; - GLTFManagerRenderingEnvironment() { - _lightDirection = simd_make_float3(0.0, 10000.0, 10000.0); - } + // Current zoom level + double _currentZoomLevel = 1; - }; + // + simd_float3 _lightDirection; -}} + GLTFManagerRenderingEnvironment() { _lightDirection = simd_make_float3(0.0, 10000.0, 10000.0); } +}; + +} // namespace gltf +} // namespace maplibre #endif /* GLTFManagerRenderingEnvironment_hpp */ diff --git a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp index ba73b24973e0..b64b422bf6bd 100644 --- a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp +++ b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp @@ -13,28 +13,29 @@ #include #include "GLTFManagerRenderingEnvironment.hpp" -namespace maplibre { namespace gltf { - - // Bsae class does nothing really, just a place holder - class GLTFManagerRenderingEnvironmentMetal: public GLTFManagerRenderingEnvironment { - public: - // Allows command buffer and render encoder to be passed in. - // if these are nil, then the renderer will create them - id _currentCommandEncoder = nullptr; - id _currentCommandBuffer = nullptr; - - id _currentDrawable = nullptr; - MTLRenderPassDescriptor *_currentRenderPassDescriptor = nullptr; - id _metalDevice = nullptr; - - // TBD: These are placeholders as we noodle how to integrate with ML - // Depth descriptor: If this is null, then use an internal depth - id _depthStencilTexture = nullptr; - - id _colorTexture = nullptr; - }; - -}} - +namespace maplibre { +namespace gltf { + +// Bsae class does nothing really, just a place holder +class GLTFManagerRenderingEnvironmentMetal : public GLTFManagerRenderingEnvironment { +public: + // Allows command buffer and render encoder to be passed in. + // if these are nil, then the renderer will create them + id _currentCommandEncoder = nullptr; + id _currentCommandBuffer = nullptr; + + id _currentDrawable = nullptr; + MTLRenderPassDescriptor *_currentRenderPassDescriptor = nullptr; + id _metalDevice = nullptr; + + // TBD: These are placeholders as we noodle how to integrate with ML + // Depth descriptor: If this is null, then use an internal depth + id _depthStencilTexture = nullptr; + + id _colorTexture = nullptr; +}; + +} // namespace gltf +} // namespace maplibre #endif /* GLTFManagerRenderingEnvironmentMetal_hpp */ diff --git a/platform/darwin/src/gltf/GLTFMath.cpp b/platform/darwin/src/gltf/GLTFMath.cpp index 97f5821e9035..8a067505ef5d 100644 --- a/platform/darwin/src/gltf/GLTFMath.cpp +++ b/platform/darwin/src/gltf/GLTFMath.cpp @@ -7,7 +7,6 @@ #include "GLTFMath.hpp" - simd_float4x4 GLTFMatrixFromScale(const simd_float3 s) { simd_float4x4 m = matrix_identity_float4x4; m.columns[0].x = s.x; @@ -24,7 +23,6 @@ simd_double4x4 GLTFMatrixFromScaleD(const simd_double3 s) { return m; } - simd_float4x4 GLTFMatrixFromUniformScale(float s) { simd_float4x4 m = matrix_identity_float4x4; m.columns[0].x = s; @@ -41,17 +39,15 @@ simd_double4x4 GLTFMatrixFromUniformScaleD(double s) { return m; } - simd_double4x4 GLTFMatrixFromTranslationD(simd_double3 t) { simd_double4x4 m = matrix_identity_double4x4; - m.columns[3] = (simd_double4) { t.x, t.y, t.z, 1.0 }; + m.columns[3] = (simd_double4){t.x, t.y, t.z, 1.0}; return m; } - simd_float4x4 GLTFMatrixFromTranslation(simd_float3 t) { simd_float4x4 m = matrix_identity_float4x4; - m.columns[3] = (simd_float4) { t.x, t.y, t.z, 1.0 }; + m.columns[3] = (simd_float4){t.x, t.y, t.z, 1.0}; return m; } @@ -60,10 +56,10 @@ GLTFBoundingSphere GLTFBoundingSphereFromBox(const GLTFBoundingBox b) { double midX = (b.maxPoint.x + b.minPoint.x) * 0.5; double midY = (b.maxPoint.y + b.minPoint.y) * 0.5; double midZ = (b.maxPoint.z + b.minPoint.z) * 0.5; - + double r = sqrt(pow(b.maxPoint.x - midX, 2) + pow(b.maxPoint.y - midY, 2) + pow(b.maxPoint.z - midZ, 2)); - - s.center = (simd_double3){ midX, midY, midZ }; + + s.center = (simd_double3){midX, midY, midZ}; s.radius = r; return s; } @@ -73,13 +69,13 @@ simd_float4x4 GLTFRotationMatrixFromAxisAngle(simd_float3 axis, float angle) { float c = cosf(angle); float s = sinf(angle); float t = 1 - c; - - simd_float4 c0 = { t * x * x + c, t * x * y + z * s, t * x * z - y * s, 0 }; - simd_float4 c1 = { t * x * y - z * s, t * y * y + c, t * y * z + x * s, 0 }; - simd_float4 c2 = { t * x * z + y * s, t * y * z - x * s, t * z * z + c, 0 }; - simd_float4 c3 = { 0, 0, 0, 1 }; - - return (simd_float4x4){ c0, c1, c2, c3 }; + + simd_float4 c0 = {t * x * x + c, t * x * y + z * s, t * x * z - y * s, 0}; + simd_float4 c1 = {t * x * y - z * s, t * y * y + c, t * y * z + x * s, 0}; + simd_float4 c2 = {t * x * z + y * s, t * y * z - x * s, t * z * z + c, 0}; + simd_float4 c3 = {0, 0, 0, 1}; + + return (simd_float4x4){c0, c1, c2, c3}; } simd_double4x4 GLTFRotationMatrixFromAxisAngleD(simd_double3 axis, double angle) { @@ -87,83 +83,68 @@ simd_double4x4 GLTFRotationMatrixFromAxisAngleD(simd_double3 axis, double angle) double c = cos(angle); double s = sin(angle); double t = 1 - c; - - simd_double4 c0 = { t * x * x + c, t * x * y + z * s, t * x * z - y * s, 0 }; - simd_double4 c1 = { t * x * y - z * s, t * y * y + c, t * y * z + x * s, 0 }; - simd_double4 c2 = { t * x * z + y * s, t * y * z - x * s, t * z * z + c, 0 }; - simd_double4 c3 = { 0, 0, 0, 1 }; - - return (simd_double4x4){ c0, c1, c2, c3 }; -} + simd_double4 c0 = {t * x * x + c, t * x * y + z * s, t * x * z - y * s, 0}; + simd_double4 c1 = {t * x * y - z * s, t * y * y + c, t * y * z + x * s, 0}; + simd_double4 c2 = {t * x * z + y * s, t * y * z - x * s, t * z * z + c, 0}; + simd_double4 c3 = {0, 0, 0, 1}; -simd_float3 GLTFAxisX = (simd_float3){ 1, 0, 0 }; -simd_float3 GLTFAxisY = (simd_float3){ 0, 1, 0 }; -simd_float3 GLTFAxisZ = (simd_float3){ 0, 0, 1 }; + return (simd_double4x4){c0, c1, c2, c3}; +} -simd_double3 GLTFAxisXD = (simd_double3){ 1, 0, 0 }; -simd_double3 GLTFAxisYD = (simd_double3){ 0, 1, 0 }; -simd_double3 GLTFAxisZD = (simd_double3){ 0, 0, 1 }; +simd_float3 GLTFAxisX = (simd_float3){1, 0, 0}; +simd_float3 GLTFAxisY = (simd_float3){0, 1, 0}; +simd_float3 GLTFAxisZ = (simd_float3){0, 0, 1}; -simd_double4x4 GLTFPerspectiveProjectionMatrixAspectFovRH(const double fovY, const double aspect, const double nearZ, const double farZ) -{ +simd_double3 GLTFAxisXD = (simd_double3){1, 0, 0}; +simd_double3 GLTFAxisYD = (simd_double3){0, 1, 0}; +simd_double3 GLTFAxisZD = (simd_double3){0, 0, 1}; + +simd_double4x4 GLTFPerspectiveProjectionMatrixAspectFovRH(const double fovY, + const double aspect, + const double nearZ, + const double farZ) { double yscale = 1 / tanf(fovY * 0.5f); // 1 / tan == cot double xscale = yscale / aspect; double q = -farZ / (farZ - nearZ); - - simd_double4x4 m = { - .columns[0] = { xscale, 0, 0, 0 }, - .columns[1] = { 0, yscale, 0, 0 }, - .columns[2] = { 0, 0, q, -1 }, - .columns[3] = { 0, 0, q * nearZ, 0 } - }; - + + simd_double4x4 m = {.columns[0] = {xscale, 0, 0, 0}, + .columns[1] = {0, yscale, 0, 0}, + .columns[2] = {0, 0, q, -1}, + .columns[3] = {0, 0, q * nearZ, 0}}; + return m; } - -simd_float4x4 GLTFOrthoProjectionMatrix(const float left, - const float right, - const float bottom, - const float top, - const float nearZ, - const float farZ) { - +simd_float4x4 GLTFOrthoProjectionMatrix( + const float left, const float right, const float bottom, const float top, const float nearZ, const float farZ) { simd_float4x4 m = { - .columns[0] = { 2 / (right - left), 0, 0, 0 }, - .columns[1] = { 0, 2 / (top - bottom), 0, 0 }, - .columns[2] = { 0, 0, 1 / (farZ - nearZ), 0 }, - .columns[3] = { (left + right) / (left - right), (top + bottom) / (bottom - top), nearZ / (nearZ - farZ), 1 } - }; - + .columns[0] = {2 / (right - left), 0, 0, 0}, + .columns[1] = {0, 2 / (top - bottom), 0, 0}, + .columns[2] = {0, 0, 1 / (farZ - nearZ), 0}, + .columns[3] = {(left + right) / (left - right), (top + bottom) / (bottom - top), nearZ / (nearZ - farZ), 1}}; + return m; - } - simd_float3x3 GLTFMatrixUpperLeft3x3(simd_float4x4 m) { - simd_float3x3 mout = { { - { m.columns[0][0], m.columns[0][1], m.columns[0][2] }, - { m.columns[1][0], m.columns[1][1], m.columns[1][2] }, - { m.columns[2][0], m.columns[2][1], m.columns[2][2] } - } }; + simd_float3x3 mout = {{{m.columns[0][0], m.columns[0][1], m.columns[0][2]}, + {m.columns[1][0], m.columns[1][1], m.columns[1][2]}, + {m.columns[2][0], m.columns[2][1], m.columns[2][2]}}}; return mout; } simd_double3x3 GLTFMatrixUpperLeft3x3D(simd_double4x4 m) { - simd_double3x3 mout = { { - { m.columns[0][0], m.columns[0][1], m.columns[0][2] }, - { m.columns[1][0], m.columns[1][1], m.columns[1][2] }, - { m.columns[2][0], m.columns[2][1], m.columns[2][2] } - } }; + simd_double3x3 mout = {{{m.columns[0][0], m.columns[0][1], m.columns[0][2]}, + {m.columns[1][0], m.columns[1][1], m.columns[1][2]}, + {m.columns[2][0], m.columns[2][1], m.columns[2][2]}}}; return mout; } - GLTFTextureTransform GLTFTextureTransformMakeIdentity(void) { GLTFTextureTransform t = { - .offset = (simd_float2){ 0, 0 }, - .scale = (simd_float2){ 1, 1 }, + .offset = (simd_float2){0, 0}, + .scale = (simd_float2){1, 1}, .rotation = 0, }; return t; @@ -185,31 +166,27 @@ simd_float3x3 GLTFTextureMatrixFromTransform(GLTFTextureTransform transform) { float ty = transform.offset.y; float sx = transform.scale.x; float sy = transform.scale.y; - simd_float3 c0 = (simd_float3){ rc * sx, rs * sy, 0 }; - simd_float3 c1 = (simd_float3){ -rs * sx, rc * sy, 0 }; - simd_float3 c2 = (simd_float3){ tx, ty, 1 }; - simd_float3x3 m = (simd_float3x3){ c0, c1, c2 }; + simd_float3 c0 = (simd_float3){rc * sx, rs * sy, 0}; + simd_float3 c1 = (simd_float3){-rs * sx, rc * sy, 0}; + simd_float3 c2 = (simd_float3){tx, ty, 1}; + simd_float3x3 m = (simd_float3x3){c0, c1, c2}; return m; } simd_float4x4 GLTFNormalMatrixFromModelMatrix(simd_float4x4 m) { simd_float3x3 nm = simd_inverse(simd_transpose(GLTFMatrixUpperLeft3x3(m))); - simd_float4x4 mout = { { - { nm.columns[0][0], nm.columns[0][1], nm.columns[0][2], 0 }, - { nm.columns[1][0], nm.columns[1][1], nm.columns[1][2], 0 }, - { nm.columns[2][0], nm.columns[2][1], nm.columns[2][2], 0 }, - { 0, 0, 0, 1 } - } }; + simd_float4x4 mout = {{{nm.columns[0][0], nm.columns[0][1], nm.columns[0][2], 0}, + {nm.columns[1][0], nm.columns[1][1], nm.columns[1][2], 0}, + {nm.columns[2][0], nm.columns[2][1], nm.columns[2][2], 0}, + {0, 0, 0, 1}}}; return mout; } simd_double4x4 GLTFNormalMatrixFromModelMatrixD(simd_double4x4 m) { simd_double3x3 nm = simd_inverse(simd_transpose(GLTFMatrixUpperLeft3x3D(m))); - simd_double4x4 mout = { { - { nm.columns[0][0], nm.columns[0][1], nm.columns[0][2], 0 }, - { nm.columns[1][0], nm.columns[1][1], nm.columns[1][2], 0 }, - { nm.columns[2][0], nm.columns[2][1], nm.columns[2][2], 0 }, - { 0, 0, 0, 1 } - } }; + simd_double4x4 mout = {{{nm.columns[0][0], nm.columns[0][1], nm.columns[0][2], 0}, + {nm.columns[1][0], nm.columns[1][1], nm.columns[1][2], 0}, + {nm.columns[2][0], nm.columns[2][1], nm.columns[2][2], 0}, + {0, 0, 0, 1}}}; return mout; } diff --git a/platform/darwin/src/gltf/GLTFMath.hpp b/platform/darwin/src/gltf/GLTFMath.hpp index eae5a828c560..6e8ce7a4f397 100644 --- a/platform/darwin/src/gltf/GLTFMath.hpp +++ b/platform/darwin/src/gltf/GLTFMath.hpp @@ -22,8 +22,8 @@ typedef enum { GLTFTextureBindIndexBRDFLookup, } GLTFMTLTextureBindIndex; -#define DEG_RAD (M_PI/180.0) -#define RAD_DEG (180.0/M_PI) +#define DEG_RAD (M_PI / 180.0) +#define RAD_DEG (180.0 / M_PI) // 0.0174533 // 57.2958 @@ -31,7 +31,6 @@ typedef enum { #define GLTFMTLMaximumLightCount 3 #define GLTFMTLMaximumTextureCount (GLTFTextureBindIndexEmissive + 1) - typedef struct { simd_float3 minPoint; simd_float3 maxPoint; @@ -42,7 +41,6 @@ typedef struct { float radius; } GLTFBoundingSphere; - typedef struct { simd_float4x4 modelMatrix; simd_float4x4 modelViewProjectionMatrix; @@ -112,14 +110,13 @@ simd_float4x4 GLTFRotationMatrixFromAxisAngle(simd_float3 axis, float angle); simd_double4x4 GLTFRotationMatrixFromAxisAngleD(simd_double3 axis, double angle); -simd_double4x4 GLTFPerspectiveProjectionMatrixAspectFovRH(const double fovY, const double aspect, const double nearZ, const double farZ); +simd_double4x4 GLTFPerspectiveProjectionMatrixAspectFovRH(const double fovY, + const double aspect, + const double nearZ, + const double farZ); -simd_float4x4 GLTFOrthoProjectionMatrix(const float left, - const float right, - const float bottom, - const float top, - const float nearZ, - const float farZ); +simd_float4x4 GLTFOrthoProjectionMatrix( + const float left, const float right, const float bottom, const float top, const float nearZ, const float farZ); simd_float3x3 GLTFMatrixUpperLeft3x3(simd_float4x4 m); @@ -135,7 +132,6 @@ simd_float4x4 GLTFNormalMatrixFromModelMatrix(simd_float4x4 m); simd_double4x4 GLTFNormalMatrixFromModelMatrixD(simd_double4x4 m); - #ifdef __cplusplus } #endif diff --git a/platform/darwin/src/gltf/GLTFModel.hpp b/platform/darwin/src/gltf/GLTFModel.hpp index a09e05b56e5b..174b7dd91ee3 100644 --- a/platform/darwin/src/gltf/GLTFModel.hpp +++ b/platform/darwin/src/gltf/GLTFModel.hpp @@ -11,36 +11,36 @@ #include #include -namespace maplibre { namespace gltf { - - // Model - class GLTFModel { - public: - // - double _referenceLat = 0; - double _referenceLon = 0; - - // What it takes to scale this model to meters units - float _scaleFactor = 1; - - // Rotation around the reference point - float _rotationDeg = 0; - - // The URL for the model, used by the loader - std::string _modelURL; - - // The brightness - float _brightness = 1.0; - - // This is a hack to deal with passing in the translation vector. - // NEed to reconcile this with the renderable model's version of it - double _xLateX = 0; - double _xLateY = 0; - double _xLateZ = 0; - - }; - - -}} +namespace maplibre { +namespace gltf { + +// Model +class GLTFModel { +public: + // + double _referenceLat = 0; + double _referenceLon = 0; + + // What it takes to scale this model to meters units + float _scaleFactor = 1; + + // Rotation around the reference point + float _rotationDeg = 0; + + // The URL for the model, used by the loader + std::string _modelURL; + + // The brightness + float _brightness = 1.0; + + // This is a hack to deal with passing in the translation vector. + // NEed to reconcile this with the renderable model's version of it + double _xLateX = 0; + double _xLateY = 0; + double _xLateZ = 0; +}; + +} // namespace gltf +} // namespace maplibre #endif /* GLTFModel_hpp */ diff --git a/platform/darwin/src/gltf/GLTFModelLayer.h b/platform/darwin/src/gltf/GLTFModelLayer.h index d9715474eb86..640f37355659 100644 --- a/platform/darwin/src/gltf/GLTFModelLayer.h +++ b/platform/darwin/src/gltf/GLTFModelLayer.h @@ -13,16 +13,16 @@ NS_ASSUME_NONNULL_BEGIN // This sets the relative light position for all the models being rendered // The light position is in meters from the origin of the model. --(void)setLightPositionX:(float)x y:(float)y z:(float)z; +- (void)setLightPositionX:(float)x y:(float)y z:(float)z; --(void)loadModelFromJSON:(NSString *)modelMetadataFilename; +- (void)loadModelFromJSON:(NSString *)modelMetadataFilename; --(void)loadModel:(NSString *)appResourceFilename - lat:(double)lat - lon:(double)lon - rotationDeg:(double)rotationDeg - scaleFactor:(float)scaleFactor - brightness:(float)brightness; +- (void)loadModel:(NSString *)appResourceFilename + lat:(double)lat + lon:(double)lon + rotationDeg:(double)rotationDeg + scaleFactor:(float)scaleFactor + brightness:(float)brightness; @end diff --git a/platform/darwin/src/gltf/GLTFModelLoader.h b/platform/darwin/src/gltf/GLTFModelLoader.h index 6cf1b928b989..d1e3ab9d7874 100644 --- a/platform/darwin/src/gltf/GLTFModelLoader.h +++ b/platform/darwin/src/gltf/GLTFModelLoader.h @@ -14,10 +14,9 @@ typedef void (^GLTFModelLoaderCompletionHandler)(GLTFAsset *asset); @interface GLTFModelLoader : NSObject --(void)loadURL:(NSURL *)assetURL -withCompletionHandler:(GLTFModelLoaderCompletionHandler)completionHandler -bufferAllocator:(id)bufferAllocator; - +- (void)loadURL:(NSURL *)assetURL + withCompletionHandler:(GLTFModelLoaderCompletionHandler)completionHandler + bufferAllocator:(id)bufferAllocator; @end diff --git a/platform/darwin/src/gltf/GLTFRenderer.cpp b/platform/darwin/src/gltf/GLTFRenderer.cpp index 86fc66be865d..c308e566f32d 100644 --- a/platform/darwin/src/gltf/GLTFRenderer.cpp +++ b/platform/darwin/src/gltf/GLTFRenderer.cpp @@ -18,14 +18,13 @@ GLTFRenderer::~GLTFRenderer() { // Base class does nothing } - // Update any animations void GLTFRenderer::update(float timeSinceLastDraw) { // Base class does nothing } // Render - void GLTFRenderer::render() { +void GLTFRenderer::render() { // Base class does nothing } @@ -35,18 +34,11 @@ void GLTFRenderer::setDrawableSize(int width, int height) { } // Protected items -void GLTFRenderer::loadBloomPipelines() { - -} - -void GLTFRenderer::loadTonemapPipeline() { - -} +void GLTFRenderer::loadBloomPipelines() {} -void GLTFRenderer::updateFramebufferSize() { - -} +void GLTFRenderer::loadTonemapPipeline() {} +void GLTFRenderer::updateFramebufferSize() {} // Load a model void GLTFRenderer::loadGLTFModel(std::shared_ptr model) { @@ -68,14 +60,11 @@ void GLTFRenderer::setRotationDeg(double rotationDeg) { _rotationDeg = rotationDeg; } - - // Use bloom pass void GLTFRenderer::setUseBloomPass(bool useBloomPass) { _useBloomPass = useBloomPass; } - // Set the rendering environemnt variables void GLTFRenderer::setRenderingEnvironemnt(std::shared_ptr renderingEnvironment) { _renderingEnvironment = renderingEnvironment; diff --git a/platform/darwin/src/gltf/GLTFRenderer.hpp b/platform/darwin/src/gltf/GLTFRenderer.hpp index 22d52ad0722e..dba305678e60 100644 --- a/platform/darwin/src/gltf/GLTFRenderer.hpp +++ b/platform/darwin/src/gltf/GLTFRenderer.hpp @@ -14,56 +14,57 @@ #include "GLTFManagerRenderingEnvironment.hpp" #include -namespace maplibre { namespace gltf { - - class GLTFRenderer { - public: - // Constructor - GLTFRenderer(); - - // Destructor - virtual ~GLTFRenderer(); - - // Update any animations - virtual void update(float timeSinceLastDraw); - - // Render - virtual void render(); - - // Set the drawable size - virtual void setDrawableSize(int width, int height); - - // Load a model - virtual void loadGLTFModel(std::shared_ptr model); - - // Set the meters per pixel scale - void setMetersPerPixel(double metersPerPixel); - - // Set tilt - void setTiltDeg(double tiltDeg); - - // Set the rotation deg - void setRotationDeg(double rotationDeg); - - // Use bloom pass - void setUseBloomPass(bool useBloomPass); - - // Set the rendering environemnt variables - virtual void setRenderingEnvironemnt(std::shared_ptr renderingEnvironment); - - protected: - std::unique_ptr _camera = nullptr; - double _metersPerPixel = 1; - std::shared_ptr _renderingEnvironment = nullptr; - double _tiltDeg = 0; - double _rotationDeg = 0; - bool _useBloomPass = true; - virtual void loadBloomPipelines(); - virtual void loadTonemapPipeline(); - virtual void updateFramebufferSize(); - - }; - -}} +namespace maplibre { +namespace gltf { + +class GLTFRenderer { +public: + // Constructor + GLTFRenderer(); + + // Destructor + virtual ~GLTFRenderer(); + + // Update any animations + virtual void update(float timeSinceLastDraw); + + // Render + virtual void render(); + + // Set the drawable size + virtual void setDrawableSize(int width, int height); + + // Load a model + virtual void loadGLTFModel(std::shared_ptr model); + + // Set the meters per pixel scale + void setMetersPerPixel(double metersPerPixel); + + // Set tilt + void setTiltDeg(double tiltDeg); + + // Set the rotation deg + void setRotationDeg(double rotationDeg); + + // Use bloom pass + void setUseBloomPass(bool useBloomPass); + + // Set the rendering environemnt variables + virtual void setRenderingEnvironemnt(std::shared_ptr renderingEnvironment); + +protected: + std::unique_ptr _camera = nullptr; + double _metersPerPixel = 1; + std::shared_ptr _renderingEnvironment = nullptr; + double _tiltDeg = 0; + double _rotationDeg = 0; + bool _useBloomPass = true; + virtual void loadBloomPipelines(); + virtual void loadTonemapPipeline(); + virtual void updateFramebufferSize(); +}; + +} // namespace gltf +} // namespace maplibre #endif /* GLTFRenderer_hpp */ diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAccessor.h b/platform/darwin/src/gltf/gltfkit/GLTFAccessor.h index 4414b8ab58fe..e5bdf0d2f77c 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFAccessor.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFAccessor.h @@ -14,8 +14,8 @@ // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // -#import "GLTFObject.h" #import "GLTFEnums.h" +#import "GLTFObject.h" #import @@ -24,8 +24,8 @@ NS_ASSUME_NONNULL_BEGIN @class GLTFBufferView; typedef struct { - float minValue[16]; - float maxValue[16]; + float minValue[16]; + float maxValue[16]; } GLTFValueRange; @interface GLTFAccessor : GLTFObject diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAnimation.h b/platform/darwin/src/gltf/gltfkit/GLTFAnimation.h index b70ab091a024..e00693e578f3 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFAnimation.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFAnimation.h @@ -14,8 +14,8 @@ // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // -#import "GLTFObject.h" #import "GLTFEnums.h" +#import "GLTFObject.h" NS_ASSUME_NONNULL_BEGIN diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAsset.h b/platform/darwin/src/gltf/gltfkit/GLTFAsset.h index 2f883a685bd1..bbd795d35a70 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFAsset.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFAsset.h @@ -16,8 +16,8 @@ #import -#import "GLTFObject.h" #import "GLTFEnums.h" +#import "GLTFObject.h" NS_ASSUME_NONNULL_BEGIN @@ -27,7 +27,9 @@ NS_ASSUME_NONNULL_BEGIN @protocol GLTFBufferAllocator; @protocol GLTFAssetLoadingDelegate -- (void)assetWithURL:(NSURL *)assetURL requiresContentsOfURL:(NSURL *)url completionHandler:(void (^)(NSData *_Nullable, NSError *_Nullable))completionHandler; +- (void)assetWithURL:(NSURL *)assetURL + requiresContentsOfURL:(NSURL *)url + completionHandler:(void (^)(NSData *_Nullable, NSError *_Nullable))completionHandler; - (void)assetWithURL:(NSURL *)assetURL didFinishLoading:(GLTFAsset *)asset; - (void)assetWithURL:(NSURL *)assetURL didFailToLoadWithError:(NSError *)error; @end @@ -35,7 +37,7 @@ NS_ASSUME_NONNULL_BEGIN @interface GLTFAsset : NSObject @property (nonatomic, readonly, strong) NSArray *scenes; -@property (nonatomic, readonly) GLTFScene * _Nullable defaultScene; +@property (nonatomic, readonly) GLTFScene *_Nullable defaultScene; @property (nonatomic, readonly, strong) NSArray *animations; @@ -43,16 +45,18 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly, strong) NSArray *cameras; -@property (nonatomic, copy) NSString * _Nullable generator; -@property (nonatomic, copy) NSString * _Nullable copyright; -@property (nonatomic, copy) NSString * _Nullable formatVersion; +@property (nonatomic, copy) NSString *_Nullable generator; +@property (nonatomic, copy) NSString *_Nullable copyright; +@property (nonatomic, copy) NSString *_Nullable formatVersion; @property (nonatomic, copy) NSArray *extensionsUsed; -/// Load an asset asynchronously. The asset may either be a local asset or a remote asset; the provided -/// delegate will receive callbacks requesting the contents of remote URLs referenced by the asset. These -/// callbacks will occur on an arbitrary internal queue. -+ (void)loadAssetWithURL:(NSURL *)url bufferAllocator:(id)bufferAllocator delegate:(id)delegate; +/// Load an asset asynchronously. The asset may either be a local asset or a remote asset; the +/// provided delegate will receive callbacks requesting the contents of remote URLs referenced by +/// the asset. These callbacks will occur on an arbitrary internal queue. ++ (void)loadAssetWithURL:(NSURL *)url + bufferAllocator:(id)bufferAllocator + delegate:(id)delegate; /// Load a local asset. The provided URL must be a file URL, or else loading will fail. - (instancetype)initWithURL:(NSURL *)url bufferAllocator:(id)bufferAllocator; diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.h b/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.h index 593b8329f29d..cb4fd22591c4 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.h @@ -19,14 +19,14 @@ extern const UInt32 GLTFBinaryMagic; typedef NS_ENUM(NSInteger, GLTFChunkType) { - GLTFChunkTypeJSON = 0x4E4F534A, - GLTFChunkTypeBinary = 0x004E4942 + GLTFChunkTypeJSON = 0x4E4F534A, + GLTFChunkTypeBinary = 0x004E4942 }; typedef struct { - UInt32 magic; - UInt32 version; - UInt32 length; + UInt32 magic; + UInt32 version; + UInt32 length; } GLTFBinaryHeader; @interface GLTFBinaryChunk : NSObject diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBuffer.h b/platform/darwin/src/gltf/gltfkit/GLTFBuffer.h index 0be3d201b020..a91cd8fda245 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFBuffer.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFBuffer.h @@ -22,7 +22,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) NSInteger length; -/// The actual data associated with this buffer. If uri is a data URI, this is populated when loading; else it is nil +/// The actual data associated with this buffer. If uri is a data URI, this is populated when +/// loading; else it is nil @property (nonatomic, readonly) void *contents; @end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBufferView.h b/platform/darwin/src/gltf/gltfkit/GLTFBufferView.h index 2b41ec2f46c7..3f83f265f350 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFBufferView.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFBufferView.h @@ -14,8 +14,8 @@ // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // -#import "GLTFObject.h" #import "GLTFEnums.h" +#import "GLTFObject.h" NS_ASSUME_NONNULL_BEGIN diff --git a/platform/darwin/src/gltf/gltfkit/GLTFCamera.h b/platform/darwin/src/gltf/gltfkit/GLTFCamera.h index 2d710a7ffcb6..67d729b85c95 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFCamera.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFCamera.h @@ -14,8 +14,8 @@ // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // -#import "GLTFObject.h" #import "GLTFEnums.h" +#import "GLTFObject.h" #import @@ -26,10 +26,10 @@ NS_ASSUME_NONNULL_BEGIN @interface GLTFCamera : GLTFObject @property (nonatomic, assign) GLTFCameraType cameraType; -@property (nonatomic, assign) float aspectRatio; // Only applicable when type is perspective -@property (nonatomic, assign) float yfov; // Only applicable when type is perspective -@property (nonatomic, assign) float xmag; // Only applicable when type is orthographic -@property (nonatomic, assign) float ymag; // Only applicable when type is orthographic +@property (nonatomic, assign) float aspectRatio; // Only applicable when type is perspective +@property (nonatomic, assign) float yfov; // Only applicable when type is perspective +@property (nonatomic, assign) float xmag; // Only applicable when type is orthographic +@property (nonatomic, assign) float ymag; // Only applicable when type is orthographic @property (nonatomic, assign) float znear; @property (nonatomic, assign) float zfar; diff --git a/platform/darwin/src/gltf/gltfkit/GLTFEnums.h b/platform/darwin/src/gltf/gltfkit/GLTFEnums.h index dbf5177be5fb..76bffbc8779a 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFEnums.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFEnums.h @@ -17,162 +17,162 @@ #import typedef NS_ENUM(NSInteger, GLTFDataType) { - GLTFBaseTypeUnknown, - GLTFDataTypeChar = 0x1400, - GLTFDataTypeUChar = 0x1401, - GLTFDataTypeShort = 0x1402, - GLTFDataTypeUShort = 0x1403, - GLTFDataTypeInt = 0x1404, - GLTFDataTypeUInt = 0x1405, - GLTFDataTypeFloat = 0x1406, - - GLTFDataTypeFloat2 = 0x8B50, - GLTFDataTypeFloat3 = 0x8B51, - GLTFDataTypeFloat4 = 0x8B52, - GLTFDataTypeInt2 = 0x8B53, - GLTFDataTypeInt3 = 0x8B54, - GLTFDataTypeInt4 = 0x8B55, - GLTFDataTypeBool = 0x8B56, - GLTFDataTypeBool2 = 0x8B57, - GLTFDataTypeBool3 = 0x8B58, - GLTFDataTypeBool4 = 0x8B59, - GLTFDataTypeFloat2x2 = 0x8B5A, - GLTFDataTypeFloat3x3 = 0x8B5B, - GLTFDataTypeFloat4x4 = 0x8B5C, - GLTFDataTypeSampler2D = 0x8B5E, + GLTFBaseTypeUnknown, + GLTFDataTypeChar = 0x1400, + GLTFDataTypeUChar = 0x1401, + GLTFDataTypeShort = 0x1402, + GLTFDataTypeUShort = 0x1403, + GLTFDataTypeInt = 0x1404, + GLTFDataTypeUInt = 0x1405, + GLTFDataTypeFloat = 0x1406, + + GLTFDataTypeFloat2 = 0x8B50, + GLTFDataTypeFloat3 = 0x8B51, + GLTFDataTypeFloat4 = 0x8B52, + GLTFDataTypeInt2 = 0x8B53, + GLTFDataTypeInt3 = 0x8B54, + GLTFDataTypeInt4 = 0x8B55, + GLTFDataTypeBool = 0x8B56, + GLTFDataTypeBool2 = 0x8B57, + GLTFDataTypeBool3 = 0x8B58, + GLTFDataTypeBool4 = 0x8B59, + GLTFDataTypeFloat2x2 = 0x8B5A, + GLTFDataTypeFloat3x3 = 0x8B5B, + GLTFDataTypeFloat4x4 = 0x8B5C, + GLTFDataTypeSampler2D = 0x8B5E, }; typedef NS_ENUM(NSInteger, GLTFDataDimension) { - GLTFDataDimensionUnknown, - GLTFDataDimensionScalar, - GLTFDataDimensionVector2, - GLTFDataDimensionVector3, - GLTFDataDimensionVector4, - GLTFDataDimensionMatrix2x2, - GLTFDataDimensionMatrix3x3, - GLTFDataDimensionMatrix4x4, + GLTFDataDimensionUnknown, + GLTFDataDimensionScalar, + GLTFDataDimensionVector2, + GLTFDataDimensionVector3, + GLTFDataDimensionVector4, + GLTFDataDimensionMatrix2x2, + GLTFDataDimensionMatrix3x3, + GLTFDataDimensionMatrix4x4, }; typedef NS_ENUM(NSInteger, GLTFTarget) { - GLTFTargetUnknown, - GLTFTargetArrayBuffer = 0x8892, - GLTFTargetElementArrayBuffer = 0x8893, + GLTFTargetUnknown, + GLTFTargetArrayBuffer = 0x8892, + GLTFTargetElementArrayBuffer = 0x8893, }; typedef NS_ENUM(NSInteger, GLTFPrimitiveType) { - GLTFPrimitiveTypePoints, - GLTFPrimitiveTypeLines, - GLTFPrimitiveTypeLineLoop, - GLTFPrimitiveTypeLineStrip, - GLTFPrimitiveTypeTriangles, - GLTFPrimitiveTypeTriangleStrip, - GLTFPrimitiveTypeTriangleFan, + GLTFPrimitiveTypePoints, + GLTFPrimitiveTypeLines, + GLTFPrimitiveTypeLineLoop, + GLTFPrimitiveTypeLineStrip, + GLTFPrimitiveTypeTriangles, + GLTFPrimitiveTypeTriangleStrip, + GLTFPrimitiveTypeTriangleFan, }; typedef NS_ENUM(NSInteger, GLTFCameraType) { - GLTFCameraTypePerspective, - GLTFCameraTypeOrthographic, + GLTFCameraTypePerspective, + GLTFCameraTypeOrthographic, }; typedef NS_ENUM(NSInteger, GLTFTextureTarget) { - GLTFTextureTargetTexture2D = 0x0DE1, + GLTFTextureTargetTexture2D = 0x0DE1, }; typedef NS_ENUM(NSInteger, GLTFTextureFormat) { - GLTFTextureFormatUnknown, - GLTFTextureFormatAlpha = 0x1906, - GLTFTextureFormatRGB = 0x1907, - GLTFTextureFormatRGBA = 0x1908, - GLTFTextureFormatLuminance = 0x1909, - GLTFTextureFormatLuminanceAlpha = 0x190A, + GLTFTextureFormatUnknown, + GLTFTextureFormatAlpha = 0x1906, + GLTFTextureFormatRGB = 0x1907, + GLTFTextureFormatRGBA = 0x1908, + GLTFTextureFormatLuminance = 0x1909, + GLTFTextureFormatLuminanceAlpha = 0x190A, }; typedef NS_ENUM(NSInteger, GLTFTextureType) { - GLTFTextureTypeUnknown, - GLTFTextureTypeUChar = 0x1401, - GLTFTextureTypeUShort565 = 0x8363, - GLTFTextureTypeUShort4444 = 0x8033, - GLTFTextureTypeUShort5551 = 0x8034, + GLTFTextureTypeUnknown, + GLTFTextureTypeUChar = 0x1401, + GLTFTextureTypeUShort565 = 0x8363, + GLTFTextureTypeUShort4444 = 0x8033, + GLTFTextureTypeUShort5551 = 0x8034, }; typedef NS_ENUM(NSInteger, GLTFShaderType) { - GLTFShaderTypeVertex = 0x8B31, - GLTFShaderTypeFragment = 0x8B30, + GLTFShaderTypeVertex = 0x8B31, + GLTFShaderTypeFragment = 0x8B30, }; typedef NS_ENUM(NSInteger, GLTFSamplingFilter) { - GLTFSamplingFilterUnknown, - GLTFSamplingFilterNearest = 0x2600, - GLTFSamplingFilterLinear = 0x2601, - GLTFSamplingFilterNearestMipNearest = 0x2700, - GLTFSamplingFilterLinearMipNearest = 0x2701, - GLTFSamplingFilterNearestMipLinear = 0x2702, - GLTFSamplingLinearMipLinear = 0x2703, + GLTFSamplingFilterUnknown, + GLTFSamplingFilterNearest = 0x2600, + GLTFSamplingFilterLinear = 0x2601, + GLTFSamplingFilterNearestMipNearest = 0x2700, + GLTFSamplingFilterLinearMipNearest = 0x2701, + GLTFSamplingFilterNearestMipLinear = 0x2702, + GLTFSamplingLinearMipLinear = 0x2703, }; typedef NS_ENUM(NSInteger, GLTFAddressMode) { - GLTFAddressModeUnknown, - GLTFAddressModeClampToEdge = 0x812F, - GLTFAddressModeMirroredRepeat = 0x8370, - GLTFAddressModeRepeat = 0x2901, + GLTFAddressModeUnknown, + GLTFAddressModeClampToEdge = 0x812F, + GLTFAddressModeMirroredRepeat = 0x8370, + GLTFAddressModeRepeat = 0x2901, }; typedef NS_ENUM(NSInteger, GLTFComparisonFunc) { - GLTFComparisonFuncLess = 0x0201, - GLTFComparisonFuncEqual = 0x0202, - GLTFComparisonFuncLessEqual = 0x0203, - GLTFComparisonFuncGreater = 0x0204, - GLTFComparisonFuncNotEqual = 0x0205, - GLTFComparisonFuncGreaterEqual = 0x0206, - GLTFComparisonFuncAlways = 0x0207, + GLTFComparisonFuncLess = 0x0201, + GLTFComparisonFuncEqual = 0x0202, + GLTFComparisonFuncLessEqual = 0x0203, + GLTFComparisonFuncGreater = 0x0204, + GLTFComparisonFuncNotEqual = 0x0205, + GLTFComparisonFuncGreaterEqual = 0x0206, + GLTFComparisonFuncAlways = 0x0207, }; typedef NS_ENUM(NSInteger, GLTFFace) { - GLTFFaceFront = 0x0404, - GLTFFaceBack = 0x405, - GLTFFaceFrontAndBack = 0x408, + GLTFFaceFront = 0x0404, + GLTFFaceBack = 0x405, + GLTFFaceFrontAndBack = 0x408, }; typedef NS_ENUM(NSInteger, GLTFWinding) { - GLTFWindingClockwise = 0x900, - GLTFWindingCounterclockwise = 0x0901, + GLTFWindingClockwise = 0x900, + GLTFWindingCounterclockwise = 0x0901, }; typedef NS_ENUM(NSInteger, GLTFState) { - GLTFStateBlendingEnabled = 0x0BE2, - GLTFStateCullFaceEnabled = 0x0B44, - GLTFStateDepthTestEnabled = 0x0B71, - GLTFStatePolygonOffsetFillEnabled = 0x8037, - GLTFStateAlphaToCoverageEnabled = 0x809E, - GLTFStateScissorTestEnabled = 0x0C11, + GLTFStateBlendingEnabled = 0x0BE2, + GLTFStateCullFaceEnabled = 0x0B44, + GLTFStateDepthTestEnabled = 0x0B71, + GLTFStatePolygonOffsetFillEnabled = 0x8037, + GLTFStateAlphaToCoverageEnabled = 0x809E, + GLTFStateScissorTestEnabled = 0x0C11, }; typedef NS_ENUM(NSInteger, GLTFBlendFunction) { - GLTFBlendFunctionAdd = 0x8006, - GLTFBlendFunctionSubtract = 0x800A, - GLTFBlendFunctionReverseSubtract = 0x800B, + GLTFBlendFunctionAdd = 0x8006, + GLTFBlendFunctionSubtract = 0x800A, + GLTFBlendFunctionReverseSubtract = 0x800B, }; typedef NS_ENUM(NSInteger, GLTFBlendEquation) { - GLTFBlendEquationZero = 0x0000, - GLTFBlendEquationOne = 0x0001, - GLTFBlendEquationSrcColor = 0x0300, - GLTFBlendEquationOneMinusSrcColor = 0x0301, - GLTFBlendEquationSrcAlpha = 0x0302, - GLTFBlendEquationOneMinusSrcAlpha = 0x0303, - GLTFBlendEquationDestAlpha = 0x0304, - GLTFBlendEquationOneMinusDestAlpha = 0x0305, - GLTFBlendEquationDestColor = 0x0306, - GLTFBlendEquationOneMinusDestColor = 0x0307, - GLTFBlendEquationSrcAlphaSaturate = 0x0308, - GLTFBlendEquationConstantColor = 0x8001, - GLTFBlendEquationOneMinusConstColor = 0x8002, - GLTFBlendEquationConstantAlpha = 0x8003, - GLTFBlendEquationOneMinusConstAlpha = 0x8004, + GLTFBlendEquationZero = 0x0000, + GLTFBlendEquationOne = 0x0001, + GLTFBlendEquationSrcColor = 0x0300, + GLTFBlendEquationOneMinusSrcColor = 0x0301, + GLTFBlendEquationSrcAlpha = 0x0302, + GLTFBlendEquationOneMinusSrcAlpha = 0x0303, + GLTFBlendEquationDestAlpha = 0x0304, + GLTFBlendEquationOneMinusDestAlpha = 0x0305, + GLTFBlendEquationDestColor = 0x0306, + GLTFBlendEquationOneMinusDestColor = 0x0307, + GLTFBlendEquationSrcAlphaSaturate = 0x0308, + GLTFBlendEquationConstantColor = 0x8001, + GLTFBlendEquationOneMinusConstColor = 0x8002, + GLTFBlendEquationConstantAlpha = 0x8003, + GLTFBlendEquationOneMinusConstAlpha = 0x8004, }; typedef NS_ENUM(NSInteger, GLTFInterpolationMode) { - GLTFInterpolationModeStep, - GLTFInterpolationModeLinear, - GLTFInterpolationModeCubic, + GLTFInterpolationModeStep, + GLTFInterpolationModeLinear, + GLTFInterpolationModeCubic, }; diff --git a/platform/darwin/src/gltf/gltfkit/GLTFImage.h b/platform/darwin/src/gltf/gltfkit/GLTFImage.h index ce444daff386..fe621ff196b6 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFImage.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFImage.h @@ -14,8 +14,8 @@ // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // -#import "GLTFObject.h" #import "GLTFBufferView.h" +#import "GLTFObject.h" #import @@ -24,13 +24,13 @@ NS_ASSUME_NONNULL_BEGIN @interface GLTFImage : GLTFObject /// A reference to a buffer view containing image data, if url is nil -@property (nonatomic, strong) GLTFBufferView * _Nullable bufferView; +@property (nonatomic, strong) GLTFBufferView *_Nullable bufferView; /// The MIME type of the data contained in this image's buffer view -@property (nonatomic, copy) NSString * _Nullable mimeType; +@property (nonatomic, copy) NSString *_Nullable mimeType; /// A file URL, if the URI was not a decodable data-uri; otherwise nil -@property (nonatomic, copy) NSURL * _Nullable url; +@property (nonatomic, copy) NSURL *_Nullable url; /// A data object containing the data encoded in the image's data-uri, if present; otherwise nil @property (nonatomic, strong) NSData *imageData; diff --git a/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.h b/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.h index 3848b78488bb..9139bacf582d 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.h @@ -19,10 +19,10 @@ #import typedef NS_ENUM(NSInteger, GLTFKHRLightType) { - GLTFKHRLightTypeAmbient, - GLTFKHRLightTypeDirectional, - GLTFKHRLightTypePoint, - GLTFKHRLightTypeSpot, + GLTFKHRLightTypeAmbient, + GLTFKHRLightTypeDirectional, + GLTFKHRLightTypePoint, + GLTFKHRLightTypeSpot, }; @interface GLTFKHRLight : GLTFObject diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.h b/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.h index fe422fe80ec9..07abe678380d 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.h @@ -14,20 +14,20 @@ // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // -#import "GLTFBuffer.h" -#import "GLTFBufferAllocator.h" #import #import +#import "GLTFBuffer.h" +#import "GLTFBufferAllocator.h" NS_ASSUME_NONNULL_BEGIN -@interface GLTFMTLBuffer : NSObject +@interface GLTFMTLBuffer : NSObject @property (nonatomic, readonly) id buffer; @end -@interface GLTFMTLBufferAllocator : NSObject +@interface GLTFMTLBufferAllocator : NSObject - (instancetype)initWithDevice:(id)device; diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.h b/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.h index 4e35d6a9f47d..4c664894ad71 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.h @@ -27,12 +27,13 @@ NS_ASSUME_NONNULL_BEGIN @interface GLTFMTLShaderBuilder : NSObject -- (id)renderPipelineStateForSubmesh:(GLTFSubmesh *)submesh - // lightingEnvironment:(GLTFMTLLightingEnvironment * _Nullable)lightingEnvironment - colorPixelFormat:(MTLPixelFormat)colorPixelFormat - depthStencilPixelFormat:(MTLPixelFormat)depthStencilPixelFormat - sampleCount:(int)sampleCount - device:(id)device; +- (id) + renderPipelineStateForSubmesh:(GLTFSubmesh *)submesh + // lightingEnvironment:(GLTFMTLLightingEnvironment * _Nullable)lightingEnvironment + colorPixelFormat:(MTLPixelFormat)colorPixelFormat + depthStencilPixelFormat:(MTLPixelFormat)depthStencilPixelFormat + sampleCount:(int)sampleCount + device:(id)device; @end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.h b/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.h index 48682d2f058d..286838dda5fa 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.h @@ -14,7 +14,6 @@ // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // - #import NS_ASSUME_NONNULL_BEGIN @@ -25,8 +24,12 @@ extern NSString *const GLTFMTLTextureLoaderOptionSRGB; @interface GLTFMTLTextureLoader : NSObject - (instancetype)initWithDevice:(id)device; -- (id _Nullable)newTextureWithContentsOfURL:(NSURL *)url options:(NSDictionary * _Nullable)options error:(NSError **)error; -- (id _Nullable)newTextureWithData:(NSData *)data options:(NSDictionary * _Nullable)options error:(NSError **)error; +- (id _Nullable)newTextureWithContentsOfURL:(NSURL *)url + options:(NSDictionary *_Nullable)options + error:(NSError **)error; +- (id _Nullable)newTextureWithData:(NSData *)data + options:(NSDictionary *_Nullable)options + error:(NSError **)error; @end NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.h b/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.h index 9764472aafde..774e113d4c51 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.h @@ -25,7 +25,6 @@ NS_ASSUME_NONNULL_BEGIN extern "C" { #endif - extern MTLPrimitiveType GLTFMTLPrimitiveTypeForPrimitiveType(GLTFPrimitiveType gltfType); extern MTLBlendOperation GLTFMTLBlendOperationForBlendFunction(GLTFBlendFunction f); @@ -44,9 +43,11 @@ extern MTLSamplerMipFilter GLTFMTLSamplerMipFilterForSamplingFilter(GLTFSampling extern MTLSamplerAddressMode GLTFMTLSamplerAddressModeForSamplerAddressMode(GLTFAddressMode mode); -extern NSString *GLTFMTLTypeNameForType(GLTFDataType baseType, GLTFDataDimension dimension, BOOL packedIfPossible); +extern NSString *GLTFMTLTypeNameForType(GLTFDataType baseType, GLTFDataDimension dimension, + BOOL packedIfPossible); -extern MTLVertexFormat GLTFMTLVertexFormatForComponentTypeAndDimension(GLTFDataType baseType, GLTFDataDimension dimension); +extern MTLVertexFormat GLTFMTLVertexFormatForComponentTypeAndDimension(GLTFDataType baseType, + GLTFDataDimension dimension); #ifdef __cplusplus } diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMaterial.h b/platform/darwin/src/gltf/gltfkit/GLTFMaterial.h index 92f1d29b4ff7..cc8a889ab828 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFMaterial.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFMaterial.h @@ -24,9 +24,9 @@ NS_ASSUME_NONNULL_BEGIN @class GLTFParameter; typedef NS_ENUM(NSInteger, GLTFAlphaMode) { - GLTFAlphaModeOpaque, - GLTFAlphaModeMask, - GLTFAlphaModeBlend, + GLTFAlphaModeOpaque, + GLTFAlphaModeMask, + GLTFAlphaModeBlend, }; @interface GLTFMaterial : GLTFObject @@ -38,23 +38,27 @@ typedef NS_ENUM(NSInteger, GLTFAlphaMode) { @property (nonatomic, assign) float occlusionStrength; @property (nonatomic, assign) simd_float3 emissiveFactor; -@property (nonatomic, assign) float glossinessFactor; // Only used by KHR_materials_pbrSpecularGlossiness extension -@property (nonatomic, assign) simd_float3 specularFactor; // Only used by KHR_materials_pbrSpecularGlossiness extension +@property (nonatomic, assign) + float glossinessFactor; // Only used by KHR_materials_pbrSpecularGlossiness extension +@property (nonatomic, assign) + simd_float3 specularFactor; // Only used by KHR_materials_pbrSpecularGlossiness extension -@property (nonatomic, strong) GLTFTextureInfo * _Nullable baseColorTexture; -@property (nonatomic, strong) GLTFTextureInfo * _Nullable metallicRoughnessTexture; -@property (nonatomic, strong) GLTFTextureInfo * _Nullable normalTexture; -@property (nonatomic, strong) GLTFTextureInfo * _Nullable emissiveTexture; -@property (nonatomic, strong) GLTFTextureInfo * _Nullable occlusionTexture; +@property (nonatomic, strong) GLTFTextureInfo* _Nullable baseColorTexture; +@property (nonatomic, strong) GLTFTextureInfo* _Nullable metallicRoughnessTexture; +@property (nonatomic, strong) GLTFTextureInfo* _Nullable normalTexture; +@property (nonatomic, strong) GLTFTextureInfo* _Nullable emissiveTexture; +@property (nonatomic, strong) GLTFTextureInfo* _Nullable occlusionTexture; -@property (nonatomic, assign) BOOL hasTextureTransforms; // Only used when KHR_texture_transform extension is present +@property (nonatomic, assign) + BOOL hasTextureTransforms; // Only used when KHR_texture_transform extension is present @property (nonatomic, assign, getter=isDoubleSided) BOOL doubleSided; @property (nonatomic, assign) GLTFAlphaMode alphaMode; -@property (nonatomic, assign) float alphaCutoff; // Only used when `alphaMode` == GLTFAlphaModeMask +@property (nonatomic, assign) float alphaCutoff; // Only used when `alphaMode` == GLTFAlphaModeMask -@property (nonatomic, assign, getter=isUnlit) BOOL unlit; // Only used when KHR_materials_unlit extension is present +@property (nonatomic, assign, getter=isUnlit) + BOOL unlit; // Only used when KHR_materials_unlit extension is present @end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMesh.h b/platform/darwin/src/gltf/gltfkit/GLTFMesh.h index 3bf40f62d258..19d4ea6f9ee7 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFMesh.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFMesh.h @@ -14,8 +14,8 @@ // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // -#import "GLTFObject.h" #import "GLTFEnums.h" +#import "GLTFObject.h" NS_ASSUME_NONNULL_BEGIN diff --git a/platform/darwin/src/gltf/gltfkit/GLTFNode.h b/platform/darwin/src/gltf/gltfkit/GLTFNode.h index 3863bb909130..f370d0299095 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFNode.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFNode.h @@ -14,32 +14,32 @@ // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // +#import +#import "GLTFNodeVisitor.h" #import "GLTFObject.h" #import "GLTFUtilities.h" -#import "GLTFNodeVisitor.h" -#import NS_ASSUME_NONNULL_BEGIN - @class GLTFCamera, GLTFSkin, GLTFMesh; @class GLTFKHRLight; @interface GLTFNode : GLTFObject -@property (nonatomic, weak) GLTFCamera * _Nullable camera; -@property (nonatomic, weak) GLTFKHRLight * _Nullable light; -@property (nonatomic, weak) GLTFNode * _Nullable parent; +@property (nonatomic, weak) GLTFCamera *_Nullable camera; +@property (nonatomic, weak) GLTFKHRLight *_Nullable light; +@property (nonatomic, weak) GLTFNode *_Nullable parent; @property (nonatomic, copy) NSArray *children; -@property (nonatomic, weak) GLTFSkin * _Nullable skin; -@property (nonatomic, copy) NSString * _Nullable jointName; -@property (nonatomic, weak) GLTFMesh * _Nullable mesh; +@property (nonatomic, weak) GLTFSkin *_Nullable skin; +@property (nonatomic, copy) NSString *_Nullable jointName; +@property (nonatomic, weak) GLTFMesh *_Nullable mesh; @property (nonatomic, copy) NSArray *morphTargetWeights; @property (nonatomic, assign) GLTFQuaternion rotationQuaternion; @property (nonatomic, assign) simd_float3 scale; @property (nonatomic, assign) simd_float3 translation; @property (nonatomic, assign) simd_float4x4 localTransform; @property (nonatomic, readonly, assign) simd_float4x4 globalTransform; -@property (nonatomic, readonly, assign) GLTFBoundingBox approximateBounds; // axis-aligned; in local coordinates +@property (nonatomic, readonly, assign) + GLTFBoundingBox approximateBounds; // axis-aligned; in local coordinates - (void)addChildNode:(GLTFNode *)node; - (void)removeFromParent; diff --git a/platform/darwin/src/gltf/gltfkit/GLTFNodeVisitor.h b/platform/darwin/src/gltf/gltfkit/GLTFNodeVisitor.h index a3bceddb5e3e..ee3ce2b5de46 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFNodeVisitor.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFNodeVisitor.h @@ -20,9 +20,7 @@ NS_ASSUME_NONNULL_BEGIN @class GLTFNode; -typedef NS_ENUM(NSInteger, GLTFVisitationStrategy) { - GLTFVisitationStrategyDepthFirst -}; +typedef NS_ENUM(NSInteger, GLTFVisitationStrategy) { GLTFVisitationStrategyDepthFirst }; typedef void (^GLTFNodeVisitor)(GLTFNode *node, int depth, BOOL *stop); diff --git a/platform/darwin/src/gltf/gltfkit/GLTFObject.h b/platform/darwin/src/gltf/gltfkit/GLTFObject.h index c745d543c20e..146d6c82a300 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFObject.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFObject.h @@ -21,7 +21,7 @@ NS_ASSUME_NONNULL_BEGIN @protocol GLTFObject /// The user-defined name of this object. Need not be unique. -@property (nonatomic, copy) NSString * _Nullable name; +@property (nonatomic, copy) NSString *_Nullable name; /// Data specific to any extensions used in this document @property (nonatomic, copy) NSDictionary *extensions; /// Contains application-specific information that is passed through but not parsed @@ -34,7 +34,7 @@ NS_ASSUME_NONNULL_BEGIN /// A unique identifier for this object @property (nonatomic, readonly) NSUUID *identifier; /// The user-defined name of this object. Need not be unique. -@property (nonatomic, copy) NSString * _Nullable name; +@property (nonatomic, copy) NSString *_Nullable name; /// Data specific to any extensions used in this document @property (nonatomic, copy) NSDictionary *extensions; /// Contains application-specific information that is passed through but not parsed diff --git a/platform/darwin/src/gltf/gltfkit/GLTFScene.h b/platform/darwin/src/gltf/gltfkit/GLTFScene.h index cf5ae8480799..6abf39c6c92f 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFScene.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFScene.h @@ -14,9 +14,9 @@ // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // +#import "GLTFNodeVisitor.h" #import "GLTFObject.h" #import "GLTFUtilities.h" -#import "GLTFNodeVisitor.h" NS_ASSUME_NONNULL_BEGIN @@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN @interface GLTFScene : GLTFObject @property (nonatomic, copy) NSArray *nodes; -@property (nonatomic, weak) GLTFKHRLight * _Nullable ambientLight; +@property (nonatomic, weak) GLTFKHRLight *_Nullable ambientLight; @property (nonatomic, readonly, assign) GLTFBoundingBox approximateBounds; - (void)addNode:(GLTFNode *)node; diff --git a/platform/darwin/src/gltf/gltfkit/GLTFTexture.h b/platform/darwin/src/gltf/gltfkit/GLTFTexture.h index 556ab715cd4d..7b7a9f97bb0d 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFTexture.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFTexture.h @@ -14,11 +14,10 @@ // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // -#import "GLTFObject.h" -#import "GLTFEnums.h" -#import "../GLTFMath.hpp" #import - +#import "../GLTFMath.hpp" +#import "GLTFEnums.h" +#import "GLTFObject.h" NS_ASSUME_NONNULL_BEGIN @@ -61,6 +60,4 @@ NS_ASSUME_NONNULL_BEGIN @end - NS_ASSUME_NONNULL_END - diff --git a/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.h b/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.h index a3b372494551..fbe3b026f529 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.h @@ -14,8 +14,8 @@ // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // -#import "GLTFObject.h" #import "GLTFEnums.h" +#import "GLTFObject.h" NS_ASSUME_NONNULL_BEGIN diff --git a/platform/darwin/src/gltf/gltfkit/GLTFUtilities.h b/platform/darwin/src/gltf/gltfkit/GLTFUtilities.h index b23bc2211025..db7a39064ce5 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFUtilities.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFUtilities.h @@ -23,44 +23,37 @@ NS_ASSUME_NONNULL_BEGIN typedef struct __attribute__((packed)) { - float x, y, z; + float x, y, z; } GLTFVector3; typedef struct __attribute__((packed)) { - float x, y, z, w; + float x, y, z, w; } GLTFVector4; typedef struct __attribute__((packed)) { - GLTFVector4 columns[4]; + GLTFVector4 columns[4]; } GLTFMatrix4; typedef simd_quatf GLTFQuaternion; - extern bool GLTFBoundingBoxIsEmpty(GLTFBoundingBox b); extern GLTFBoundingBox *GLTFBoundingBoxUnion(GLTFBoundingBox *a, GLTFBoundingBox b); extern void GLTFBoundingBoxTransform(GLTFBoundingBox *b, simd_float4x4 transform); - extern GLTFQuaternion GLTFQuaternionFromEulerAngles(float pitch, float yaw, float roll); - - - - extern simd_float3x3 GLTFMatrixUpperLeft3x3(simd_float4x4); extern simd_float4x4 GLTFNormalMatrixFromModelMatrix(simd_float4x4); - - extern GLTFDataDimension GLTFDataDimensionForName(NSString *name); extern size_t GLTFSizeOfDataType(GLTFDataType type); -extern size_t GLTFSizeOfComponentTypeWithDimension(GLTFDataType baseType, GLTFDataDimension dimension); +extern size_t GLTFSizeOfComponentTypeWithDimension(GLTFDataType baseType, + GLTFDataDimension dimension); extern NSInteger GLTFComponentCountForDimension(GLTFDataDimension dimension); diff --git a/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.h b/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.h index 4a73f93ef054..beaf2bf9d093 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.h +++ b/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.h @@ -46,7 +46,7 @@ extern NSString *const GLTFAttributeSemanticMetallic; @property (nonatomic, assign) NSInteger stride; @end -@interface GLTFVertexDescriptor: NSObject +@interface GLTFVertexDescriptor : NSObject @property (nonatomic, copy) NSArray *attributes; @property (nonatomic, copy) NSArray *bufferLayouts; @end diff --git a/src/mbgl/style/layers/custom_layer_render_parameters.cpp b/src/mbgl/style/layers/custom_layer_render_parameters.cpp index 4541234ad821..789097ee1ea0 100644 --- a/src/mbgl/style/layers/custom_layer_render_parameters.cpp +++ b/src/mbgl/style/layers/custom_layer_render_parameters.cpp @@ -18,7 +18,7 @@ CustomLayerRenderParameters::CustomLayerRenderParameters(const mbgl::PaintParame mat4 projMatrix; state.getProjMatrix(projMatrix); projectionMatrix = projMatrix; - + const TransformParameters& params = paintParameters.transformParams; nearClippedProjMatrix = params.nearClippedProjMatrix; } From b1198521c7cf72b9c1bc076ee60e5abff87c61f8 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Tue, 11 Feb 2025 14:53:30 +0300 Subject: [PATCH 038/221] fix macos builds --- platform/BUILD.bazel | 5 +- platform/darwin/bazel/files.bzl | 54 +++++++++---------- ...TFMTLRenderItem.m => GLTFMTLRenderItem.mm} | 0 platform/darwin/src/gltf/GLTFModelLayer.mm | 6 --- .../{GLTFModelLoader.m => GLTFModelLoader.mm} | 0 .../{GLTFAccessor.m => GLTFAccessor.mm} | 0 .../{GLTFAnimation.m => GLTFAnimation.mm} | 21 ++++---- .../gltfkit/{GLTFAsset.m => GLTFAsset.mm} | 35 ++++++------ .../{GLTFBinaryChunk.m => GLTFBinaryChunk.mm} | 0 .../{GLTFBufferView.m => GLTFBufferView.mm} | 0 .../gltfkit/{GLTFCamera.m => GLTFCamera.mm} | 0 ...ocator.m => GLTFDefaultBufferAllocator.mm} | 0 ...ExtensionNames.m => GLTFExtensionNames.mm} | 0 .../gltfkit/{GLTFImage.m => GLTFImage.mm} | 0 .../{GLTFKHRLight.m => GLTFKHRLight.mm} | 0 ...rAllocator.m => GLTFMTLBufferAllocator.mm} | 0 ...haderBuilder.m => GLTFMTLShaderBuilder.mm} | 0 ...extureLoader.m => GLTFMTLTextureLoader.mm} | 8 +-- ...GLTFMTLUtilities.m => GLTFMTLUtilities.mm} | 5 +- .../{GLTFMaterial.m => GLTFMaterial.mm} | 0 .../gltf/gltfkit/{GLTFMesh.m => GLTFMesh.mm} | 0 .../gltf/gltfkit/{GLTFNode.m => GLTFNode.mm} | 4 +- .../gltfkit/{GLTFObject.m => GLTFObject.mm} | 0 .../gltfkit/{GLTFScene.m => GLTFScene.mm} | 2 +- .../gltf/gltfkit/{GLTFSkin.m => GLTFSkin.mm} | 0 ...TextureSampler.m => GLTFTextureSampler.mm} | 0 .../{GLTFUtilities.m => GLTFUtilities.mm} | 3 +- ...exDescriptor.m => GLTFVertexDescriptor.mm} | 0 platform/macos/src/MLNMapView+Impl.h | 4 ++ platform/macos/src/MLNMapView+Metal.h | 2 + platform/macos/src/MLNMapView+Metal.mm | 11 ++++ platform/macos/src/MLNMapView+OpenGL.h | 2 + platform/macos/src/MLNMapView+OpenGL.mm | 4 ++ platform/macos/src/MLNMapView.h | 2 + platform/macos/src/MLNMapView.mm | 4 ++ 35 files changed, 99 insertions(+), 73 deletions(-) rename platform/darwin/src/gltf/{GLTFMTLRenderItem.m => GLTFMTLRenderItem.mm} (100%) rename platform/darwin/src/gltf/{GLTFModelLoader.m => GLTFModelLoader.mm} (100%) rename platform/darwin/src/gltf/gltfkit/{GLTFAccessor.m => GLTFAccessor.mm} (100%) rename platform/darwin/src/gltf/gltfkit/{GLTFAnimation.m => GLTFAnimation.mm} (87%) rename platform/darwin/src/gltf/gltfkit/{GLTFAsset.m => GLTFAsset.mm} (96%) rename platform/darwin/src/gltf/gltfkit/{GLTFBinaryChunk.m => GLTFBinaryChunk.mm} (100%) rename platform/darwin/src/gltf/gltfkit/{GLTFBufferView.m => GLTFBufferView.mm} (100%) rename platform/darwin/src/gltf/gltfkit/{GLTFCamera.m => GLTFCamera.mm} (100%) rename platform/darwin/src/gltf/gltfkit/{GLTFDefaultBufferAllocator.m => GLTFDefaultBufferAllocator.mm} (100%) rename platform/darwin/src/gltf/gltfkit/{GLTFExtensionNames.m => GLTFExtensionNames.mm} (100%) rename platform/darwin/src/gltf/gltfkit/{GLTFImage.m => GLTFImage.mm} (100%) rename platform/darwin/src/gltf/gltfkit/{GLTFKHRLight.m => GLTFKHRLight.mm} (100%) rename platform/darwin/src/gltf/gltfkit/{GLTFMTLBufferAllocator.m => GLTFMTLBufferAllocator.mm} (100%) rename platform/darwin/src/gltf/gltfkit/{GLTFMTLShaderBuilder.m => GLTFMTLShaderBuilder.mm} (100%) rename platform/darwin/src/gltf/gltfkit/{GLTFMTLTextureLoader.m => GLTFMTLTextureLoader.mm} (97%) rename platform/darwin/src/gltf/gltfkit/{GLTFMTLUtilities.m => GLTFMTLUtilities.mm} (98%) rename platform/darwin/src/gltf/gltfkit/{GLTFMaterial.m => GLTFMaterial.mm} (100%) rename platform/darwin/src/gltf/gltfkit/{GLTFMesh.m => GLTFMesh.mm} (100%) rename platform/darwin/src/gltf/gltfkit/{GLTFNode.m => GLTFNode.mm} (98%) rename platform/darwin/src/gltf/gltfkit/{GLTFObject.m => GLTFObject.mm} (100%) rename platform/darwin/src/gltf/gltfkit/{GLTFScene.m => GLTFScene.mm} (97%) rename platform/darwin/src/gltf/gltfkit/{GLTFSkin.m => GLTFSkin.mm} (100%) rename platform/darwin/src/gltf/gltfkit/{GLTFTextureSampler.m => GLTFTextureSampler.mm} (100%) rename platform/darwin/src/gltf/gltfkit/{GLTFUtilities.m => GLTFUtilities.mm} (99%) rename platform/darwin/src/gltf/gltfkit/{GLTFVertexDescriptor.m => GLTFVertexDescriptor.mm} (100%) diff --git a/platform/BUILD.bazel b/platform/BUILD.bazel index 9d961d07115e..ae82104a0028 100644 --- a/platform/BUILD.bazel +++ b/platform/BUILD.bazel @@ -4,6 +4,8 @@ load("//bazel:flags.bzl", "CPP_FLAGS", "MAPLIBRE_FLAGS", "WARNING_FLAGS") objc_library( name = "macos-objcpp", srcs = [ + "//platform/darwin:darwin_gltf_hdrs", + "//platform/darwin:darwin_gltf_srcs", "//platform/darwin:darwin_objcpp_custom_drawable_srcs", "//platform/darwin:darwin_objcpp_srcs", "//platform/darwin:darwin_private_hdrs", @@ -36,6 +38,7 @@ objc_library( "CoreLocation", "AppKit", "SystemConfiguration", + "Accelerate", ], visibility = ["//visibility:public"], deps = [ @@ -50,8 +53,6 @@ objc_library( objc_library( name = "macos-objc", srcs = [ - "//platform/darwin:darwin_gltf_hdrs", - "//platform/darwin:darwin_gltf_srcs", "//platform/darwin:darwin_objc_hdrs", "//platform/darwin:darwin_objc_srcs", "//platform/darwin:darwin_private_hdrs", diff --git a/platform/darwin/bazel/files.bzl b/platform/darwin/bazel/files.bzl index f18243fceb4d..08125a3024ad 100644 --- a/platform/darwin/bazel/files.bzl +++ b/platform/darwin/bazel/files.bzl @@ -1,5 +1,5 @@ MLN_GLTF_HEADERS = [ - "src/gltf/GLTFModelLayer.h" + "src/gltf/GLTFModelLayer.h", ] MLN_GLTF_SOURCE = [ @@ -20,68 +20,66 @@ MLN_GLTF_SOURCE = [ "src/gltf/GLTFModelLayer.h", "src/gltf/GLTFModelLayer.mm", "src/gltf/GLTFModelLoader.h", - "src/gltf/GLTFModelLoader.m", + "src/gltf/GLTFModelLoader.mm", "src/gltf/GLTFMTLRenderItem.h", - "src/gltf/GLTFMTLRenderItem.m", + "src/gltf/GLTFMTLRenderItem.mm", "src/gltf/GLTFRenderer.hpp", "src/gltf/GLTFRenderer.cpp", "src/gltf/MetalRenderer+GLTFAsset.mm", "src/gltf/gltfkit/GLTFAsset.h", - "src/gltf/gltfkit/GLTFAsset.m", + "src/gltf/gltfkit/GLTFAsset.mm", "src/gltf/gltfkit/GLTFAccessor.h", - "src/gltf/gltfkit/GLTFAccessor.m", + "src/gltf/gltfkit/GLTFAccessor.mm", "src/gltf/gltfkit/GLTFAnimation.h", - "src/gltf/gltfkit/GLTFAnimation.m", + "src/gltf/gltfkit/GLTFAnimation.mm", "src/gltf/gltfkit/GLTFBinaryChunk.h", - "src/gltf/gltfkit/GLTFBinaryChunk.m", + "src/gltf/gltfkit/GLTFBinaryChunk.mm", "src/gltf/gltfkit/GLTFBuffer.h", "src/gltf/gltfkit/GLTFBufferAllocator.h", "src/gltf/gltfkit/GLTFBufferView.h", - "src/gltf/gltfkit/GLTFBufferView.m", + "src/gltf/gltfkit/GLTFBufferView.mm", "src/gltf/gltfkit/GLTFCamera.h", - "src/gltf/gltfkit/GLTFCamera.m", + "src/gltf/gltfkit/GLTFCamera.mm", "src/gltf/gltfkit/GLTFDefaultBufferAllocator.h", - "src/gltf/gltfkit/GLTFDefaultBufferAllocator.m", + "src/gltf/gltfkit/GLTFDefaultBufferAllocator.mm", "src/gltf/gltfkit/GLTFEnums.h", "src/gltf/gltfkit/GLTFExtensionNames.h", - "src/gltf/gltfkit/GLTFExtensionNames.m", + "src/gltf/gltfkit/GLTFExtensionNames.mm", "src/gltf/gltfkit/GLTFImage.h", - "src/gltf/gltfkit/GLTFImage.m", + "src/gltf/gltfkit/GLTFImage.mm", "src/gltf/gltfkit/GLTFKHRLight.h", - "src/gltf/gltfkit/GLTFKHRLight.m", + "src/gltf/gltfkit/GLTFKHRLight.mm", "src/gltf/gltfkit/GLTFMaterial.h", - "src/gltf/gltfkit/GLTFMaterial.m", + "src/gltf/gltfkit/GLTFMaterial.mm", "src/gltf/gltfkit/GLTFMesh.h", - "src/gltf/gltfkit/GLTFMesh.m", + "src/gltf/gltfkit/GLTFMesh.mm", "src/gltf/gltfkit/GLTFMTLBufferAllocator.h", - "src/gltf/gltfkit/GLTFMTLBufferAllocator.m", + "src/gltf/gltfkit/GLTFMTLBufferAllocator.mm", "src/gltf/gltfkit/GLTFMTLShaderBuilder.h", - "src/gltf/gltfkit/GLTFMTLShaderBuilder.m", + "src/gltf/gltfkit/GLTFMTLShaderBuilder.mm", "src/gltf/gltfkit/GLTFMTLTextureLoader.h", - "src/gltf/gltfkit/GLTFMTLTextureLoader.m", + "src/gltf/gltfkit/GLTFMTLTextureLoader.mm", "src/gltf/gltfkit/GLTFMTLUtilities.h", - "src/gltf/gltfkit/GLTFMTLUtilities.m", + "src/gltf/gltfkit/GLTFMTLUtilities.mm", "src/gltf/gltfkit/GLTFNode.h", - "src/gltf/gltfkit/GLTFNode.m", + "src/gltf/gltfkit/GLTFNode.mm", "src/gltf/gltfkit/GLTFNodeVisitor.h", "src/gltf/gltfkit/GLTFObject.h", - "src/gltf/gltfkit/GLTFObject.m", + "src/gltf/gltfkit/GLTFObject.mm", "src/gltf/gltfkit/GLTFScene.h", - "src/gltf/gltfkit/GLTFScene.m", + "src/gltf/gltfkit/GLTFScene.mm", "src/gltf/gltfkit/GLTFSkin.h", - "src/gltf/gltfkit/GLTFSkin.m", + "src/gltf/gltfkit/GLTFSkin.mm", "src/gltf/gltfkit/GLTFTexture.h", "src/gltf/gltfkit/GLTFTexture.mm", "src/gltf/gltfkit/GLTFTextureSampler.h", - "src/gltf/gltfkit/GLTFTextureSampler.m", + "src/gltf/gltfkit/GLTFTextureSampler.mm", "src/gltf/gltfkit/GLTFUtilities.h", - "src/gltf/gltfkit/GLTFUtilities.m", + "src/gltf/gltfkit/GLTFUtilities.mm", "src/gltf/gltfkit/GLTFVertexDescriptor.h", - "src/gltf/gltfkit/GLTFVertexDescriptor.m", - + "src/gltf/gltfkit/GLTFVertexDescriptor.mm", ] - MLN_GENERATED_DARWIN_STYLE_SOURCE = [ "src/MLNLight.mm", "src/MLNBackgroundStyleLayer.mm", diff --git a/platform/darwin/src/gltf/GLTFMTLRenderItem.m b/platform/darwin/src/gltf/GLTFMTLRenderItem.mm similarity index 100% rename from platform/darwin/src/gltf/GLTFMTLRenderItem.m rename to platform/darwin/src/gltf/GLTFMTLRenderItem.mm diff --git a/platform/darwin/src/gltf/GLTFModelLayer.mm b/platform/darwin/src/gltf/GLTFModelLayer.mm index c88150a4e310..b21e7e46a7f2 100644 --- a/platform/darwin/src/gltf/GLTFModelLayer.mm +++ b/platform/darwin/src/gltf/GLTFModelLayer.mm @@ -9,7 +9,6 @@ #import #import "MLNBackendResource.h" #import "MLNMapView.h" -#import "MLNMapProjection.h" #include #import "GLTFManagerRenderingEnvironmentMetal.hpp" #import "GLTFManager.hpp" @@ -344,11 +343,6 @@ - (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingCon _viewportSize.y = resource.mtkView.drawableSize.height; _manager->setDrawableSize(_viewportSize.x, _viewportSize.y); - MLNMapProjection *proj2 = mapView.mapProjection; - _manager->_metersPerPixel = proj2.metersPerPoint / 2.0; - _manager->setTiltDeg(90-mapView.camera.pitch); - _manager->setRotationDeg(-mapView.camera.heading); - float timestep = (1 / 60.0f); _manager->updateScene(timestep); diff --git a/platform/darwin/src/gltf/GLTFModelLoader.m b/platform/darwin/src/gltf/GLTFModelLoader.mm similarity index 100% rename from platform/darwin/src/gltf/GLTFModelLoader.m rename to platform/darwin/src/gltf/GLTFModelLoader.mm diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAccessor.m b/platform/darwin/src/gltf/gltfkit/GLTFAccessor.mm similarity index 100% rename from platform/darwin/src/gltf/gltfkit/GLTFAccessor.m rename to platform/darwin/src/gltf/gltfkit/GLTFAccessor.mm diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAnimation.m b/platform/darwin/src/gltf/gltfkit/GLTFAnimation.mm similarity index 87% rename from platform/darwin/src/gltf/gltfkit/GLTFAnimation.m rename to platform/darwin/src/gltf/gltfkit/GLTFAnimation.mm index 7bde7e060135..e716fc0113f5 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFAnimation.m +++ b/platform/darwin/src/gltf/gltfkit/GLTFAnimation.mm @@ -15,6 +15,7 @@ // #import "GLTFAnimation.h" +#include "GLTFUtilities.h" #import "GLTFAccessor.h" #import "GLTFBufferView.h" #import "GLTFBuffer.h" @@ -27,11 +28,11 @@ - (NSString *)description { } - (const void *)inputValues { - return [self.inputAccessor.bufferView.buffer contents] + self.inputAccessor.bufferView.offset + self.inputAccessor.offset; + return (uint8_t*)[self.inputAccessor.bufferView.buffer contents] + self.inputAccessor.bufferView.offset + self.inputAccessor.offset; } - (const void *)outputValues { - return [self.outputAccessor.bufferView.buffer contents] + self.outputAccessor.bufferView.offset + self.outputAccessor.offset; + return (uint8_t*)[self.outputAccessor.bufferView.buffer contents] + self.outputAccessor.bufferView.offset + self.outputAccessor.offset; } - (int)keyFrameCount { @@ -48,14 +49,14 @@ - (NSString *)description { - (NSTimeInterval)startTime { GLTFAnimationSampler *sampler = self.sampler; - const float *timeValues = sampler.inputValues; + const float *timeValues = (const float*)sampler.inputValues; float startTime = timeValues[0]; return startTime; } - (NSTimeInterval)endTime { GLTFAnimationSampler *sampler = self.sampler; - const float *timeValues = sampler.inputValues; + const float *timeValues = (const float*)sampler.inputValues; int keyFrameCount = sampler.keyFrameCount; float endTime = timeValues[keyFrameCount - 1]; return endTime; @@ -81,7 +82,7 @@ - (void)runAtTime:(NSTimeInterval)time { int keyFrameCount = sampler.keyFrameCount; - const float *timeValues = sampler.inputValues; + const float *timeValues = (const float*)sampler.inputValues; float minTime = timeValues[0]; float maxTime = timeValues[keyFrameCount - 1]; @@ -115,7 +116,7 @@ - (void)runAtTime:(NSTimeInterval)time { NSLog(@"WARNING: Only float accessors are supported for rotation animations. This will only be reported once."); }); } - const GLTFQuaternion *rotationValues = sampler.outputValues; + const GLTFQuaternion *rotationValues = (const GLTFQuaternion*)sampler.outputValues; GLTFQuaternion previousRotation = rotationValues[previousKeyFrame]; GLTFQuaternion nextRotation = rotationValues[nextKeyFrame]; @@ -123,11 +124,11 @@ - (void)runAtTime:(NSTimeInterval)time { target.rotationQuaternion = interpRotation; } else if ([path isEqualToString:@"translation"]) { - const GLTFVector3 *translationValues = sampler.outputValues; + const GLTFVector3 *translationValues = (const GLTFVector3*)sampler.outputValues; GLTFVector3 previousTranslation = translationValues[previousKeyFrame]; GLTFVector3 nextTranslation = translationValues[nextKeyFrame]; - + GLTFVector3 interpTranslation = (GLTFVector3) { ((1 - frameProgress) * previousTranslation.x) + (frameProgress * nextTranslation.x), ((1 - frameProgress) * previousTranslation.y) + (frameProgress * nextTranslation.y), @@ -136,7 +137,7 @@ - (void)runAtTime:(NSTimeInterval)time { target.translation = (simd_float3){ interpTranslation.x, interpTranslation.y, interpTranslation.z }; } else if ([path isEqualToString:@"scale"]) { - const float *scaleValues = sampler.outputValues; + const float *scaleValues = (const float*)sampler.outputValues; float previousScale = scaleValues[previousKeyFrame]; float nextScale = scaleValues[nextKeyFrame]; @@ -151,7 +152,7 @@ - (void)runAtTime:(NSTimeInterval)time { NSLog(@"WARNING: Only scalar float accessors are supported for weight animations. This will only be reported once."); }); } - const float *weightValues = sampler.outputValues; + const float *weightValues = (const float*)sampler.outputValues; long weightCount = sampler.outputAccessor.count / keyFrameCount; diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAsset.m b/platform/darwin/src/gltf/gltfkit/GLTFAsset.mm similarity index 96% rename from platform/darwin/src/gltf/gltfkit/GLTFAsset.m rename to platform/darwin/src/gltf/gltfkit/GLTFAsset.mm index b54289e4ddeb..ccda5f5ed2d7 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFAsset.m +++ b/platform/darwin/src/gltf/gltfkit/GLTFAsset.mm @@ -15,6 +15,7 @@ // #import "GLTFAsset.h" +#include "GLTFEnums.h" #import "GLTFAnimation.h" #import "GLTFAccessor.h" #import "GLTFBinaryChunk.h" @@ -263,11 +264,11 @@ - (void)readBinaryChunks:(NSData *)assetData { [assetData getBytes:&chunkHeader range:NSMakeRange(offset, sizeof(chunkHeader))]; - NSData *chunkData = [NSData dataWithBytesNoCopy:(void *)(assetData.bytes + offset + sizeof(chunkHeader)) + NSData *chunkData = [NSData dataWithBytesNoCopy:(void *)((uint8_t*)assetData.bytes + offset + sizeof(chunkHeader)) length:chunkHeader.length freeWhenDone:NO]; chunk.data = chunkData; - chunk.chunkType = chunkHeader.type; + chunk.chunkType = (GLTFChunkType)chunkHeader.type; [chunks addObject:chunk]; @@ -296,7 +297,7 @@ - (BOOL)loadAccessors:(NSArray *)accessorsMap { NSMutableArray *accessors = [NSMutableArray arrayWithCapacity:accessorsMap.count]; for (NSDictionary *properties in accessorsMap) { GLTFAccessor *accessor = [[GLTFAccessor alloc] init]; - accessor.componentType = [properties[@"componentType"] integerValue]; + accessor.componentType = (GLTFDataType)[properties[@"componentType"] integerValue]; accessor.dimension = GLTFDataDimensionForName(properties[@"type"]); accessor.offset = [properties[@"byteOffset"] integerValue]; accessor.count = [properties[@"count"] integerValue]; @@ -315,7 +316,7 @@ - (BOOL)loadAccessors:(NSArray *)accessorsMap { NSLog(@"WARNING: Accessor had misaligned offset %d, which is not a multiple of %d. Building auxiliary buffer of length %d and continuing...", (int)dataOffset, (int)alignment, (int)length); id buffer = [_bufferAllocator newBufferWithLength:length]; - memcpy(buffer.contents, accessor.bufferView.buffer.contents + accessor.bufferView.offset + accessor.offset, buffer.length); + memcpy(buffer.contents, (uint8_t*)accessor.bufferView.buffer.contents + accessor.bufferView.offset + accessor.offset, buffer.length); _buffers = [_buffers arrayByAddingObject:buffer]; GLTFBufferView *bufferView = [GLTFBufferView new]; @@ -329,7 +330,7 @@ - (BOOL)loadAccessors:(NSArray *)accessorsMap { } } - __block GLTFValueRange valueRange = { 0 }; + __block GLTFValueRange valueRange = { {}, {} }; NSArray *minValues = properties[@"min"]; [minValues enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger index, BOOL *stop) { valueRange.minValue[index] = num.floatValue; @@ -408,7 +409,7 @@ - (BOOL)loadBufferViews:(NSArray *)bufferViewsMap { bufferView.length = [properties[@"byteLength"] integerValue]; bufferView.stride = [properties[@"byteStride"] integerValue]; bufferView.offset = [properties[@"byteOffset"] integerValue]; - bufferView.target = [properties[@"target"] integerValue]; + bufferView.target = (GLTFTarget)[properties[@"target"] integerValue]; // if ((bufferView.buffer != nil) && (bufferView.offset % 16 != 0)) { // NSLog(@"WARNING: Buffer view %d had misaligned offset of %d. Creating auxilliary buffer of length %d and continuing...", @@ -435,10 +436,10 @@ - (BOOL)loadSamplers:(NSArray *)samplersMap { NSMutableArray *samplers = [NSMutableArray arrayWithCapacity:samplersMap.count]; for (NSDictionary *properties in samplersMap) { GLTFTextureSampler *sampler = [[GLTFTextureSampler alloc] init]; - sampler.minFilter = [properties[@"minFilter"] integerValue] ?: sampler.minFilter; - sampler.magFilter = [properties[@"magFilter"] integerValue] ?: sampler.magFilter; - sampler.sAddressMode = [properties[@"wrapS"] integerValue] ?: sampler.sAddressMode; - sampler.tAddressMode = [properties[@"wrapT"] integerValue] ?: sampler.tAddressMode; + sampler.minFilter = (GLTFSamplingFilter)([properties[@"minFilter"] integerValue] ?: sampler.minFilter); + sampler.magFilter = (GLTFSamplingFilter)([properties[@"magFilter"] integerValue] ?: sampler.magFilter); + sampler.sAddressMode = (GLTFAddressMode)([properties[@"wrapS"] integerValue] ?: sampler.sAddressMode); + sampler.tAddressMode = (GLTFAddressMode)([properties[@"wrapT"] integerValue] ?: sampler.tAddressMode); sampler.name = properties[@"name"]; sampler.extensions = properties[@"extensions"]; sampler.extras = properties[@"extras"]; @@ -510,10 +511,10 @@ - (BOOL)loadTextures:(NSArray *)texturesMap { texture.image = _images[imageIndex]; } - texture.format = [properties[@"format"] integerValue] ?: texture.format; - texture.internalFormat = [properties[@"internalFormat"] integerValue] ?: texture.internalFormat; - texture.target = [properties[@"target"] integerValue] ?: texture.target; - texture.type = [properties[@"type"] integerValue] ?: texture.type; + texture.format = (GLTFTextureFormat)([properties[@"format"] integerValue] ?: texture.format); + texture.internalFormat = (GLTFTextureFormat)([properties[@"internalFormat"] integerValue] ?: texture.internalFormat); + texture.target = (GLTFTextureTarget)([properties[@"target"] integerValue] ?: texture.target); + texture.type = (GLTFTextureType)([properties[@"type"] integerValue] ?: texture.type); texture.name = properties[@"name"]; texture.extensions = properties[@"extensions"]; texture.extras = properties[@"extras"]; @@ -665,12 +666,12 @@ - (BOOL)loadMeshes:(NSArray *)meshesMap { NSUInteger indexAccessorIndex = [submeshProperties[@"indices"] intValue]; if (indexAccessorIndex < _accessors.count) { GLTFAccessor *indexAccessor = _accessors[indexAccessorIndex]; - if (indexAccessor.componentType == GLTFTextureTypeUChar) { + if (indexAccessor.componentType == (GLTFDataType)GLTFTextureTypeUChar) { // Fix up 8-bit indices, since they're unsupported in modern APIs - uint8_t *sourceIndices = indexAccessor.bufferView.buffer.contents + indexAccessor.offset + indexAccessor.bufferView.offset; + uint8_t *sourceIndices = (uint8_t*)indexAccessor.bufferView.buffer.contents + indexAccessor.offset + indexAccessor.bufferView.offset; id shortBuffer = [_bufferAllocator newBufferWithLength:indexAccessor.count * sizeof(uint16_t)]; - uint16_t *destIndices = shortBuffer.contents; + uint16_t *destIndices = (uint16_t*)shortBuffer.contents; for (int i = 0; i < indexAccessor.count; ++i) { destIndices[i] = (uint16_t)sourceIndices[i]; } diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.m b/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.mm similarity index 100% rename from platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.m rename to platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.mm diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBufferView.m b/platform/darwin/src/gltf/gltfkit/GLTFBufferView.mm similarity index 100% rename from platform/darwin/src/gltf/gltfkit/GLTFBufferView.m rename to platform/darwin/src/gltf/gltfkit/GLTFBufferView.mm diff --git a/platform/darwin/src/gltf/gltfkit/GLTFCamera.m b/platform/darwin/src/gltf/gltfkit/GLTFCamera.mm similarity index 100% rename from platform/darwin/src/gltf/gltfkit/GLTFCamera.m rename to platform/darwin/src/gltf/gltfkit/GLTFCamera.mm diff --git a/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.m b/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.mm similarity index 100% rename from platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.m rename to platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.mm diff --git a/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.m b/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.mm similarity index 100% rename from platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.m rename to platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.mm diff --git a/platform/darwin/src/gltf/gltfkit/GLTFImage.m b/platform/darwin/src/gltf/gltfkit/GLTFImage.mm similarity index 100% rename from platform/darwin/src/gltf/gltfkit/GLTFImage.m rename to platform/darwin/src/gltf/gltfkit/GLTFImage.mm diff --git a/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.m b/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.mm similarity index 100% rename from platform/darwin/src/gltf/gltfkit/GLTFKHRLight.m rename to platform/darwin/src/gltf/gltfkit/GLTFKHRLight.mm diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.m b/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.mm similarity index 100% rename from platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.m rename to platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.mm diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.m b/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.mm similarity index 100% rename from platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.m rename to platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.mm diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.m b/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.mm similarity index 97% rename from platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.m rename to platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.mm index ba6f8eb1e046..95c113d17c1e 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.m +++ b/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.mm @@ -77,7 +77,7 @@ vImageConverter_Release(converter); CFRelease(srcData); - return dstPixels; + return (__fp16*)dstPixels; } unsigned char *GLTFMTLConvertImageToRGBA8U(CGImageRef image) @@ -108,7 +108,7 @@ .bitsPerComponent = sizeof(unsigned char) * 8, .bitsPerPixel = sizeof(unsigned char) * 8 * 4, .colorSpace = dstColorSpace, - .bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaLast + .bitmapInfo = (CGBitmapInfo)kCGBitmapByteOrder32Big | (CGBitmapInfo)kCGImageAlphaLast }; vImage_Error error = kvImageNoError; @@ -138,7 +138,7 @@ vImageConverter_Release(converter); CFRelease(srcData); - return dstPixels; + return (unsigned char*)dstPixels; } @interface GLTFMTLTextureLoader () @@ -201,7 +201,7 @@ - (instancetype)initWithDevice:(id)device { height:height mipmapped:mipmapped]; - id texture = [self newTextureWithBytes:dstBytes + id texture = [self newTextureWithBytes:(const unsigned char*)dstBytes bytesPerRow:bytesPerRow descriptor:descriptor options:options diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.m b/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.mm similarity index 98% rename from platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.m rename to platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.mm index 182067e1b400..1dc446902fb5 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.m +++ b/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.mm @@ -29,11 +29,12 @@ MTLPrimitiveType GLTFMTLPrimitiveTypeForPrimitiveType(GLTFPrimitiveType gltfType case GLTFPrimitiveTypeTriangleStrip: return MTLPrimitiveTypeTriangleStrip; - // Not supported; need to duplicate first element and restitch into tri strip, respectively + // Not supported; need to duplicate first element and restitch into tri strip, respectively case GLTFPrimitiveTypeLineLoop: case GLTFPrimitiveTypeTriangleFan: default: - return -1; + NSLog(@"Unsupported primitive type function %d", (int)gltfType); + return MTLPrimitiveTypePoint; } } diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMaterial.m b/platform/darwin/src/gltf/gltfkit/GLTFMaterial.mm similarity index 100% rename from platform/darwin/src/gltf/gltfkit/GLTFMaterial.m rename to platform/darwin/src/gltf/gltfkit/GLTFMaterial.mm diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMesh.m b/platform/darwin/src/gltf/gltfkit/GLTFMesh.mm similarity index 100% rename from platform/darwin/src/gltf/gltfkit/GLTFMesh.m rename to platform/darwin/src/gltf/gltfkit/GLTFMesh.mm diff --git a/platform/darwin/src/gltf/gltfkit/GLTFNode.m b/platform/darwin/src/gltf/gltfkit/GLTFNode.mm similarity index 98% rename from platform/darwin/src/gltf/gltfkit/GLTFNode.m rename to platform/darwin/src/gltf/gltfkit/GLTFNode.mm index 52dd177fde1a..2630d49960c5 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFNode.m +++ b/platform/darwin/src/gltf/gltfkit/GLTFNode.mm @@ -119,11 +119,11 @@ - (GLTFBoundingBox)approximateBounds { } - (GLTFBoundingBox)_approximateBoundsRecursive:(simd_float4x4)transform { - GLTFBoundingBox bounds = { 0 }; + GLTFBoundingBox bounds = { 0, 0 }; if (self.mesh != nil) { for (GLTFSubmesh *submesh in self.mesh.submeshes) { - GLTFBoundingBox submeshBounds = { 0 }; + GLTFBoundingBox submeshBounds = { 0, 0 }; GLTFAccessor *positionAccessor = submesh.accessorsForAttributes[GLTFAttributeSemanticPosition]; GLTFValueRange positionRange = positionAccessor.valueRange; submeshBounds.minPoint.x = positionRange.minValue[0]; diff --git a/platform/darwin/src/gltf/gltfkit/GLTFObject.m b/platform/darwin/src/gltf/gltfkit/GLTFObject.mm similarity index 100% rename from platform/darwin/src/gltf/gltfkit/GLTFObject.m rename to platform/darwin/src/gltf/gltfkit/GLTFObject.mm diff --git a/platform/darwin/src/gltf/gltfkit/GLTFScene.m b/platform/darwin/src/gltf/gltfkit/GLTFScene.mm similarity index 97% rename from platform/darwin/src/gltf/gltfkit/GLTFScene.m rename to platform/darwin/src/gltf/gltfkit/GLTFScene.mm index 3ec31b78f08c..b3f0a6901277 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFScene.m +++ b/platform/darwin/src/gltf/gltfkit/GLTFScene.mm @@ -40,7 +40,7 @@ - (void)addNode:(GLTFNode *)node { } - (GLTFBoundingBox)approximateBounds { - GLTFBoundingBox sceneBounds = { 0 }; + GLTFBoundingBox sceneBounds = { 0, 0 }; for (GLTFNode *node in self.nodes) { GLTFBoundingBox nodeBounds = node.approximateBounds; GLTFBoundingBoxUnion(&sceneBounds, nodeBounds); diff --git a/platform/darwin/src/gltf/gltfkit/GLTFSkin.m b/platform/darwin/src/gltf/gltfkit/GLTFSkin.mm similarity index 100% rename from platform/darwin/src/gltf/gltfkit/GLTFSkin.m rename to platform/darwin/src/gltf/gltfkit/GLTFSkin.mm diff --git a/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.m b/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.mm similarity index 100% rename from platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.m rename to platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.mm diff --git a/platform/darwin/src/gltf/gltfkit/GLTFUtilities.m b/platform/darwin/src/gltf/gltfkit/GLTFUtilities.mm similarity index 99% rename from platform/darwin/src/gltf/gltfkit/GLTFUtilities.m rename to platform/darwin/src/gltf/gltfkit/GLTFUtilities.mm index effa58a06690..ecce6e6fc0bc 100644 --- a/platform/darwin/src/gltf/gltfkit/GLTFUtilities.m +++ b/platform/darwin/src/gltf/gltfkit/GLTFUtilities.mm @@ -15,6 +15,7 @@ // #import "GLTFUtilities.h" +#include "GLTFEnums.h" bool GLTFBoundingBoxIsEmpty(GLTFBoundingBox b) { return (b.minPoint.x == b.maxPoint.x) && (b.minPoint.y == b.maxPoint.y) && (b.minPoint.z == b.maxPoint.z); @@ -115,7 +116,7 @@ GLTFDataDimension GLTFDataDimensionForName(NSString *name) { return GLTFDataDimensionMatrix4x4; } - return -1; + return GLTFDataDimensionUnknown; } size_t GLTFSizeOfDataType(GLTFDataType type) { diff --git a/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.m b/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.mm similarity index 100% rename from platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.m rename to platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.mm diff --git a/platform/macos/src/MLNMapView+Impl.h b/platform/macos/src/MLNMapView+Impl.h index 16a61fca4a6c..4ccc00a17a27 100644 --- a/platform/macos/src/MLNMapView+Impl.h +++ b/platform/macos/src/MLNMapView+Impl.h @@ -2,6 +2,8 @@ #import #import +#import "MLNBackendResource.h" + @class MLNMapView; typedef struct _CGLContextObject* CGLContextObj; @@ -23,6 +25,8 @@ class MLNMapViewImpl : public mbgl::MapObserver { // Called by the view delegate when it's time to render. void render(); + virtual MLNBackendResource getObject() = 0; + // mbgl::MapObserver implementation void onCameraWillChange(mbgl::MapObserver::CameraChangeMode) override; void onCameraIsChanging() override; diff --git a/platform/macos/src/MLNMapView+Metal.h b/platform/macos/src/MLNMapView+Metal.h index f6d12e66c600..a366e38a1bac 100644 --- a/platform/macos/src/MLNMapView+Metal.h +++ b/platform/macos/src/MLNMapView+Metal.h @@ -37,6 +37,8 @@ class MLNMapViewMetalImpl final : public MLNMapViewImpl, mbgl::PremultipliedImage readStillImage() override; + MLNBackendResource getObject() override; + private: bool presentsWithTransaction = false; }; diff --git a/platform/macos/src/MLNMapView+Metal.mm b/platform/macos/src/MLNMapView+Metal.mm index 5c4759cbda7b..b7edee233d7f 100644 --- a/platform/macos/src/MLNMapView+Metal.mm +++ b/platform/macos/src/MLNMapView+Metal.mm @@ -158,3 +158,14 @@ void swap() override { // return readFramebuffer(mapView.framebufferSize); // TODO: RendererBackend::readFramebuffer return {}; } + +MLNBackendResource MLNMapViewMetalImpl::getObject() { + auto& resource = getResource(); + auto renderPassDescriptor = resource.getRenderPassDescriptor().get(); + return { + resource.mtlView, + resource.mtlView.device, + [MTLRenderPassDescriptor renderPassDescriptor], + resource.commandBuffer + }; +} \ No newline at end of file diff --git a/platform/macos/src/MLNMapView+OpenGL.h b/platform/macos/src/MLNMapView+OpenGL.h index fb882b7072bd..2daf3aaab9d9 100644 --- a/platform/macos/src/MLNMapView+OpenGL.h +++ b/platform/macos/src/MLNMapView+OpenGL.h @@ -38,4 +38,6 @@ class MLNMapViewOpenGLImpl final : public MLNMapViewImpl, mbgl::PremultipliedImage readStillImage() override; CGLContextObj getCGLContextObj() override; + + MLNBackendResource getObject() override; }; diff --git a/platform/macos/src/MLNMapView+OpenGL.mm b/platform/macos/src/MLNMapView+OpenGL.mm index de747afbcd3b..83409e00a359 100644 --- a/platform/macos/src/MLNMapView+OpenGL.mm +++ b/platform/macos/src/MLNMapView+OpenGL.mm @@ -87,3 +87,7 @@ void bind() override { MLNOpenGLLayer* layer = (MLNOpenGLLayer*)mapView.layer; return layer.openGLContext.CGLContextObj; } + +MLNBackendResource MLNMapViewOpenGLImpl::getObject() { + return MLNBackendResource(); +} \ No newline at end of file diff --git a/platform/macos/src/MLNMapView.h b/platform/macos/src/MLNMapView.h index d3db2ea6f988..42f93147f791 100644 --- a/platform/macos/src/MLNMapView.h +++ b/platform/macos/src/MLNMapView.h @@ -2,6 +2,7 @@ #import #import +#import "MLNBackendResource.h" #import "MLNFoundation.h" #import "MLNGeometry.h" #import "MLNStyle.h" @@ -1270,6 +1271,7 @@ around the returned camera object if it were set as the receiver’s camera. */ @property (nonatomic) MLNMapDebugMaskOptions debugMask; +- (MLNBackendResource)backendResource; @end NS_ASSUME_NONNULL_END diff --git a/platform/macos/src/MLNMapView.mm b/platform/macos/src/MLNMapView.mm index 7a5281c9cd0b..8b4bac3152c3 100644 --- a/platform/macos/src/MLNMapView.mm +++ b/platform/macos/src/MLNMapView.mm @@ -3190,4 +3190,8 @@ - (void)setDebugMask:(MLNMapDebugMaskOptions)debugMask { _mbglMap->setDebug(options); } +- (MLNBackendResource)backendResource { + return _mbglView->getObject(); +} + @end From b3828292bdcba9bb76351fcfd7bb1bb45d890395 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 5 Mar 2025 21:56:56 +0300 Subject: [PATCH 039/221] support android opengl and vulkan release to github - disbable android device farm test - add support to build and release maplibre-native for android with vulkan and opengl builds. - Add support to publish to github packages --- .github/workflows/android-device-test.yml | 5 +- .github/workflows/android-release.yml | 15 +-- platform/android/Makefile | 2 +- platform/android/build.gradle.kts | 22 ++--- .../kotlin/maplibre.gradle-publish.gradle.kts | 95 +++++++++---------- 5 files changed, 61 insertions(+), 78 deletions(-) diff --git a/.github/workflows/android-device-test.yml b/.github/workflows/android-device-test.yml index 93c516bb6ae3..1bb2b74f9627 100644 --- a/.github/workflows/android-device-test.yml +++ b/.github/workflows/android-device-test.yml @@ -1,10 +1,7 @@ name: android-device-test on: - workflow_run: - workflows: [android-ci] - types: - - completed + workflow_dispatch: permissions: id-token: write # needed for AWS diff --git a/.github/workflows/android-release.yml b/.github/workflows/android-release.yml index 35594f091c89..972291b45cb5 100644 --- a/.github/workflows/android-release.yml +++ b/.github/workflows/android-release.yml @@ -138,18 +138,7 @@ jobs: rm -f ${{ steps.prepare_release.outputs.release_notes }} shell: bash - - name: Prepare MavenCentral release + - name: Publish to Github env: - GPG_KEY_CONTENTS: ${{ secrets.GPG_KEY_CONTENTS }} - run: | - echo "${GPG_KEY_CONTENTS}" | base64 -d > signing-key.gpg - shell: bash - - - name: Publish to MavenCentral + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: make run-android-publish - env: - OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }} - OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} - SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }} - SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }} - SONATYPE_STAGING_PROFILE_ID: ${{ secrets.SONATYPE_STAGING_PROFILE_ID }} diff --git a/platform/android/Makefile b/platform/android/Makefile index c2d85ff530c2..6cf8a85d3283 100644 --- a/platform/android/Makefile +++ b/platform/android/Makefile @@ -247,7 +247,7 @@ run-android-test-app-center: # Uploads the compiled Android SDK to Maven Central Staging .PHONY: run-android-publish run-android-publish: - $(MLN_ANDROID_GRADLE_SINGLE_JOB)-Pmaplibre.abis=all :MapLibreAndroid:publishAllPublicationsToSonatypeRepository closeAndReleaseSonatypeStagingRepository + $(MLN_ANDROID_GRADLE_SINGLE_JOB) -Pmaplibre.abis=all publish # Dump system graphics information for the test app .PHONY: android-gfxinfo diff --git a/platform/android/build.gradle.kts b/platform/android/build.gradle.kts index c830ffbd021f..967adf2d5020 100644 --- a/platform/android/build.gradle.kts +++ b/platform/android/build.gradle.kts @@ -8,14 +8,14 @@ plugins { } -nexusPublishing { - repositories { - sonatype { - stagingProfileId.set(extra["sonatypeStagingProfileId"] as String?) - username.set(extra["ossrhUsername"] as String?) - password.set(extra["ossrhPassword"] as String?) - nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) - snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) - } - } -} +// nexusPublishing { +// repositories { +// sonatype { +// stagingProfileId.set(extra["sonatypeStagingProfileId"] as String?) +// username.set(extra["ossrhUsername"] as String?) +// password.set(extra["ossrhPassword"] as String?) +// nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) +// snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) +// } +// } +// } diff --git a/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts index 3058a4232f37..07b5bedb68f6 100644 --- a/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts +++ b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts @@ -44,68 +44,65 @@ project.logger.lifecycle(project.extra["versionName"].toString()) version = project.extra["versionName"] as String group = project.extra["mapLibreArtifactGroupId"] as String -fun configureMavenPublication( +fun PublishingExtension.configureMavenPublication( renderer: String, publicationName: String, artifactIdPostfix: String, descriptionPostfix: String, ) { - publishing { - publications { - create(publicationName) { - groupId = project.group.toString() - artifactId = "${project.extra["mapLibreArtifactId"]}$artifactIdPostfix" - version = project.version.toString() - - from(components["${renderer}Release"]) - - pom { - name.set("${project.extra["mapLibreArtifactTitle"]}$descriptionPostfix") - description.set("${project.extra["mapLibreArtifactTitle"]}$descriptionPostfix") - url.set(project.extra["mapLibreArtifactUrl"].toString()) - licenses { - license { - name.set(project.extra["mapLibreArtifactLicenseName"].toString()) - url.set(project.extra["mapLibreArtifactLicenseUrl"].toString()) - } - } - developers { - developer { - id.set(project.extra["mapLibreDeveloperId"].toString()) - name.set(project.extra["mapLibreDeveloperName"].toString()) - email.set("team@maplibre.org") - } + publications { + create(publicationName) { + groupId = project.group.toString() + artifactId = "${project.extra["mapLibreArtifactId"]}$artifactIdPostfix" + version = project.version.toString() + + from(components["${renderer}Release"]) + + pom { + name.set("${project.extra["mapLibreArtifactTitle"]}$descriptionPostfix") + description.set("${project.extra["mapLibreArtifactTitle"]}$descriptionPostfix") + url.set(project.extra["mapLibreArtifactUrl"].toString()) + licenses { + license { + name.set(project.extra["mapLibreArtifactLicenseName"].toString()) + url.set(project.extra["mapLibreArtifactLicenseUrl"].toString()) } - scm { - connection.set(project.extra["mapLibreArtifactScmUrl"].toString()) - developerConnection.set(project.extra["mapLibreArtifactScmUrl"].toString()) - url.set(project.extra["mapLibreArtifactUrl"].toString()) + } + developers { + developer { + id.set(project.extra["mapLibreDeveloperId"].toString()) + name.set(project.extra["mapLibreDeveloperName"].toString()) + email.set("team@maplibre.org") } } + scm { + connection.set(project.extra["mapLibreArtifactScmUrl"].toString()) + developerConnection.set(project.extra["mapLibreArtifactScmUrl"].toString()) + url.set(project.extra["mapLibreArtifactUrl"].toString()) + } } } } } - -// workaround for https://github.com/gradle/gradle/issues/26091#issuecomment-1836156762 -// https://github.com/gradle-nexus/publish-plugin/issues/208 -tasks { - withType { - dependsOn(withType()) - } -} - afterEvaluate { - configureMavenPublication("drawable", "opengl", "", "") - configureMavenPublication("vulkan", "vulkan", "-vulkan", "(Vulkan)") - // Right now this is the same as the first, but in the future we might release a major version - // which defaults to Vulkan (or has support for multiple backends). We will keep using only - // OpenGL ES with this artifact ID if that happens. - configureMavenPublication("drawable", "opengl2", "-opengl", " (OpenGL ES)") + publishing { + configureMavenPublication("drawable", "opengl", "", "") + configureMavenPublication("vulkan", "vulkan", "-vulkan", "(Vulkan)") + + repositories { + maven { + name = "GithubPackages" + url = uri("https://maven.pkg.github.com/HudHud-Maps/maplibre-native") + credentials { + username = System.getenv("GITHUB_ACTOR") + password = System.getenv("GITHUB_TOKEN") + } + } + } + } } - afterEvaluate { android.libraryVariants.forEach { variant -> tasks.named("androidJavadocs", Javadoc::class.java).configure { @@ -116,6 +113,6 @@ afterEvaluate { } } -signing { - sign(publishing.publications) -} +// signing { +// sign(publishing.publications) +// } From 8ce65121979d57a173ce5c52660f23b5a7e1412b Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 6 Mar 2025 16:37:48 +0300 Subject: [PATCH 040/221] use maplibre native private token instead of github token --- .github/workflows/android-release.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/android-release.yml b/.github/workflows/android-release.yml index 972291b45cb5..f89f1cc16092 100644 --- a/.github/workflows/android-release.yml +++ b/.github/workflows/android-release.yml @@ -85,7 +85,7 @@ jobs: id: create_release uses: actions/create-release@v1 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.MAPLIBRE_NATIVE_PRIVATE_TOKEN }} with: tag_name: ${{ steps.prepare_release.outputs.version_tag }} release_name: ${{steps.prepare_release.outputs.version_tag }} @@ -96,7 +96,7 @@ jobs: - name: Upload aar (OpenGL) uses: actions/upload-release-asset@v1 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.MAPLIBRE_NATIVE_PRIVATE_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: platform/android/MapLibreAndroid/build/outputs/aar/MapLibreAndroid-drawable-release.aar @@ -106,7 +106,7 @@ jobs: - name: Upload aar (Vulkan) uses: actions/upload-release-asset@v1 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.MAPLIBRE_NATIVE_PRIVATE_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: platform/android/MapLibreAndroid/build/outputs/aar/MapLibreAndroid-vulkan-release.aar @@ -116,7 +116,7 @@ jobs: - name: Upload debug symbols (OpenGL) uses: actions/upload-release-asset@v1 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.MAPLIBRE_NATIVE_PRIVATE_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: platform/android/build/debug-symbols-opengl.tar.gz @@ -126,7 +126,7 @@ jobs: - name: Upload debug symbols (Vulkan) uses: actions/upload-release-asset@v1 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.MAPLIBRE_NATIVE_PRIVATE_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: platform/android/build/debug-symbols-vulkan.tar.gz @@ -140,5 +140,5 @@ jobs: - name: Publish to Github env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.MAPLIBRE_NATIVE_PRIVATE_TOKEN }} run: make run-android-publish From e6998f315f44a51998d10d6f4267db222fbb601a Mon Sep 17 00:00:00 2001 From: alasram Date: Wed, 9 Oct 2024 15:30:45 -0700 Subject: [PATCH 041/221] Add Tile LOD controls --- benchmark/util/tilecover.benchmark.cpp | 2 +- include/mbgl/map/map.hpp | 32 +++++++ .../src/cpp/native_map_view.cpp | 40 ++++++++ .../src/cpp/native_map_view.hpp | 16 ++++ .../maplibre/android/maps/MapLibreMap.java | 95 +++++++++++++++++++ .../org/maplibre/android/maps/NativeMap.java | 16 ++++ .../maplibre/android/maps/NativeMapView.java | 88 +++++++++++++++++ platform/glfw/glfw_view.cpp | 82 +++++++++++++++- src/mbgl/map/map.cpp | 32 +++++++ src/mbgl/map/map_impl.cpp | 6 +- src/mbgl/map/map_impl.hpp | 7 ++ .../layers/render_background_layer.cpp | 16 +++- src/mbgl/renderer/paint_parameters.cpp | 10 +- src/mbgl/renderer/paint_parameters.hpp | 9 +- src/mbgl/renderer/render_orchestrator.cpp | 6 +- src/mbgl/renderer/renderer_impl.cpp | 11 ++- .../renderer/sources/render_image_source.cpp | 4 +- src/mbgl/renderer/tile_parameters.hpp | 5 + src/mbgl/renderer/tile_pyramid.cpp | 15 ++- src/mbgl/renderer/update_parameters.hpp | 6 ++ src/mbgl/util/tile_cover.cpp | 31 +++--- src/mbgl/util/tile_cover.hpp | 13 ++- test/util/tile_cover.test.cpp | 22 ++--- 23 files changed, 518 insertions(+), 46 deletions(-) diff --git a/benchmark/util/tilecover.benchmark.cpp b/benchmark/util/tilecover.benchmark.cpp index dde9f3e9e2b5..c541323edde4 100644 --- a/benchmark/util/tilecover.benchmark.cpp +++ b/benchmark/util/tilecover.benchmark.cpp @@ -26,7 +26,7 @@ static void TileCoverPitchedViewport(benchmark::State& state) { std::size_t length = 0; while (state.KeepRunning()) { - auto tiles = util::tileCover(transform.getState(), 8); + auto tiles = util::tileCover({transform.getState()}, 8); length += tiles.size(); } benchmark::DoNotOptimize(length); diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 914560c92030..442479ee174a 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -152,6 +152,38 @@ class Map : private util::noncopyable { void setFreeCameraOptions(const FreeCameraOptions& camera); FreeCameraOptions getFreeCameraOptions() const; + // Tile LOD controls + // + /// The number of map tile requests can be reduced by using a lower level + /// of details (Lower zoom level) away from the camera. + /// This can improve performance, particularly when the camera pitch is high. + /// The LOD calculation uses a heuristic based on the distance to the camera + /// view point. The heuristic behavior is controlled with 3 parameters: + /// - `TileLodMinRadius` is a radius around the view point in unit of tiles + /// in which the fine grained zoom level tiles are always used + /// - `TileLodScale` is a scale factor for the distance to the camera view + /// point. A value larger than 1 increases the distance to the camera view + /// point in which case the LOD is reduced + /// - `TileLodPitchThreshold` is the pitch angle in radians above which LOD + /// calculation is performed. + /// LOD calculation is always performed if `TileLodPitchThreshold` is zero. + /// LOD calculation is never performed if `TileLodPitchThreshold` is pi. + /// - `TileLodZoomShift` shifts the the Zoom level used for LOD calculation + /// A value of zero (default) does not change the Zoom level + /// A positive value increases the Zoom level and a negative value decreases + /// the Zoom level + /// A negative values typically improves performance but reduces quality. + /// For instance, a value of -1 reduces the zoom level by 1 and this + /// reduces the number of tiles by a factor of 4 for the same camera view. + void setTileLodMinRadius(double radius); + double getTileLodMinRadius() const; + void setTileLodScale(double scale); + double getTileLodScale() const; + void setTileLodPitchThreshold(double threshold); + double getTileLodPitchThreshold() const; + void setTileLodZoomShift(double shift); + double getTileLodZoomShift() const; + protected: class Impl; const std::unique_ptr impl; diff --git a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp index 082443b98efa..e26dea7e2af0 100644 --- a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp +++ b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp @@ -1220,6 +1220,38 @@ jni::jboolean NativeMapView::getTileCacheEnabled(JNIEnv&) { return jni::jboolean(rendererFrontend->getTileCacheEnabled()); } +void NativeMapView::setTileLodMinRadius(JNIEnv&, jni::jdouble radius) { + map->setTileLodMinRadius(radius); +} + +jni::jdouble NativeMapView::getTileLodMinRadius(JNIEnv&) { + return jni::jdouble(map->getTileLodMinRadius()); +} + +void NativeMapView::setTileLodScale(JNIEnv&, jni::jdouble scale) { + map->setTileLodScale(scale); +} + +jni::jdouble NativeMapView::getTileLodScale(JNIEnv&) { + return jni::jdouble(map->getTileLodScale()); +} + +void NativeMapView::setTileLodPitchThreshold(JNIEnv&, jni::jdouble threshold) { + map->setTileLodPitchThreshold(threshold); +} + +jni::jdouble NativeMapView::getTileLodPitchThreshold(JNIEnv&) { + return jni::jdouble(map->getTileLodPitchThreshold()); +} + +void NativeMapView::setTileLodZoomShift(JNIEnv&, jni::jdouble shift) { + map->setTileLodZoomShift(shift); +} + +jni::jdouble NativeMapView::getTileLodZoomShift(JNIEnv&) { + return jni::jdouble(map->getTileLodZoomShift()); +} + mbgl::Map& NativeMapView::getMap() { return *map; } @@ -1339,6 +1371,14 @@ void NativeMapView::registerNative(jni::JNIEnv& env) { METHOD(&NativeMapView::getPrefetchZoomDelta, "nativeGetPrefetchZoomDelta"), METHOD(&NativeMapView::setTileCacheEnabled, "nativeSetTileCacheEnabled"), METHOD(&NativeMapView::getTileCacheEnabled, "nativeGetTileCacheEnabled"), + METHOD(&NativeMapView::setTileLodMinRadius, "nativeSetTileLodMinRadius"), + METHOD(&NativeMapView::getTileLodMinRadius, "nativeGetTileLodMinRadius"), + METHOD(&NativeMapView::setTileLodScale, "nativeSetTileLodScale"), + METHOD(&NativeMapView::getTileLodScale, "nativeGetTileLodScale"), + METHOD(&NativeMapView::setTileLodPitchThreshold, "nativeSetTileLodPitchThreshold"), + METHOD(&NativeMapView::getTileLodPitchThreshold, "nativeGetTileLodPitchThreshold"), + METHOD(&NativeMapView::setTileLodZoomShift, "nativeSetTileLodZoomShift"), + METHOD(&NativeMapView::getTileLodZoomShift, "nativeGetTileLodZoomShift"), METHOD(&NativeMapView::triggerRepaint, "nativeTriggerRepaint")); } diff --git a/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp b/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp index 7ec2a4dd3596..3c136040344d 100644 --- a/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp +++ b/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp @@ -295,6 +295,22 @@ class NativeMapView : public MapObserver { jni::jboolean getTileCacheEnabled(JNIEnv&); + void setTileLodMinRadius(JNIEnv&, jni::jdouble); + + jni::jdouble getTileLodMinRadius(JNIEnv&); + + void setTileLodScale(JNIEnv&, jni::jdouble); + + jni::jdouble getTileLodScale(JNIEnv&); + + void setTileLodPitchThreshold(JNIEnv&, jni::jdouble); + + jni::jdouble getTileLodPitchThreshold(JNIEnv&); + + void setTileLodZoomShift(JNIEnv&, jni::jdouble); + + jni::jdouble getTileLodZoomShift(JNIEnv&); + mbgl::Map& getMap(); void triggerRepaint(JNIEnv&); diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java index 04d758d68e88..7d7a00bf7d0b 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java @@ -344,6 +344,101 @@ public boolean getTileCacheEnabled() { return nativeMapView.getTileCacheEnabled(); } + /** + * Camera based tile level of detail controls + * + * @param radius minimum radius around the view point in unit of tiles in which the fine + * grained zoom level tiles are always used when performing LOD + * radius must be greater than 1 (At least 1 fine detailed tile is present) + * A smaller radius value may improve performance at the cost of quality (tiles away from + * camera use lower Zoom levels) + */ + public void setTileLodMinRadius(@FloatRange(from = 1, fromInclusive = true) double radius) { + nativeMapView.setTileLodMinRadius(radius); + } + + /** + * Camera based tile level of detail controls + * + * @return minimum radius around the view point in unit of tiles in which the fine grained + * zoom level tiles are always used when performing LOD + * @see MapLibreMap#setTileLodMinRadius(double) + */ + public double getTileLodMinRadius() { + return nativeMapView.getTileLodMinRadius(); + } + + /** + * Camera based tile level of detail controls + * + * @param scale factor for the distance to the camera view point + * A value larger than 1 increases the distance to the camera view point reducing LOD + * Larger values may improve performance at the cost of quality (tiles away from camera + * use lower Zoom levels) + */ + public void setTileLodScale(@FloatRange(from = 0, fromInclusive = false) double scale) { + nativeMapView.setTileLodScale(scale); + } + + /** + * Camera based tile level of detail controls + * + * @return scale factor for the distance to the camera view point + * @see MapLibreMap#setTileLodScale(double) + */ + public double getTileLodScale() { + return nativeMapView.getTileLodScale(); + } + + /** + * Camera based tile level of detail controls + * + * @param threshold pitch angle in radians above which LOD calculation is performed + * A smaller radius value may improve performance at the cost of quality + */ + public void setTileLodPitchThreshold(@FloatRange(from = 0, to = Math.PI) double threshold) { + nativeMapView.setTileLodPitchThreshold(threshold); + } + + /** + * Camera based tile level of detail controls + * + * @return pitch angle threshold in radians above which LOD calculation is performed + * @see MapLibreMap#setTileLodPitchThreshold(double) + */ + public double getTileLodPitchThreshold() { + return nativeMapView.getTileLodPitchThreshold(); + } + + /** + * Camera based tile level of detail controls + * + * @param shift shift applied to the Zoom level during LOD calculation + * A negative value shifts the Zoom level to a coarser level reducing quality but + * improving performance + * A positive value shifts the Zoom level to a finer level increasing details but + * negatively affecting performance + * A value of zero (default) does not apply any shift to the Zoom level + * It is not recommended to change the default value unless performance is critical + * and the loss of quality is acceptable. A value of -1 reduces the number of + * displayed tiles by a factor of 4 on average + * It is recommended to first configure the pixelRatio before adjusting + * TileLodZoomShift. {@link MapLibreMapOptions#pixelRatio(float)} + */ + public void setTileLodZoomShift(double shift) { + nativeMapView.setTileLodZoomShift(shift); + } + + /** + * Camera based tile level of detail controls + * + * @return shift applied to the Zoom level during LOD calculation + * @see MapLibreMap#setTileLodZoomShift(double) + */ + public double getTileLodZoomShift() { + return nativeMapView.getTileLodZoomShift(); + } + // // MinZoom // diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java index 31fd4f6bafa5..fc110bbdfd14 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java @@ -238,6 +238,22 @@ List queryRenderedFeatures(@NonNull RectF coordinates, boolean getTileCacheEnabled(); + void setTileLodMinRadius(double radius); + + double getTileLodMinRadius(); + + void setTileLodScale(double scale); + + double getTileLodScale(); + + void setTileLodPitchThreshold(double threshold); + + double getTileLodPitchThreshold(); + + void setTileLodZoomShift(double shift); + + double getTileLodZoomShift(); + void setGestureInProgress(boolean inProgress); float getPixelRatio(); diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java index 4ed013c50dcb..999be1368ced 100755 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java @@ -825,6 +825,70 @@ public boolean getTileCacheEnabled() { } return nativeGetTileCacheEnabled(); } + + @Override + public void setTileLodMinRadius(double radius) { + if (checkState("setTileLodMinRadius")) { + return; + } + nativeSetTileLodMinRadius(radius); + } + + @Override + public double getTileLodMinRadius() { + if (checkState("getTileLodMinRadius")) { + return 0; + } + return nativeGetTileLodMinRadius(); + } + + @Override + public void setTileLodScale(double scale) { + if (checkState("setTileLodScale")) { + return; + } + nativeSetTileLodScale(scale); + } + + @Override + public double getTileLodScale() { + if (checkState("getTileLodScale")) { + return 0; + } + return nativeGetTileLodScale(); + } + + @Override + public void setTileLodPitchThreshold(double threshold) { + if (checkState("setTileLodPitchThreshold")) { + return; + } + nativeSetTileLodPitchThreshold(threshold); + } + + @Override + public double getTileLodPitchThreshold() { + if (checkState("getTileLodPitchThreshold")) { + return 0; + } + return nativeGetTileLodPitchThreshold(); + } + + @Override + public void setTileLodZoomShift(double shift) { + if (checkState("setTileLodZoomShift")) { + return; + } + nativeSetTileLodZoomShift(shift); + } + + @Override + public double getTileLodZoomShift() { + if (checkState("getTileLodZoomShift")) { + return 0; + } + return nativeGetTileLodZoomShift(); + } // Runtime style Api @Override @@ -1596,6 +1660,30 @@ private native Feature[] nativeQueryRenderedFeaturesForBox(float left, float top @Keep private native int nativeGetPrefetchZoomDelta(); + @Keep + private native void nativeSetTileLodMinRadius(double radius); + + @Keep + private native double nativeGetTileLodMinRadius(); + + @Keep + private native void nativeSetTileLodScale(double scale); + + @Keep + private native double nativeGetTileLodScale(); + + @Keep + private native void nativeSetTileLodPitchThreshold(double threshold); + + @Keep + private native double nativeGetTileLodPitchThreshold(); + + @Keep + private native void nativeSetTileLodZoomShift(double shift); + + @Keep + private native double nativeGetTileLodZoomShift(); + @Override public long getNativePtr() { return nativePtr; diff --git a/platform/glfw/glfw_view.cpp b/platform/glfw/glfw_view.cpp index 4c11ccf27348..95864f199e7d 100644 --- a/platform/glfw/glfw_view.cpp +++ b/platform/glfw/glfw_view.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -68,7 +69,6 @@ using namespace std::numbers; #ifdef ENABLE_LOCATION_INDICATOR - namespace { const std::string mbglPuckAssetsPath{MLN_ASSETS_PATH}; @@ -83,7 +83,7 @@ std::array toArray(const mbgl::LatLng &crd) { return {crd.latitude(), crd.longitude(), 0}; } } // namespace -#endif +#endif // ENABLE_LOCATION_INDICATOR class SnapshotObserver final : public mbgl::MapSnapshotterObserver { public: @@ -99,6 +99,72 @@ class SnapshotObserver final : public mbgl::MapSnapshotterObserver { }; namespace { + +enum class TileLodMode { + Default, // Default Tile LOD parameters + NoLod, // Disable LOD + Reduced, // Reduce LOD away from camera + Aggressive, // Aggressively reduce LOD away from camera at the detriment of quality +}; + +constexpr TileLodMode nextTileLodMode(TileLodMode current) { + switch (current) { + case TileLodMode::Default: + return TileLodMode::NoLod; + case TileLodMode::NoLod: + return TileLodMode::Reduced; + case TileLodMode::Reduced: + return TileLodMode::Aggressive; + case TileLodMode::Aggressive: + return TileLodMode::Default; + default: + return TileLodMode::Default; + } +} + +void cycleTileLodMode(mbgl::Map &map) { + // TileLodMode::Default parameters + static const auto defaultRadius = map.getTileLodMinRadius(); + static const auto defaultScale = map.getTileLodScale(); + static const auto defaultPitchThreshold = map.getTileLodPitchThreshold(); + + static TileLodMode mode = TileLodMode::Default; + mode = nextTileLodMode(mode); + + switch (mode) { + case TileLodMode::Default: + map.setTileLodMinRadius(defaultRadius); + map.setTileLodScale(defaultScale); + map.setTileLodPitchThreshold(defaultPitchThreshold); + break; + case TileLodMode::NoLod: + // When LOD is off we set a maximum PitchThreshold + map.setTileLodMinRadius(std::numbers::pi); + break; + case TileLodMode::Reduced: + map.setTileLodMinRadius(2); + map.setTileLodScale(1.5); + map.setTileLodPitchThreshold(std::numbers::pi / 4); + break; + case TileLodMode::Aggressive: + map.setTileLodMinRadius(1); + map.setTileLodScale(2); + map.setTileLodPitchThreshold(0); + break; + } + map.triggerRepaint(); +} + +void tileLodZoomShift(mbgl::Map &map, bool positive) { + constexpr auto tileLodZoomShiftStep = 0.25; + auto shift = positive ? tileLodZoomShiftStep : -tileLodZoomShiftStep; + shift = map.getTileLodZoomShift() + shift; + shift = mbgl::util::clamp(shift, -2.5, 2.5); + mbgl::Log::Info(mbgl::Event::OpenGL, "Zoom shift: " + std::to_string(shift)); + map.setTileLodZoomShift(shift); + map.triggerRepaint(); +} + void addFillExtrusionLayer(mbgl::style::Style &style, bool visible) { MLN_TRACE_FUNC(); @@ -286,6 +352,9 @@ GLFWView::GLFWView(bool fullscreen_, printf("- Press `F1` to generate a render test for the current view\n"); printf("\n"); printf("- Press `Tab` to cycle through the map debug options\n"); + printf("- Press `V` to cycle through Tile LOD modes\n"); + printf("- Press `F7` to lower the zoom level without changing the camera\n"); + printf("- Press `F8` to higher the zoom level without changing the camera\n"); printf("- Press `Esc` to quit\n"); printf("\n"); printf( @@ -562,6 +631,15 @@ void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action, view->freeCameraDemoStartTime = mbgl::Clock::now(); view->invalidate(); } break; + case GLFW_KEY_V: { + cycleTileLodMode(*view->map); + } break; + case GLFW_KEY_F7: { + tileLodZoomShift(*view->map, false); + } break; + case GLFW_KEY_F8: { + tileLodZoomShift(*view->map, true); + } break; } } diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 9bad545b1842..8903bb1b71c5 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -527,4 +527,36 @@ FreeCameraOptions Map::getFreeCameraOptions() const { return impl->transform.getFreeCameraOptions(); } +void Map::setTileLodMinRadius(double radius) { + impl->tileLodMinRadius = radius; +} + +double Map::getTileLodMinRadius() const { + return impl->tileLodMinRadius; +} + +void Map::setTileLodScale(double scale) { + impl->tileLodScale = scale; +} + +double Map::getTileLodScale() const { + return impl->tileLodScale; +} + +void Map::setTileLodPitchThreshold(double threshold) { + impl->tileLodPitchThreshold = threshold; +} + +double Map::getTileLodPitchThreshold() const { + return impl->tileLodPitchThreshold; +} + +void Map::setTileLodZoomShift(double shift) { + impl->tileLodZoomShift = shift; +} + +double Map::getTileLodZoomShift() const { + return impl->tileLodZoomShift; +} + } // namespace mbgl diff --git a/src/mbgl/map/map_impl.cpp b/src/mbgl/map/map_impl.cpp index 6b5a6454f182..aeb7b78dfc38 100644 --- a/src/mbgl/map/map_impl.cpp +++ b/src/mbgl/map/map_impl.cpp @@ -99,7 +99,11 @@ void Map::Impl::onUpdate() { fileSource, prefetchZoomDelta, bool(stillImageRequest), - crossSourceCollisions}; + crossSourceCollisions, + tileLodMinRadius, + tileLodScale, + tileLodPitchThreshold, + tileLodZoomShift}; rendererFrontend.update(std::make_shared(std::move(params))); } diff --git a/src/mbgl/map/map_impl.hpp b/src/mbgl/map/map_impl.hpp index d093b30f227b..83aca45f8c77 100644 --- a/src/mbgl/map/map_impl.hpp +++ b/src/mbgl/map/map_impl.hpp @@ -14,6 +14,8 @@ #include #include +#include + namespace mbgl { class FileSource; @@ -90,6 +92,11 @@ class Map::Impl final : public style::Observer, public RendererObserver { bool loading = false; bool rendererFullyLoaded; std::unique_ptr stillImageRequest; + + double tileLodMinRadius = 3; + double tileLodScale = 1; + double tileLodPitchThreshold = (60.0 / 180.0) * std::numbers::pi; + double tileLodZoomShift = 0; }; // Forward declaration of this method is required for the MapProjection class diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp index b32271a23bc7..dc0046ff2954 100644 --- a/src/mbgl/renderer/layers/render_background_layer.cpp +++ b/src/mbgl/renderer/layers/render_background_layer.cpp @@ -130,6 +130,9 @@ void RenderBackgroundLayer::render(PaintParameters& parameters) { segments = RenderStaticData::tileTriangleSegments(); } + util::TileCoverParameters tileCoverParameters = { + parameters.state, parameters.tileLodMinRadius, parameters.tileLodScale, parameters.tileLodPitchThreshold}; + const auto& evaluated = static_cast(*evaluatedProperties).evaluated; const auto& crossfade = static_cast(*evaluatedProperties).crossfade; if (!evaluated.get().to.empty()) { @@ -141,7 +144,7 @@ void RenderBackgroundLayer::render(PaintParameters& parameters) { if (!imagePosA || !imagePosB) return; uint32_t i = 0; - for (const auto& tileID : util::tileCover(parameters.state, parameters.state.getIntegerZoom())) { + for (const auto& tileID : util::tileCover(tileCoverParameters, parameters.state.getIntegerZoom())) { const UnwrappedTileID unwrappedTileID = tileID.toUnwrapped(); draw(*backgroundPatternProgram, BackgroundPatternProgram::layoutUniformValues(parameters.matrixForTile(unwrappedTileID), @@ -167,7 +170,7 @@ void RenderBackgroundLayer::render(PaintParameters& parameters) { return; } uint32_t i = 0; - for (const auto& tileID : util::tileCover(parameters.state, parameters.state.getIntegerZoom())) { + for (const auto& tileID : util::tileCover(tileCoverParameters, parameters.state.getIntegerZoom())) { draw(*backgroundProgram, BackgroundProgram::LayoutUniformValues{ uniforms::matrix::Value(parameters.matrixForTile(tileID.toUnwrapped())), @@ -217,11 +220,16 @@ static constexpr std::string_view BackgroundPatternShaderName = "BackgroundPatte void RenderBackgroundLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, const TransformState& state, - const std::shared_ptr&, + const std::shared_ptr& updateParameters, [[maybe_unused]] const RenderTree& renderTree, [[maybe_unused]] UniqueChangeRequestVec& changes) { + assert(updateParameters); const auto zoom = state.getIntegerZoom(); - const auto tileCover = util::tileCover(state, zoom); + const auto tileCover = util::tileCover({state, + updateParameters->tileLodMinRadius, + updateParameters->tileLodScale, + updateParameters->tileLodPitchThreshold}, + zoom); // renderTiles is always empty, we use tileCover instead if (tileCover.empty()) { diff --git a/src/mbgl/renderer/paint_parameters.cpp b/src/mbgl/renderer/paint_parameters.cpp index 460e5d2278bc..d4ae017f91e7 100644 --- a/src/mbgl/renderer/paint_parameters.cpp +++ b/src/mbgl/renderer/paint_parameters.cpp @@ -51,7 +51,10 @@ PaintParameters::PaintParameters(gfx::Context& context_, RenderStaticData& staticData_, LineAtlas& lineAtlas_, PatternAtlas& patternAtlas_, - uint64_t frameCount_) + uint64_t frameCount_, + double tileLodMinRadius_, + double tileLodScale_, + double tileLodPitchThreshold_) : context(context_), backend(backend_), encoder(context.createCommandEncoder()), @@ -71,7 +74,10 @@ PaintParameters::PaintParameters(gfx::Context& context_, programs(staticData_.programs), #endif shaders(*staticData_.shaders), - frameCount(frameCount_) { + frameCount(frameCount_), + tileLodMinRadius(tileLodMinRadius_), + tileLodScale(tileLodScale_), + tileLodPitchThreshold(tileLodPitchThreshold_) { pixelsToGLUnits = {{2.0f / state.getSize().width, -2.0f / state.getSize().height}}; if (state.getViewportMode() == ViewportMode::FlippedY) { diff --git a/src/mbgl/renderer/paint_parameters.hpp b/src/mbgl/renderer/paint_parameters.hpp index 6bb5a13fcde7..6385ec0c7096 100644 --- a/src/mbgl/renderer/paint_parameters.hpp +++ b/src/mbgl/renderer/paint_parameters.hpp @@ -58,7 +58,10 @@ class PaintParameters { RenderStaticData&, LineAtlas&, PatternAtlas&, - uint64_t frameCount); + uint64_t frameCount, + double tileLodMinRadius, + double tileLodScale, + double tileLodPitchThreshold); ~PaintParameters(); gfx::Context& context; @@ -134,6 +137,10 @@ class PaintParameters { static constexpr float depthEpsilon = 1.0f / (1 << 12); #endif static constexpr int maxStencilValue = 255; + + double tileLodMinRadius; + double tileLodScale; + double tileLodPitchThreshold; }; } // namespace mbgl diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index 83cb534b4928..45bfa89260d6 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -197,7 +197,11 @@ std::unique_ptr RenderOrchestrator::createRenderTree( imageManager, glyphManager, updateParameters->prefetchZoomDelta, - threadPool}; + threadPool, + updateParameters->tileLodMinRadius, + updateParameters->tileLodScale, + updateParameters->tileLodPitchThreshold, + updateParameters->tileLodZoomShift}; glyphManager->setURL(updateParameters->glyphURL); diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index f28165ca2c85..6e5701ba889a 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -90,12 +91,13 @@ void Renderer::Impl::setObserver(RendererObserver* observer_) { observer = observer_ ? observer_ : &nullObserver(); } -void Renderer::Impl::render(const RenderTree& renderTree, - [[maybe_unused]] const std::shared_ptr& updateParameters) { +void Renderer::Impl::render(const RenderTree& renderTree, const std::shared_ptr& updateParameters) { MLN_TRACE_FUNC(); auto& context = backend.getContext(); context.setObserver(this); + assert(updateParameters); + #if MLN_RENDER_BACKEND_METAL if constexpr (EnableMetalCapture) { const auto& mtlBackend = static_cast(backend); @@ -200,7 +202,10 @@ void Renderer::Impl::render(const RenderTree& renderTree, *staticData, renderTree.getLineAtlas(), renderTree.getPatternAtlas(), - frameCount}; + frameCount, + updateParameters->tileLodMinRadius, + updateParameters->tileLodScale, + updateParameters->tileLodPitchThreshold}; parameters.symbolFadeChange = renderTreeParameters.symbolFadeChange; parameters.opaquePassCutoff = renderTreeParameters.opaquePassCutOff; diff --git a/src/mbgl/renderer/sources/render_image_source.cpp b/src/mbgl/renderer/sources/render_image_source.cpp index 76c9e71dde39..6f17c6bf3dba 100644 --- a/src/mbgl/renderer/sources/render_image_source.cpp +++ b/src/mbgl/renderer/sources/render_image_source.cpp @@ -182,7 +182,9 @@ void RenderImageSource::update(Immutable baseImpl_, bool hasVisibleTile = false; // Add additional wrapped tile ids if neccessary - auto idealTiles = util::tileCover(transformState, static_cast(transformState.getZoom())); + auto idealTiles = util::tileCover( + {transformState, parameters.tileLodMinRadius, parameters.tileLodScale, parameters.tileLodPitchThreshold}, + static_cast(transformState.getZoom())); for (auto tile : idealTiles) { if (tile.wrap != 0 && tileCover[0].canonical.isChildOf(tile.canonical)) { tileIds.emplace_back(tile.wrap, tileCover[0].canonical); diff --git a/src/mbgl/renderer/tile_parameters.hpp b/src/mbgl/renderer/tile_parameters.hpp index 75c1c152f4ff..d6615f8a6d13 100644 --- a/src/mbgl/renderer/tile_parameters.hpp +++ b/src/mbgl/renderer/tile_parameters.hpp @@ -4,6 +4,7 @@ #include #include +#include #include @@ -27,6 +28,10 @@ class TileParameters { std::shared_ptr glyphManager; const uint8_t prefetchZoomDelta; TaggedScheduler threadPool; + double tileLodMinRadius = 3; + double tileLodScale = 1; + double tileLodPitchThreshold = (60.0 / 180.0) * std::numbers::pi; + double tileLodZoomShift = 0; }; } // namespace mbgl diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp index 3e79657b5bf6..efe0d6f94eb8 100644 --- a/src/mbgl/renderer/tile_pyramid.cpp +++ b/src/mbgl/renderer/tile_pyramid.cpp @@ -89,9 +89,13 @@ void TilePyramid::update(const std::vector>& l handleWrapJump(static_cast(parameters.transformState.getLatLng().longitude())); + // Optionally shift the zoom level + double zoom = util::clamp( + parameters.transformState.getZoom() + parameters.tileLodZoomShift, zoomRange.min, zoomRange.max); + const auto type = sourceImpl.type; // Determine the overzooming/underzooming amounts and required tiles. - int32_t overscaledZoom = util::coveringZoomLevel(parameters.transformState.getZoom(), type, tileSize); + int32_t overscaledZoom = util::coveringZoomLevel(zoom, type, tileSize); int32_t tileZoom = overscaledZoom; int32_t panZoom = zoomRange.max; @@ -103,6 +107,11 @@ void TilePyramid::update(const std::vector>& l std::vector idealTiles; std::vector panTiles; + util::TileCoverParameters tileCoverParameters = {parameters.transformState, + parameters.tileLodMinRadius, + parameters.tileLodScale, + parameters.tileLodPitchThreshold}; + if (overscaledZoom >= zoomRange.min) { int32_t idealZoom = std::min(zoomRange.max, overscaledZoom); @@ -123,11 +132,11 @@ void TilePyramid::update(const std::vector>& l } if (panZoom < idealZoom) { - panTiles = util::tileCover(parameters.transformState, panZoom); + panTiles = util::tileCover(tileCoverParameters, panZoom); } } - idealTiles = util::tileCover(parameters.transformState, idealZoom, tileZoom); + idealTiles = util::tileCover(tileCoverParameters, idealZoom, tileZoom); if (parameters.mode == MapMode::Tile && type != SourceType::Raster && type != SourceType::RasterDEM && idealTiles.size() > 1) { mbgl::Log::Warning(mbgl::Event::General, diff --git a/src/mbgl/renderer/update_parameters.hpp b/src/mbgl/renderer/update_parameters.hpp index a16a2801f0bb..d2b162c29eeb 100644 --- a/src/mbgl/renderer/update_parameters.hpp +++ b/src/mbgl/renderer/update_parameters.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -44,6 +45,11 @@ class UpdateParameters { const bool stillImageRequest; const bool crossSourceCollisions; + + double tileLodMinRadius = 3; + double tileLodScale = 1; + double tileLodPitchThreshold = (60.0 / 180.0) * std::numbers::pi; + double tileLodZoomShift = 0; }; } // namespace mbgl diff --git a/src/mbgl/util/tile_cover.cpp b/src/mbgl/util/tile_cover.cpp index 1a3055788bfd..d4f2e4eab4f5 100644 --- a/src/mbgl/util/tile_cover.cpp +++ b/src/mbgl/util/tile_cover.cpp @@ -1,4 +1,3 @@ -#include #include #include #include @@ -9,7 +8,6 @@ #include #include -#include using namespace std::numbers; @@ -157,7 +155,7 @@ int32_t coveringZoomLevel(double zoom, style::SourceType type, uint16_t size) no } } -std::vector tileCover(const TransformState& state, +std::vector tileCover(const TileCoverParameters& state, uint8_t z, const std::optional& overscaledZ) { struct Node { @@ -173,23 +171,26 @@ std::vector tileCover(const TransformState& state, double sqrDist; }; + const auto& transform = state.transformState; const double numTiles = std::pow(2.0, z); - const double worldSize = Projection::worldSize(state.getScale()); - const uint8_t minZoom = state.getPitch() <= (60.0 / 180.0) * pi ? z : 0; + const double worldSize = Projection::worldSize(transform.getScale()); + const uint8_t minZoom = transform.getPitch() <= state.tileLodPitchThreshold ? z : 0; const uint8_t maxZoom = z; - const uint8_t overscaledZoom = overscaledZ.value_or(z); - const bool flippedY = state.getViewportMode() == ViewportMode::FlippedY; + const uint8_t overscaledZoom = std::max(overscaledZ.value_or(z), z); + const bool flippedY = transform.getViewportMode() == ViewportMode::FlippedY; - const auto centerPoint = - TileCoordinate::fromScreenCoordinate(state, z, {state.getSize().width / 2.0, state.getSize().height / 2.0}).p; + const auto centerPoint = TileCoordinate::fromScreenCoordinate( + transform, z, {transform.getSize().width / 2.0, transform.getSize().height / 2.0}) + .p; const vec3 centerCoord = {{centerPoint.x, centerPoint.y, 0.0}}; - const Frustum frustum = Frustum::fromInvProjMatrix(state.getInvProjectionMatrix(), worldSize, z, flippedY); + const Frustum frustum = Frustum::fromInvProjMatrix(transform.getInvProjectionMatrix(), worldSize, z, flippedY); // There should always be a certain number of maximum zoom level tiles // surrounding the center location - const double radiusOfMaxLvlLodInTiles = 3; + assert(state.tileLodMinRadius >= 1); + const double radiusOfMaxLvlLodInTiles = std::max(1.0, state.tileLodMinRadius); const auto newRootTile = [&](int16_t wrap) -> Node { return {AABB({{wrap * numTiles, 0.0, 0.0}}, {{(wrap + 1) * numTiles, numTiles, 0.0}}), @@ -235,12 +236,14 @@ std::vector tileCover(const TransformState& state, // there's always a certain number of maxLevel tiles next to the map // center. Using the fact that a parent node in quadtree is twice the // size of its children (per dimension) we can define distance - // thresholds for each relative level: f(k) = offset + 2 + 4 + 8 + 16 + - // ... + 2^k. This is the same as "offset+2^(k+1)-2" + // thresholds for each relative level: + // f(k) = offset + 2 + 4 + 8 + 16 + ... + 2^k + // This is the same as: + // f(k) = offset + 2^(k+1)-2 const double distToSplit = radiusOfMaxLvlLodInTiles + (1 << (maxZoom - node.zoom)) - 2; // Have we reached the target depth or is the tile too far away to be any split further? - if (node.zoom == maxZoom || (*longestDim > distToSplit && node.zoom >= minZoom)) { + if (node.zoom == maxZoom || (*longestDim * state.tileLodScale > distToSplit && node.zoom >= minZoom)) { // Perform precise intersection test between the frustum and aabb. // This will cull < 1% false positives missed by the original test if (node.fullyVisible || frustum.intersectsPrecise(node.aabb, true) != IntersectionResult::Separate) { diff --git a/src/mbgl/util/tile_cover.hpp b/src/mbgl/util/tile_cover.hpp index 972fdc5ed844..a935b2d3a4cb 100644 --- a/src/mbgl/util/tile_cover.hpp +++ b/src/mbgl/util/tile_cover.hpp @@ -1,16 +1,18 @@ #pragma once +#include #include #include #include +#include #include #include +#include #include namespace mbgl { -class TransformState; class LatLngBounds; namespace util { @@ -31,9 +33,16 @@ class TileCover { std::unique_ptr impl; }; +struct TileCoverParameters { + TransformState transformState; + double tileLodMinRadius = 3; + double tileLodScale = 1; + double tileLodPitchThreshold = (60.0 / 180.0) * std::numbers::pi; +}; + int32_t coveringZoomLevel(double z, style::SourceType type, uint16_t tileSize) noexcept; -std::vector tileCover(const TransformState&, +std::vector tileCover(const TileCoverParameters& state, uint8_t z, const std::optional& overscaledZ = std::nullopt); std::vector tileCover(const LatLngBounds&, uint8_t z); diff --git a/test/util/tile_cover.test.cpp b/test/util/tile_cover.test.cpp index 535029d1d4ed..a84119d2da36 100644 --- a/test/util/tile_cover.test.cpp +++ b/test/util/tile_cover.test.cpp @@ -44,7 +44,7 @@ TEST(TileCover, Pitch) { .withPitch(40.0)); EXPECT_EQ((std::vector{{2, 1, 1}, {2, 2, 1}, {2, 1, 2}, {2, 2, 2}}), - util::tileCover(transform.getState(), 2)); + util::tileCover({transform.getState()}, 2)); } TEST(TileCover, PitchIssue15442) { @@ -62,7 +62,7 @@ TEST(TileCover, PitchIssue15442) { EXPECT_EQ((std::vector{ {2, 3, 1}, {2, 2, 1}, {2, 3, 0}, {2, 2, 0}, {2, 1, {2, 0, 0}}, {2, 1, {2, 1, 0}}}), - util::tileCover(transform.getState(), 2)); + util::tileCover({transform.getState()}, 2)); } TEST(TileCover, PitchOverAllowedByContentInsets) { @@ -80,7 +80,7 @@ TEST(TileCover, PitchOverAllowedByContentInsets) { EXPECT_EQ( (std::vector{{3, 4, 3}, {3, 3, 3}, {3, 4, 4}, {3, 3, 4}, {3, 4, 2}, {3, 5, 3}, {3, 5, 2}}), - util::tileCover(transform.getState(), 3)); + util::tileCover({transform.getState()}, 3)); } TEST(TileCover, PitchWithLargerResultSet) { @@ -96,7 +96,7 @@ TEST(TileCover, PitchWithLargerResultSet) { .withBearing(-142.2630000003529176) .withPitch(60.0)); - auto cover = util::tileCover(transform.getState(), 5); + auto cover = util::tileCover({transform.getState()}, 5); // Returned vector has above 100 elements, we check first 16 as there is a // plan to return lower LOD for distant tiles. EXPECT_EQ((std::vector{{5, 15, 16}, @@ -148,7 +148,7 @@ TEST(TileCover, CoordinatesAreUnwrapped) { EXPECT_EQ( (std::vector{{1, 0, {1, 1, 0}}, {1, 1, {1, 0, 0}}, {1, 0, {1, 1, 1}}, {1, 1, {1, 0, 1}}}), - util::tileCover(transform.getState(), 1)); + util::tileCover({transform.getState()}, 1)); } TEST(TileCover, DifferentOverscaledZ) { @@ -165,7 +165,7 @@ TEST(TileCover, DifferentOverscaledZ) { EXPECT_EQ( (std::vector{{3, 0, {2, 1, 1}}, {3, 0, {2, 2, 1}}, {3, 0, {2, 1, 2}}, {3, 0, {2, 2, 2}}}), - util::tileCover(transform.getState(), 2, 3)); + util::tileCover({transform.getState()}, 2, 3)); } TEST(TileCover, DifferentOverscaledZWithPitch) { @@ -186,7 +186,7 @@ TEST(TileCover, DifferentOverscaledZWithPitch) { {5, 0, {3, 3, 1}}, {5, 0, {3, 4, 1}}, {5, 0, {3, 2, 1}}}), - util::tileCover(transform.getState(), 3, 5)); + util::tileCover({transform.getState()}, 3, 5)); } TEST(TileCover, DifferentOverscaledZWrapped) { @@ -201,7 +201,7 @@ TEST(TileCover, DifferentOverscaledZWrapped) { EXPECT_EQ( (std::vector{{2, 0, {1, 1, 0}}, {2, 1, {1, 0, 0}}, {2, 0, {1, 1, 1}}, {2, 1, {1, 0, 1}}}), - util::tileCover(transform.getState(), 1, 2)); + util::tileCover({transform.getState()}, 1, 2)); } TEST(TileCover, FlippedY) { @@ -216,7 +216,7 @@ TEST(TileCover, FlippedY) { .withZoom(1.0)); EXPECT_EQ((std::vector{{1, 0, 0}, {1, 1, 0}, {1, 0, 1}, {1, 1, 1}}), - util::tileCover(transform.getState(), 1)); + util::tileCover({transform.getState()}, 1)); } TEST(TileCover, FlippedYPitch) { @@ -233,7 +233,7 @@ TEST(TileCover, FlippedYPitch) { .withPitch(40.0)); EXPECT_EQ((std::vector{{2, 1, 1}, {2, 2, 1}, {2, 1, 2}, {2, 2, 2}}), - util::tileCover(transform.getState(), 2)); + util::tileCover({transform.getState()}, 2)); } TEST(TileCover, FlippedYHelsinki) { @@ -248,7 +248,7 @@ TEST(TileCover, FlippedYHelsinki) { .withZoom(11.447425)); EXPECT_EQ((std::vector{{11, 1165, 592}, {11, 1166, 592}, {11, 1165, 593}, {11, 1166, 593}}), - util::tileCover(transform.getState(), 11)); + util::tileCover({transform.getState()}, 11)); } TEST(TileCoverStream, Arctic) { From d474130183ab54929ffd6fb6435c142ec610427a Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 19 Feb 2025 13:47:07 +0300 Subject: [PATCH 042/221] expose camera based lod controls to iOS --- platform/ios/src/MLNMapView.h | 43 ++++++++++++++++++++++++++++++++++ platform/ios/src/MLNMapView.mm | 40 +++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/platform/ios/src/MLNMapView.h b/platform/ios/src/MLNMapView.h index 395c58efb2d5..1835042550aa 100644 --- a/platform/ios/src/MLNMapView.h +++ b/platform/ios/src/MLNMapView.h @@ -426,6 +426,49 @@ MLN_EXPORT @property (nonatomic, assign) BOOL tileCacheEnabled; +// MARK: Camera based tile level of detail controls + +/** + Minimum radius around the view point in unit of tiles in which the fine + grained zoom level tiles are always used when performing LOD + radius must be greater than 1 (At least 1 fine detailed tile is present) + A smaller radius value may improve performance at the cost of quality (tiles away from + camera use lower Zoom levels) + */ + +@property (nonatomic, assign) double tileLodMinRadius; + +/** + factor for the distance to the camera view point + A value larger than 1 increases the distance to the camera view point reducing LOD + Larger values may improve performance at the cost of quality (tiles away from camera + use lower Zoom levels) + */ + +@property (nonatomic, assign) double tileLodScale; + +/** + pitch angle in radians above which LOD calculation is performed + A smaller radius value may improve performance at the cost of quality + */ + +@property (nonatomic, assign) double tileLodPitchThreshold; + +/** + Shift applied to the Zoom level during LOD calculation + A negative value shifts the Zoom level to a coarser level reducing quality but + improving performance + A positive value shifts the Zoom level to a finer level increasing details but + negatively affecting performance + A value of zero (default) does not apply any shift to the Zoom level + It is not recommended to change the default value unless performance is critical + and the loss of quality is acceptable. A value of -1 reduces the number of + displayed tiles by a factor of 4 on average + It is recommended to first configure the pixelRatio before adjusting + TileLodZoomShift. {@link MapLibreMapOptions#pixelRatio(float)} + */ +@property (nonatomic, assign) double tileLodZoomShift; + // MARK: Displaying the User’s Location /** diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index e5329c80915b..35525bf0f9d6 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -3159,6 +3159,46 @@ - (BOOL)tileCacheEnabled return _rendererFrontend->getTileCacheEnabled(); } +- (void)setTileLodMinRadius:(double)radius +{ + self.mbglMap.setTileLodMinRadius(radius); +} + +- (double)tileLodMinRadius +{ + return self.mbglMap.getTileLodMinRadius(); +} + +- (void)setTileLodScale:(double)scale +{ + self.mbglMap.setTileLodScale(scale); +} + +- (double)tileLodScale +{ + return self.mbglMap.getTileLodScale(); +} + +- (void)setTileLodPitchThreshold:(double)threshold +{ + self.mbglMap.setTileLodPitchThreshold(threshold); +} + +- (double)tileLodPitchThreshold +{ + return self.mbglMap.getTileLodPitchThreshold(); +} + +- (void)setTileLodZoomShift:(double)shift +{ + self.mbglMap.setTileLodZoomShift(shift); +} + +- (double)tileLodZoomShift +{ + return self.mbglMap.getTileLodZoomShift(); +} + // MARK: - Accessibility - - (NSString *)accessibilityValue From 7b2dff69663d9b821c42991bf628dac4ff799673 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 19 Feb 2025 13:48:26 +0300 Subject: [PATCH 043/221] increment version for release 6.8.5 ios and 11.6.2 android --- platform/android/MapLibreAndroid/gradle.properties | 2 +- platform/ios/VERSION | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/android/MapLibreAndroid/gradle.properties b/platform/android/MapLibreAndroid/gradle.properties index 40eb27e5d79e..2651115244b7 100644 --- a/platform/android/MapLibreAndroid/gradle.properties +++ b/platform/android/MapLibreAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=11.8.5 +VERSION_NAME=11.6.2 # Only build native dependencies for the current ABI # See https://code.google.com/p/android/issues/detail?id=221098#c20 diff --git a/platform/ios/VERSION b/platform/ios/VERSION index 9ffc8cfb6caa..d3ce71d95844 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.8.4 +6.8.5 From 96d58bb98225f23a0b45c2693e84390cbc08bb50 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Sun, 9 Mar 2025 19:12:49 +0300 Subject: [PATCH 044/221] add changelog details for android release --- platform/android/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index cabe0244f008..b52fb2cae790 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -100,6 +100,11 @@ Thanks to everyone who helped test the pre-releases! ### 🐞 Bug fixes - Fix crash on unsupported attribute type conversion ([#3066](https://github.com/maplibre/maplibre-native/pull/3066)). +## 11.6.2 + +### Features and Improvements + +- Add LoD Support ## 11.6.1 From 27070a7b866b34d303eb4f795e6066f3e56c1150 Mon Sep 17 00:00:00 2001 From: Bart Louwers Date: Wed, 26 Feb 2025 12:53:08 +0100 Subject: [PATCH 045/221] Add .git and other directories to .bazelignore (#3255) --- .bazelignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.bazelignore b/.bazelignore index bbb6d1890679..690b96edccbb 100644 --- a/.bazelignore +++ b/.bazelignore @@ -9,7 +9,12 @@ node_modules bazel-out bazel-bin bazel-testlogs +node_modules +.git .cache .idea .vscode +build +/build-* +node_modules .cxx From 2517b9c1640ec6c1dc980a244d4f51b894a211c0 Mon Sep 17 00:00:00 2001 From: Bart Louwers Date: Wed, 26 Feb 2025 15:22:47 +0100 Subject: [PATCH 046/221] Fix .bazelignore (#3257) --- .bazelignore | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.bazelignore b/.bazelignore index 690b96edccbb..1e206a96e8c1 100644 --- a/.bazelignore +++ b/.bazelignore @@ -9,12 +9,7 @@ node_modules bazel-out bazel-bin bazel-testlogs -node_modules -.git .cache .idea .vscode -build -/build-* -node_modules -.cxx +.cxx \ No newline at end of file From 539fd6b25e87d2cbc56a6ea05c9f7f5a5d4a2183 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 13 Mar 2025 13:52:45 +0300 Subject: [PATCH 047/221] clamp zoom level to transform state min and max instead of source's min and max --- src/mbgl/renderer/tile_pyramid.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp index efe0d6f94eb8..2c62ec348c29 100644 --- a/src/mbgl/renderer/tile_pyramid.cpp +++ b/src/mbgl/renderer/tile_pyramid.cpp @@ -90,8 +90,9 @@ void TilePyramid::update(const std::vector>& l handleWrapJump(static_cast(parameters.transformState.getLatLng().longitude())); // Optionally shift the zoom level - double zoom = util::clamp( - parameters.transformState.getZoom() + parameters.tileLodZoomShift, zoomRange.min, zoomRange.max); + double zoom = util::clamp(parameters.transformState.getZoom() + parameters.tileLodZoomShift, + parameters.transformState.getMinZoom(), + parameters.transformState.getMaxZoom()); const auto type = sourceImpl.type; // Determine the overzooming/underzooming amounts and required tiles. From 9292b51e0cf1f0e069dfff800a340aec54ddd2ab Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 13 Mar 2025 14:06:20 +0300 Subject: [PATCH 048/221] prepare android and ios release --- platform/android/CHANGELOG.md | 9 +++++++++ platform/android/MapLibreAndroid/gradle.properties | 2 +- platform/ios/VERSION | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index b52fb2cae790..15d4ce07fb94 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -100,6 +100,15 @@ Thanks to everyone who helped test the pre-releases! ### 🐞 Bug fixes - Fix crash on unsupported attribute type conversion ([#3066](https://github.com/maplibre/maplibre-native/pull/3066)). +## 11.6.3 + +## Features and improvements + +### Bug fixes + +- LoD Clamping fixed to be based on view range and not source range to support over/under zooming +- Disable depth writing for the location indicator layer + ## 11.6.2 ### Features and Improvements diff --git a/platform/android/MapLibreAndroid/gradle.properties b/platform/android/MapLibreAndroid/gradle.properties index 2651115244b7..942dc1265f07 100644 --- a/platform/android/MapLibreAndroid/gradle.properties +++ b/platform/android/MapLibreAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=11.6.2 +VERSION_NAME=11.6.3 # Only build native dependencies for the current ABI # See https://code.google.com/p/android/issues/detail?id=221098#c20 diff --git a/platform/ios/VERSION b/platform/ios/VERSION index d3ce71d95844..519779faa79b 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.8.5 +6.8.6 From 619ae596421020c16f4aa63268b2de6e451b695a Mon Sep 17 00:00:00 2001 From: Mohammad Alhomaid Date: Sat, 15 Mar 2025 05:45:31 +0300 Subject: [PATCH 049/221] Update ios-ci.yml: remove tj-actions/changed-files --- .github/workflows/ios-ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ios-ci.yml b/.github/workflows/ios-ci.yml index 299ccd801197..5aa371f11c2a 100644 --- a/.github/workflows/ios-ci.yml +++ b/.github/workflows/ios-ci.yml @@ -40,12 +40,12 @@ jobs: with: submodules: recursive - - name: Get all iOS files that have changed - if: github.event_name != 'workflow_dispatch' - id: changed-files-yaml - uses: tj-actions/changed-files@v45 - with: - files_yaml_from_source_file: .github/changed-files.yml + # - name: Get all iOS files that have changed + # if: github.event_name != 'workflow_dispatch' + # id: changed-files-yaml + # uses: tj-actions/changed-files@v45 + # with: + # files_yaml_from_source_file: .github/changed-files.yml - name: Run step if test file(s) change if: steps.changed-files-yaml.outputs.ios_any_modified == 'true' From f0501546da055a83530010e9fa6e4472fffdc583 Mon Sep 17 00:00:00 2001 From: Mohammad Alhomaid Date: Sat, 15 Mar 2025 05:48:46 +0300 Subject: [PATCH 050/221] Update android-ci.yml: remove tj-actions/changed-files --- .github/workflows/android-ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/android-ci.yml b/.github/workflows/android-ci.yml index c121ca7bc01d..c9a8508a725b 100644 --- a/.github/workflows/android-ci.yml +++ b/.github/workflows/android-ci.yml @@ -27,12 +27,12 @@ jobs: with: submodules: recursive - - name: Get all Android files that have changed - if: github.event_name != 'workflow_dispatch' - id: changed-files - uses: tj-actions/changed-files@v45 - with: - files_yaml_from_source_file: .github/changed-files.yml + # - name: Get all Android files that have changed + # if: github.event_name != 'workflow_dispatch' + # id: changed-files + # uses: tj-actions/changed-files@v45 + # with: + # files_yaml_from_source_file: .github/changed-files.yml android-build: runs-on: ubuntu-24.04 From 47a8e94ddffb7c4bfa2e9d6a3227ecdadec3b2d9 Mon Sep 17 00:00:00 2001 From: Mohammad Alhomaid Date: Sat, 15 Mar 2025 05:50:07 +0300 Subject: [PATCH 051/221] Update linux-ci.yml: remove tj-actions/changed-files --- .github/workflows/linux-ci.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/linux-ci.yml b/.github/workflows/linux-ci.yml index 4b888d5d947d..b56d96426412 100644 --- a/.github/workflows/linux-ci.yml +++ b/.github/workflows/linux-ci.yml @@ -34,13 +34,12 @@ jobs: with: submodules: recursive - - name: Get all Linux files that have changed - if: github.event_name != 'workflow_dispatch' - id: changed-files - - uses: tj-actions/changed-files@v45 - with: - files_yaml_from_source_file: .github/changed-files.yml + # - name: Get all Linux files that have changed + # if: github.event_name != 'workflow_dispatch' + # id: changed-files + # uses: tj-actions/changed-files@v45 + # with: + # files_yaml_from_source_file: .github/changed-files.yml - name: List changed files if: steps.changed-files.outputs.linux_any_modified == 'true' From ce4298ce82bbd9cdedb955dff059e30a4187281a Mon Sep 17 00:00:00 2001 From: Mohammad Alhomaid Date: Sat, 15 Mar 2025 05:50:56 +0300 Subject: [PATCH 052/221] Update windows-ci.yml: remove tj-actions/changed-files --- .github/workflows/windows-ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/windows-ci.yml b/.github/workflows/windows-ci.yml index dfa76d88cd14..12410872b303 100644 --- a/.github/workflows/windows-ci.yml +++ b/.github/workflows/windows-ci.yml @@ -39,12 +39,12 @@ jobs: with: submodules: recursive - - name: Get all Windows files that have changed - if: github.event_name != 'workflow_dispatch' - id: changed-files - uses: tj-actions/changed-files@v45 - with: - files_yaml_from_source_file: .github/changed-files.yml + # - name: Get all Windows files that have changed + # if: github.event_name != 'workflow_dispatch' + # id: changed-files + # uses: tj-actions/changed-files@v45 + # with: + # files_yaml_from_source_file: .github/changed-files.yml - name: List changed files if: steps.changed-files.outputs.windows_any_modified == 'true' From 536f00616112379c99d063e2414d7ea82c06bf2b Mon Sep 17 00:00:00 2001 From: Mohammad Alhomaid Date: Sat, 15 Mar 2025 06:08:05 +0300 Subject: [PATCH 053/221] Update ios-ci.yml: remove tj-actions/changed-files --- .github/workflows/ios-ci.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ios-ci.yml b/.github/workflows/ios-ci.yml index 5aa371f11c2a..834f10a214fb 100644 --- a/.github/workflows/ios-ci.yml +++ b/.github/workflows/ios-ci.yml @@ -213,11 +213,11 @@ jobs: submodules: recursive fetch-depth: 0 - - name: VERSION file changed - id: version-file-ios-changed - uses: tj-actions/changed-files@v45 - with: - files: platform/ios/VERSION + # - name: VERSION file changed + # id: version-file-ios-changed + # uses: tj-actions/changed-files@v45 + # with: + # files: platform/ios/VERSION # Make Metal XCFramework release - name: Should make release? From 5b3b36dbe6b5c9b48b0751eb0ea60104982ccb8a Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Sun, 16 Mar 2025 13:30:51 +0300 Subject: [PATCH 054/221] replace tj-actions/chagned-files with step-security/changed-files Also pinned to a specific git commit to avoid any future compromises --- .github/workflows/android-ci.yml | 12 ++++++------ .github/workflows/ios-ci.yml | 22 +++++++++++----------- .github/workflows/linux-ci.yml | 12 ++++++------ .github/workflows/windows-ci.yml | 12 ++++++------ 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/.github/workflows/android-ci.yml b/.github/workflows/android-ci.yml index c9a8508a725b..dbab5b2b6989 100644 --- a/.github/workflows/android-ci.yml +++ b/.github/workflows/android-ci.yml @@ -27,12 +27,12 @@ jobs: with: submodules: recursive - # - name: Get all Android files that have changed - # if: github.event_name != 'workflow_dispatch' - # id: changed-files - # uses: tj-actions/changed-files@v45 - # with: - # files_yaml_from_source_file: .github/changed-files.yml + - name: Get all Android files that have changed + if: github.event_name != 'workflow_dispatch' + id: changed-files + uses: step-security/changed-files@3dbe17c78367e7d60f00d78ae6781a35be47b4a1 + with: + files_yaml_from_source_file: .github/changed-files.yml android-build: runs-on: ubuntu-24.04 diff --git a/.github/workflows/ios-ci.yml b/.github/workflows/ios-ci.yml index 834f10a214fb..b540c67c8ca4 100644 --- a/.github/workflows/ios-ci.yml +++ b/.github/workflows/ios-ci.yml @@ -40,12 +40,12 @@ jobs: with: submodules: recursive - # - name: Get all iOS files that have changed - # if: github.event_name != 'workflow_dispatch' - # id: changed-files-yaml - # uses: tj-actions/changed-files@v45 - # with: - # files_yaml_from_source_file: .github/changed-files.yml + - name: Get all iOS files that have changed + if: github.event_name != 'workflow_dispatch' + id: changed-files-yaml + uses: step-security/changed-files@3dbe17c78367e7d60f00d78ae6781a35be47b4a1 + with: + files_yaml_from_source_file: .github/changed-files.yml - name: Run step if test file(s) change if: steps.changed-files-yaml.outputs.ios_any_modified == 'true' @@ -213,11 +213,11 @@ jobs: submodules: recursive fetch-depth: 0 - # - name: VERSION file changed - # id: version-file-ios-changed - # uses: tj-actions/changed-files@v45 - # with: - # files: platform/ios/VERSION + - name: VERSION file changed + id: version-file-ios-changed + uses: step-security/changed-files@3dbe17c78367e7d60f00d78ae6781a35be47b4a1 + with: + files: platform/ios/VERSION # Make Metal XCFramework release - name: Should make release? diff --git a/.github/workflows/linux-ci.yml b/.github/workflows/linux-ci.yml index b56d96426412..2b20422596d3 100644 --- a/.github/workflows/linux-ci.yml +++ b/.github/workflows/linux-ci.yml @@ -34,12 +34,12 @@ jobs: with: submodules: recursive - # - name: Get all Linux files that have changed - # if: github.event_name != 'workflow_dispatch' - # id: changed-files - # uses: tj-actions/changed-files@v45 - # with: - # files_yaml_from_source_file: .github/changed-files.yml + - name: Get all Linux files that have changed + if: github.event_name != 'workflow_dispatch' + id: changed-files + uses: step-security/changed-files@3dbe17c78367e7d60f00d78ae6781a35be47b4a1 + with: + files_yaml_from_source_file: .github/changed-files.yml - name: List changed files if: steps.changed-files.outputs.linux_any_modified == 'true' diff --git a/.github/workflows/windows-ci.yml b/.github/workflows/windows-ci.yml index 12410872b303..f82c2b4b4f29 100644 --- a/.github/workflows/windows-ci.yml +++ b/.github/workflows/windows-ci.yml @@ -39,12 +39,12 @@ jobs: with: submodules: recursive - # - name: Get all Windows files that have changed - # if: github.event_name != 'workflow_dispatch' - # id: changed-files - # uses: tj-actions/changed-files@v45 - # with: - # files_yaml_from_source_file: .github/changed-files.yml + - name: Get all Windows files that have changed + if: github.event_name != 'workflow_dispatch' + id: changed-files + uses: step-security/changed-files@3dbe17c78367e7d60f00d78ae6781a35be47b4a1 + with: + files_yaml_from_source_file: .github/changed-files.yml - name: List changed files if: steps.changed-files.outputs.windows_any_modified == 'true' From 585c56fa4cfdcdcde40328f9393149f447d71942 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 3 Apr 2025 05:01:45 +0300 Subject: [PATCH 055/221] make new release with latest maplibre changes --- .bazelignore | 2 +- platform/android/Makefile | 2 +- .../android/MapLibreAndroid/gradle.properties | 2 +- platform/darwin/src/gltf/GLTFModelLayer.mm | 85 ++++++++------- platform/darwin/src/gltf/MetalRenderer.mm | 100 +++++++++--------- platform/glfw/glfw_view.cpp | 2 +- platform/ios/VERSION | 2 +- 7 files changed, 97 insertions(+), 98 deletions(-) diff --git a/.bazelignore b/.bazelignore index 1e206a96e8c1..bbb6d1890679 100644 --- a/.bazelignore +++ b/.bazelignore @@ -12,4 +12,4 @@ bazel-testlogs .cache .idea .vscode -.cxx \ No newline at end of file +.cxx diff --git a/platform/android/Makefile b/platform/android/Makefile index 6cf8a85d3283..c6aedaf805ed 100644 --- a/platform/android/Makefile +++ b/platform/android/Makefile @@ -247,7 +247,7 @@ run-android-test-app-center: # Uploads the compiled Android SDK to Maven Central Staging .PHONY: run-android-publish run-android-publish: - $(MLN_ANDROID_GRADLE_SINGLE_JOB) -Pmaplibre.abis=all publish + $(MLN_ANDROID_GRADLE_SINGLE_JOB) -Pmaplibre.abis=all publish # Dump system graphics information for the test app .PHONY: android-gfxinfo diff --git a/platform/android/MapLibreAndroid/gradle.properties b/platform/android/MapLibreAndroid/gradle.properties index 942dc1265f07..40eb27e5d79e 100644 --- a/platform/android/MapLibreAndroid/gradle.properties +++ b/platform/android/MapLibreAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=11.6.3 +VERSION_NAME=11.8.5 # Only build native dependencies for the current ABI # See https://code.google.com/p/android/issues/detail?id=221098#c20 diff --git a/platform/darwin/src/gltf/GLTFModelLayer.mm b/platform/darwin/src/gltf/GLTFModelLayer.mm index b21e7e46a7f2..b71972d27d46 100644 --- a/platform/darwin/src/gltf/GLTFModelLayer.mm +++ b/platform/darwin/src/gltf/GLTFModelLayer.mm @@ -40,7 +40,7 @@ -(id)init { @interface GLTFModelLayer () { std::shared_ptr _metalEnvironment; std::shared_ptr _manager; - + } @property NSMutableArray *models; @@ -66,7 +66,7 @@ simd_float4x4 toSimdMatrix4F(const MLNMatrix4 & mlMatrix) { double m30, m31, m32, m33; } MLNMatrix4; */ - + tempResult.columns[0][0] = mlMatrix.m00; tempResult.columns[0][1] = mlMatrix.m01; tempResult.columns[0][2] = mlMatrix.m02; @@ -84,7 +84,7 @@ simd_float4x4 toSimdMatrix4F(const MLNMatrix4 & mlMatrix) { tempResult.columns[3][2] = mlMatrix.m32; tempResult.columns[3][3] = mlMatrix.m33; - + return tempResult; } @@ -101,7 +101,7 @@ simd_double4x4 toSimdMatrix4D(const MLNMatrix4 & mlMatrix) { double m30, m31, m32, m33; } MLNMatrix4; */ - + tempResult.columns[0][0] = mlMatrix.m00; tempResult.columns[0][1] = mlMatrix.m01; tempResult.columns[0][2] = mlMatrix.m02; @@ -119,7 +119,7 @@ simd_double4x4 toSimdMatrix4D(const MLNMatrix4 & mlMatrix) { tempResult.columns[3][2] = mlMatrix.m32; tempResult.columns[3][3] = mlMatrix.m33; - + return tempResult; } @@ -137,32 +137,32 @@ -(id)initWithIdentifier:(NSString *)identifier { } - (void)didMoveToMapView:(MLNMapView *)mapView { - + } // This sets the relative light position for all the models being rendered // The light position is in meters from the origin of the model. -(void)setLightPositionX:(float)x y:(float)y z:(float)z { - + self.lightSet = YES; self.lightX = x; self.lightY = y; self.lightZ = z; - + if (_metalEnvironment != nullptr) { _metalEnvironment->_lightDirection = simd_make_float3(_lightX, _lightY, _lightZ); } - + } -(void)loadModels { - + // This goes through the model array and loads whatever hasn't been loaded already for (GLTFModelMetadata *m in self.models) { [self addModel:m]; } - + /* @{@"modelURL":@"al_awwal_v02.glb",@"lat":@(24.729326775575686),@"lon":@(46.623841518553355),@"rot":@(0)}, @{@"modelURL":@"alawwalpark-03.glb",@"lat":@(24.729326775575686),@"lon":@(46.623841518553355),@"rot":@(0)}, @@ -173,7 +173,7 @@ -(void)loadModels { @{@"modelURL":@"turaif-03-bl.glb",@"lat":@(24.733690223733547),@"lon":@(46.57492745287205),@"rot":@(0)}, @{@"modelURL":@"tvtower_009.glb",@"lat":@(24.643391710253425),@"lon":@(46.69595652756665),@"rot":@(0)}, */ - + //[self loadModel:@"alawwalpark-03.glb" lat:24.729326775575686 lon:46.623841518553355 rotationDeg:90]; /* [self loadModel:@"Al_faisaliyah_007.glb" lat:24.69052042910012 lon:46.6856124145449 rotationDeg:-65]; @@ -182,7 +182,7 @@ -(void)loadModels { [self loadModel:@"turaif-03-bl.glb" lat:24.733690223733547 lon:46.57492745287205 rotationDeg:0]; [self loadModel:@"tvtower_009.glb" lat:24.643391710253425 lon:46.69595652756665 rotationDeg:0]; - + [self loadModel:@"KAFD_Building01_v01.glb" lat:24.76592011755998 lon:46.64337787824368 rotationDeg:0]; [self loadModel:@"KAFD_Building02_v01.glb" lat:24.76592011755998 lon:46.64337787824368 rotationDeg:0]; [self loadModel:@"KAFD_Building06_v02.glb" lat:24.76592011755998 lon:46.64337787824368 rotationDeg:0]; @@ -193,7 +193,7 @@ -(void)loadModels { } -(void)loadModelFromJSON:(NSString *)modelMetadataFilename { - + NSError *error = nil; NSData *dat = [NSData dataWithContentsOfFile:modelMetadataFilename]; NSDictionary *d = [NSJSONSerialization JSONObjectWithData:dat @@ -201,7 +201,7 @@ -(void)loadModelFromJSON:(NSString *)modelMetadataFilename { error:&error]; NSArray *models = [d objectForKey:@"models"]; for (NSDictionary *model in models) { - + NSString *modelFilename = [model objectForKey:@"name"]; double lat = [[model objectForKey:@"lat"] doubleValue]; double lon = [[model objectForKey:@"lon"] doubleValue]; @@ -219,7 +219,7 @@ -(void)loadModelFromJSON:(NSString *)modelMetadataFilename { scaleFactor:scale brightness:brightnessCoefficient]; } - + } @@ -229,11 +229,11 @@ -(void)loadModel:(NSString *)appResourceFilename rotationDeg:(double)rotationDeg scaleFactor:(float)scaleFactor brightness:(float)brightness { - + if (brightness == 0) { brightness = 1.0; } - + GLTFModelMetadata *modelMetadata = [[GLTFModelMetadata alloc] init]; modelMetadata.modelPath = appResourceFilename; modelMetadata.modelCoordinate = CLLocationCoordinate2DMake(lat, lon); @@ -242,25 +242,25 @@ -(void)loadModel:(NSString *)appResourceFilename modelMetadata.brightness = brightness; [self.models addObject:modelMetadata]; - + if (self.managerCreated) { [self addModel:modelMetadata]; } - + } -(void)addModel:(GLTFModelMetadata *)modelMetadata { - + if (modelMetadata.modelLoaded) { return; } - + NSURL *fileURL = [[NSBundle mainBundle] URLForResource:modelMetadata.modelPath withExtension:nil]; - + std::string modelURL = [[fileURL absoluteString] UTF8String]; - + std::shared_ptr model = std::make_shared(); model->_referenceLat = modelMetadata.modelCoordinate.latitude; model->_referenceLon = modelMetadata.modelCoordinate.longitude; @@ -269,40 +269,40 @@ -(void)addModel:(GLTFModelMetadata *)modelMetadata { model->_brightness = modelMetadata.brightness; model->_scaleFactor = modelMetadata.modelScale; // model->_scaleFactor = 1.0; // Models are in meters - + _manager->addModel(model); - + modelMetadata.modelLoaded = YES; - + } - (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingContext)context { - - MLNBackendResource resource = [mapView backendResource]; - + + MLNBackendResource* resource = [mapView backendResource]; + bool loadModels = false; - + if (_manager == nullptr) { - + // Setup the metal environment for the model rendering _metalEnvironment = std::make_shared(); if (self.lightSet) { _metalEnvironment->_lightDirection = simd_make_float3(_lightX, _lightY, _lightZ); } - + // Create the GLTF Manager _manager = std::make_shared(RenderingEnvironmentMetal); _manager->setRenderingEnvironmentVariables(_metalEnvironment); - + _manager->setProjectionCallback(^Cartesian3D(const Coordinate2D & coordinate){ Cartesian3D tempResult; - + tempResult._x = 5198170.102753558; tempResult._y = 2832006.4886368043; tempResult._z = 0; - + tempResult._x = coordinate._lon * DEG_RAD; double lat = coordinate._lat * DEG_RAD; tempResult._y = log((1.0f+sin(lat))/cos(lat)); @@ -312,10 +312,10 @@ - (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingCon tempResult._y = tempResult._y * metersScale / M_PI; return tempResult; }); - + loadModels = true; } - + _metalEnvironment->_currentFOVDEG = context.fieldOfView * RAD_DEG; _metalEnvironment->_currentProjectionMatrix = toSimdMatrix4D(context.nearClippedProjMatrix); _metalEnvironment->_currentZoomLevel = context.zoomLevel; @@ -330,22 +330,22 @@ - (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingCon if (self.lightSet) { _metalEnvironment->_lightDirection = simd_make_float3(_lightX, _lightY, _lightZ); } - + // TODO: Remove this.. This is legacy _manager->setRenderingEnvironmentVariables(_metalEnvironment); if (loadModels) { [self loadModels]; } - + vector_uint2 _viewportSize; _viewportSize.x = resource.mtkView.drawableSize.width; _viewportSize.y = resource.mtkView.drawableSize.height; _manager->setDrawableSize(_viewportSize.x, _viewportSize.y); - + float timestep = (1 / 60.0f); _manager->updateScene(timestep); - + // Render the image _manager->render(); } @@ -355,4 +355,3 @@ - (void)willMoveFromMapView:(MLNMapView *)mapView { } @end - diff --git a/platform/darwin/src/gltf/MetalRenderer.mm b/platform/darwin/src/gltf/MetalRenderer.mm index 295035cc0acf..1a21692ea38e 100644 --- a/platform/darwin/src/gltf/MetalRenderer.mm +++ b/platform/darwin/src/gltf/MetalRenderer.mm @@ -30,7 +30,7 @@ if (_metalDevice == device) { return; } - + _metalDevice = device; setupMetal(); } @@ -58,15 +58,15 @@ // Update any animations void MetalRenderer::update(float timeSinceLastDraw) { - + // Update the global time _globalTime += timeSinceLastDraw; - + // If we don't have an asset, then bail if (_models.size() == 0) { return; } - + double maxAnimDuration = 0; for (auto m: _models) { for (GLTFAnimation *animation in m->_asset.animations) { @@ -77,19 +77,19 @@ } } } - + double animTime = fmod(_globalTime, maxAnimDuration); for (auto m: _models) { for (GLTFAnimation *animation in m->_asset.animations) { [animation runAtTime:animTime]; } } - + _camera->updateWithTimestep(timeSinceLastDraw); for (auto m: _models) { computeTransforms(m); } - + } // Render @@ -102,13 +102,13 @@ double worldSize = (tileSize / scaleFactor) * pow(2.0, zoom); simd_double4x4 scaleMatrix = GLTFMatrixFromScaleD(simd_make_double3(worldSize, -worldSize, 1.0)); simd_double4x4 xlateMatrix = GLTFMatrixFromTranslationD(simd_make_double3(20037508.34,-20037508.34,0.0)); - + auto m1 = matrix_multiply(scaleMatrix, xlateMatrix); auto m2 = matrix_multiply(environmentMVP, m1); _projectionMatrix = m2; // id internalCommandBuffer = [_internalMetalCommandQueue commandBuffer]; -// +// // if (_existingCommandBuffer) { // commandBuffer = _metalRenderingEnvironment->_currentCommandBuffer; // } else { @@ -116,12 +116,12 @@ // commandBuffer = [_internalMetalCommandQueue commandBuffer]; // currentDrawable = _metalRenderingEnvironment->_currentDrawable; // } -// +// encodeMainPass(_metalRenderingEnvironment->_currentCommandBuffer); // if (_useBloomPass) { // encodeBloomPasses(internalCommandBuffer); // } - + // [internalCommandBuffer addCompletedHandler:^(id buffer) { // dispatch_async(dispatch_get_main_queue(), ^{ // signalFrameCompletion(); @@ -136,7 +136,7 @@ // Load a model void MetalRenderer::loadGLTFModel(std::shared_ptr model) { - + GLTFModelLoader *modelLoader = [[GLTFModelLoader alloc] init]; NSURL *u = [NSURL URLWithString:[NSString stringWithCString:model->_modelURL.c_str()]]; [modelLoader loadURL:u @@ -144,34 +144,34 @@ addGLTFAsset(asset, model); } bufferAllocator:_bufferAllocator]; - + } // Set the rendering environemnt variables void MetalRenderer::setRenderingEnvironemnt(std::shared_ptr renderingEnvironment) { GLTFRenderer::setRenderingEnvironemnt(renderingEnvironment); - + _metalRenderingEnvironment = std::static_pointer_cast(renderingEnvironment); - + } // RENDERING void MetalRenderer::encodeMainPass(id commandBuffer) { - + id renderEncoder = _metalRenderingEnvironment->_currentCommandEncoder; - + for (auto m: _models) { [renderEncoder pushDebugGroup:@"Draw glTF Scene"]; renderScene(m, m->_asset.defaultScene, commandBuffer, renderEncoder); [renderEncoder popDebugGroup]; } - + } void MetalRenderer::encodeBloomPasses(id commandBuffer) { - + MTLRenderPassDescriptor *pass = [MTLRenderPassDescriptor renderPassDescriptor]; pass.colorAttachments[0].texture = _bloomTextureA; pass.colorAttachments[0].loadAction = MTLLoadActionDontCare; @@ -207,7 +207,7 @@ pass.colorAttachments[0].texture = _colorTexture; pass.colorAttachments[0].loadAction = MTLLoadActionLoad; pass.colorAttachments[0].storeAction = MTLStoreActionStore; - + renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:pass]; [renderEncoder pushDebugGroup:@"Post-process (Bloom combine)"]; drawFullscreenPassWithPipeline(_additiveBlendPipelineState,renderEncoder,_bloomTextureA); @@ -216,7 +216,7 @@ } void MetalRenderer::encodeTonemappingPass(id commandBuffer) { - + if (_metalRenderingEnvironment->_currentRenderPassDescriptor == nil) { return; } @@ -226,7 +226,7 @@ drawFullscreenPassWithPipeline(_tonemapPipelineState,renderEncoder,_colorTexture); [renderEncoder popDebugGroup]; [renderEncoder endEncoding]; - + } @@ -270,7 +270,7 @@ pass.depthAttachment.texture = _metalRenderingEnvironment->_depthStencilTexture; pass.depthAttachment.loadAction = MTLLoadActionLoad; pass.depthAttachment.storeAction = MTLStoreActionStore; - + return pass; } @@ -282,22 +282,22 @@ void MetalRenderer::setupMetal() { - + _internalMetalCommandQueue = [_metalDevice newCommandQueue]; _metalLibrary = [_metalDevice newDefaultLibrary]; - + _projectionMatrix = matrix_identity_double4x4; _colorPixelFormat = MTLPixelFormatBGRA8Unorm; _depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8; _sampleCount = 1; _drawableSize = {1, 1}; - + _frameBoundarySemaphore = dispatch_semaphore_create(_maxInflightFrames); - + loadBloomPipelines(); loadTonemapPipeline(); loadDepthClearPipeline(); - + _opaqueRenderItems = [NSMutableArray array]; _transparentRenderItems = [NSMutableArray array]; _currentLightNodes = [NSMutableArray array]; @@ -312,17 +312,17 @@ _textureLoader = [[GLTFMTLTextureLoader alloc] initWithDevice:_metalDevice]; _bufferAllocator = [[GLTFMTLBufferAllocator alloc] initWithDevice:_metalDevice]; //_assets = [NSMutableArray array]; - - - - + + + + MTLDepthStencilDescriptor *fullscreenTransfterDepthStencilDescriptor = [[MTLDepthStencilDescriptor alloc] init]; fullscreenTransfterDepthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways; // Or another value as needed fullscreenTransfterDepthStencilDescriptor.depthWriteEnabled = NO; _fullscreenTransfterDepthStencilState = [_metalDevice newDepthStencilStateWithDescriptor:fullscreenTransfterDepthStencilDescriptor]; - - + + } void MetalRenderer::updateFramebufferSize() { @@ -338,7 +338,7 @@ textureDescriptor.storageMode = MTLStorageModePrivate; textureDescriptor.usage = MTLTextureUsageRenderTarget; _multisampleColorTexture = [_metalDevice newTextureWithDescriptor:textureDescriptor]; - + textureDescriptor.textureType = MTLTextureType2D; textureDescriptor.pixelFormat = _colorPixelFormat; textureDescriptor.sampleCount = 1; @@ -352,7 +352,7 @@ textureDescriptor.storageMode = MTLStorageModePrivate; textureDescriptor.usage = MTLTextureUsageRenderTarget; _depthStencilTexture = [_metalDevice newTextureWithDescriptor:textureDescriptor]; - + textureDescriptor.width = _drawableSize.x / 2; textureDescriptor.height = _drawableSize.y / 2; textureDescriptor.textureType = MTLTextureType2D; @@ -370,7 +370,7 @@ textureDescriptor.storageMode = MTLStorageModePrivate; textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; _bloomTextureB = [_metalDevice newTextureWithDescriptor:textureDescriptor]; - + //self.renderer.sampleCount = self.sampleCount; @@ -382,7 +382,7 @@ void MetalRenderer::loadBloomPipelines() { - + NSError *error = nil; MTLRenderPipelineDescriptor *descriptor = [MTLRenderPipelineDescriptor new]; descriptor.vertexFunction = [_metalLibrary newFunctionWithName:@"quad_vertex_main"]; @@ -406,7 +406,7 @@ } descriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"additive_blend_fragment_main"]; - + // Original Values descriptor.colorAttachments[0].blendingEnabled = YES; descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; @@ -424,7 +424,7 @@ descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOne; descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorDestinationAlpha; - + _additiveBlendPipelineState = [_metalDevice newRenderPipelineStateWithDescriptor:descriptor error:&error]; if (_additiveBlendPipelineState == nil) { NSLog(@"Error occurred when creating render pipeline state: %@", error); @@ -432,11 +432,11 @@ } void MetalRenderer::loadTonemapPipeline() { - + NSError *error = nil; MTLRenderPipelineDescriptor *descriptor = [MTLRenderPipelineDescriptor new]; - - + + // MT: Added blending descriptor.colorAttachments[0].blendingEnabled = YES; descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; @@ -446,20 +446,20 @@ descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha; descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha; - + id vertexFunction = [_metalLibrary newFunctionWithName:@"quad_vertex_main"]; - + descriptor.vertexFunction = vertexFunction; descriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"tonemap_fragment_main"]; descriptor.sampleCount = _sampleCount; descriptor.colorAttachments[0].pixelFormat = _colorPixelFormat; - + // TODO: This was hard coded to fix an issue whe moving to ML. Need to sort out // how these params are set in ML and pass them into here descriptor.stencilAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; descriptor.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; - - + + _tonemapPipelineState = [_metalDevice newRenderPipelineStateWithDescriptor:descriptor error:&error]; if (_tonemapPipelineState == nil) { NSLog(@"Error occurred when creating render pipeline state: %@", error); @@ -523,9 +523,9 @@ } id MetalRenderer::renderPipelineStateForSubmesh(GLTFSubmesh *submesh) { - + id pipeline = _pipelineStatesForSubmeshes[submesh.identifier]; - + if (pipeline == nil) { GLTFMTLShaderBuilder *shaderBuilder = [[GLTFMTLShaderBuilder alloc] init]; pipeline = [shaderBuilder renderPipelineStateForSubmesh: submesh diff --git a/platform/glfw/glfw_view.cpp b/platform/glfw/glfw_view.cpp index 95864f199e7d..7423ccab14af 100644 --- a/platform/glfw/glfw_view.cpp +++ b/platform/glfw/glfw_view.cpp @@ -631,7 +631,7 @@ void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action, view->freeCameraDemoStartTime = mbgl::Clock::now(); view->invalidate(); } break; - case GLFW_KEY_V: { + case GLFW_KEY_COMMA: { cycleTileLodMode(*view->map); } break; case GLFW_KEY_F7: { diff --git a/platform/ios/VERSION b/platform/ios/VERSION index 519779faa79b..f867e299309d 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.8.6 +6.12.2 From cee1ffc9ea34308fe81ee5eb8350447fec4465dc Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 3 Apr 2025 08:03:08 +0300 Subject: [PATCH 056/221] release ios 6.12.3 and android 11.8.6 --- .github/workflows/android-release.yml | 2 +- platform/android/CHANGELOG.md | 6 ++++++ platform/android/MapLibreAndroid/gradle.properties | 2 +- platform/ios/VERSION | 2 +- platform/macos/src/MLNMapView.h | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/android-release.yml b/.github/workflows/android-release.yml index f89f1cc16092..3a2610fd0b1b 100644 --- a/.github/workflows/android-release.yml +++ b/.github/workflows/android-release.yml @@ -5,7 +5,7 @@ on: jobs: build: - runs-on: MapLibre_Native_Ubuntu_24_04_x84_16_core + runs-on: ubuntu-latest defaults: run: working-directory: platform/android diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index 15d4ce07fb94..3bc7f2dbf0dd 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog MapLibre Native for Android +## 11.8.6 + +### 🐞 Bug fixes + +- Fix issue related to symbol icon scaling with offset + ## 11.8.5 ### 🐞 Bug fixes diff --git a/platform/android/MapLibreAndroid/gradle.properties b/platform/android/MapLibreAndroid/gradle.properties index 40eb27e5d79e..6f36e432f3da 100644 --- a/platform/android/MapLibreAndroid/gradle.properties +++ b/platform/android/MapLibreAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=11.8.5 +VERSION_NAME=11.8.6 # Only build native dependencies for the current ABI # See https://code.google.com/p/android/issues/detail?id=221098#c20 diff --git a/platform/ios/VERSION b/platform/ios/VERSION index f867e299309d..ffd41f5c6b29 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.12.2 +6.12.3 diff --git a/platform/macos/src/MLNMapView.h b/platform/macos/src/MLNMapView.h index 42f93147f791..f063fa81a497 100644 --- a/platform/macos/src/MLNMapView.h +++ b/platform/macos/src/MLNMapView.h @@ -1271,7 +1271,7 @@ around the returned camera object if it were set as the receiver’s camera. */ @property (nonatomic) MLNMapDebugMaskOptions debugMask; -- (MLNBackendResource)backendResource; +- (MLNBackendResource *)backendResource; @end NS_ASSUME_NONNULL_END From 19e65c5046e8da96a4e8757dc1394fd5658a331c Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Mon, 7 Apr 2025 15:41:11 +0300 Subject: [PATCH 057/221] rename android package to avoid github name conflict issue --- .../buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts index 07b5bedb68f6..2e10b2676e01 100644 --- a/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts +++ b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts @@ -52,7 +52,7 @@ fun PublishingExtension.configureMavenPublication( ) { publications { create(publicationName) { - groupId = project.group.toString() + groupId = project.group.toString().replace("org.maplibre.gl", "org.hudhud.maplibre.gl") artifactId = "${project.extra["mapLibreArtifactId"]}$artifactIdPostfix" version = project.version.toString() From a7642851ee0470612f6b4e0c24015c9a5031155b Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 16 Apr 2025 10:28:03 +0300 Subject: [PATCH 058/221] fix macos and windows builds after recent merge + github actions changes Also utilize the new arm based linux targets --- .github/workflows/node-ci.yml | 2 +- .github/workflows/windows-ci.yml | 2 +- platform/macos/src/MLNMapView+Impl.h | 2 +- platform/macos/src/MLNMapView+Metal.h | 2 +- platform/macos/src/MLNMapView+Metal.mm | 14 ++++++-------- platform/macos/src/MLNMapView.mm | 2 +- 6 files changed, 11 insertions(+), 13 deletions(-) diff --git a/.github/workflows/node-ci.yml b/.github/workflows/node-ci.yml index 6a08ef5f933f..9e2bf5f41a1e 100644 --- a/.github/workflows/node-ci.yml +++ b/.github/workflows/node-ci.yml @@ -76,7 +76,7 @@ jobs: include: - runs-on: ubuntu-22.04 arch: x86_64 - - runs-on: MapLibre_Native_Ubuntu_22_04_ARM_8_core + - runs-on: ubuntu-22.04-arm arch: arm64 - runs-on: macos-14 arch: arm64 diff --git a/.github/workflows/windows-ci.yml b/.github/workflows/windows-ci.yml index d46d4f0c5c5f..42524475439d 100644 --- a/.github/workflows/windows-ci.yml +++ b/.github/workflows/windows-ci.yml @@ -112,7 +112,7 @@ jobs: core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); - - uses: mozilla-actions/sccache-action@v0.0.8 + - uses: mozilla-actions/sccache-action@v0.0.9 - name: Initialize sccache run: | diff --git a/platform/macos/src/MLNMapView+Impl.h b/platform/macos/src/MLNMapView+Impl.h index 4ccc00a17a27..13079062667f 100644 --- a/platform/macos/src/MLNMapView+Impl.h +++ b/platform/macos/src/MLNMapView+Impl.h @@ -25,7 +25,7 @@ class MLNMapViewImpl : public mbgl::MapObserver { // Called by the view delegate when it's time to render. void render(); - virtual MLNBackendResource getObject() = 0; + virtual MLNBackendResource* getObject() = 0; // mbgl::MapObserver implementation void onCameraWillChange(mbgl::MapObserver::CameraChangeMode) override; diff --git a/platform/macos/src/MLNMapView+Metal.h b/platform/macos/src/MLNMapView+Metal.h index a366e38a1bac..9704e27a28f6 100644 --- a/platform/macos/src/MLNMapView+Metal.h +++ b/platform/macos/src/MLNMapView+Metal.h @@ -37,7 +37,7 @@ class MLNMapViewMetalImpl final : public MLNMapViewImpl, mbgl::PremultipliedImage readStillImage() override; - MLNBackendResource getObject() override; + MLNBackendResource* getObject() override; private: bool presentsWithTransaction = false; diff --git a/platform/macos/src/MLNMapView+Metal.mm b/platform/macos/src/MLNMapView+Metal.mm index b7edee233d7f..06ed7392378b 100644 --- a/platform/macos/src/MLNMapView+Metal.mm +++ b/platform/macos/src/MLNMapView+Metal.mm @@ -159,13 +159,11 @@ void swap() override { return {}; } -MLNBackendResource MLNMapViewMetalImpl::getObject() { +MLNBackendResource* MLNMapViewMetalImpl::getObject() { auto& resource = getResource(); auto renderPassDescriptor = resource.getRenderPassDescriptor().get(); - return { - resource.mtlView, - resource.mtlView.device, - [MTLRenderPassDescriptor renderPassDescriptor], - resource.commandBuffer - }; -} \ No newline at end of file + return [[MLNBackendResource alloc] initWithMTKView:resource.mtlView + device:resource.mtlView.device + renderPassDescriptor:[MTLRenderPassDescriptor renderPassDescriptor] + commandBuffer:resource.commandBuffer]; +} diff --git a/platform/macos/src/MLNMapView.mm b/platform/macos/src/MLNMapView.mm index 8b4bac3152c3..693210ffe6a1 100644 --- a/platform/macos/src/MLNMapView.mm +++ b/platform/macos/src/MLNMapView.mm @@ -3190,7 +3190,7 @@ - (void)setDebugMask:(MLNMapDebugMaskOptions)debugMask { _mbglMap->setDebug(options); } -- (MLNBackendResource)backendResource { +- (MLNBackendResource *)backendResource { return _mbglView->getObject(); } From 11cef9c3b8f64ee645eecd59b7f154bae141b6c3 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 16 Apr 2025 19:48:27 +0300 Subject: [PATCH 059/221] add easing parameters to mln transitions --- include/mbgl/style/transition_options.hpp | 9 ++++++++- include/mbgl/util/unitbezier.hpp | 12 ++++++------ .../MapLibreAndroid/src/cpp/native_map_view.cpp | 1 + platform/darwin/src/MLNStyleValue_Private.h | 8 +++++++- platform/darwin/src/MLNTypes.h | 7 ++++++- platform/darwin/test/MLNLightTest.mm.ejs | 4 ++-- platform/darwin/test/MLNStyleLayerTests.mm.ejs | 2 +- platform/darwin/test/MLNStyleTests.mm | 2 +- src/mbgl/style/properties.hpp | 9 ++++++--- 9 files changed, 38 insertions(+), 16 deletions(-) diff --git a/include/mbgl/style/transition_options.hpp b/include/mbgl/style/transition_options.hpp index 8dde72ec025f..517887edf125 100644 --- a/include/mbgl/style/transition_options.hpp +++ b/include/mbgl/style/transition_options.hpp @@ -4,6 +4,7 @@ #include +#include #include namespace mbgl { @@ -13,17 +14,23 @@ class TransitionOptions { public: std::optional duration; std::optional delay; + std::optional ease; bool enablePlacementTransitions; TransitionOptions(std::optional duration_ = std::nullopt, std::optional delay_ = std::nullopt, + std::optional ease_ = std::nullopt, bool enablePlacementTransitions_ = true) : duration(duration_ ? std::move(duration_) : std::nullopt), delay(delay_ ? std::move(delay_) : std::nullopt), + ease(ease_ ? std::move(ease_) : std::nullopt), enablePlacementTransitions(enablePlacementTransitions_) {} TransitionOptions reverseMerge(const TransitionOptions& defaults) const { - return {duration ? duration : defaults.duration, delay ? delay : defaults.delay, enablePlacementTransitions}; + return {duration ? duration : defaults.duration, + delay ? delay : defaults.delay, + ease ? ease : defaults.ease, + enablePlacementTransitions}; } bool isDefined() const { return duration || delay; } diff --git a/include/mbgl/util/unitbezier.hpp b/include/mbgl/util/unitbezier.hpp index 5b821b5a2130..074816bcad24 100644 --- a/include/mbgl/util/unitbezier.hpp +++ b/include/mbgl/util/unitbezier.hpp @@ -106,13 +106,13 @@ struct UnitBezier { } private: - const double cx; - const double bx; - const double ax; + double cx; + double bx; + double ax; - const double cy; - const double by; - const double ay; + double cy; + double by; + double ay; }; } // namespace util diff --git a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp index e26dea7e2af0..6fce0fa15870 100644 --- a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp +++ b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp @@ -880,6 +880,7 @@ void NativeMapView::setTransitionOptions(JNIEnv& env, const jni::ObjectgetStyle().setTransitionOptions(transitionOptions); } diff --git a/platform/darwin/src/MLNStyleValue_Private.h b/platform/darwin/src/MLNStyleValue_Private.h index f95638eee62a..a15c6b0b8203 100644 --- a/platform/darwin/src/MLNStyleValue_Private.h +++ b/platform/darwin/src/MLNStyleValue_Private.h @@ -19,6 +19,7 @@ #import #include +#include #include @@ -48,8 +49,13 @@ NS_INLINE MLNTransition MLNTransitionFromOptions(const mbgl::style::TransitionOp } NS_INLINE mbgl::style::TransitionOptions MLNOptionsFromTransition(MLNTransition transition) { + CAMediaTimingFunction *function = [CAMediaTimingFunction functionWithName:transition.ease]; + float p0[2], p3[2]; + [function getControlPointAtIndex:0 values:p0]; + [function getControlPointAtIndex:3 values:p3]; mbgl::style::TransitionOptions options{{MLNDurationFromTimeInterval(transition.duration)}, - {MLNDurationFromTimeInterval(transition.delay)}}; + {MLNDurationFromTimeInterval(transition.delay)}, + mbgl::util::UnitBezier({p0[0], p0[1], p3[0], p3[1]})}; return options; } diff --git a/platform/darwin/src/MLNTypes.h b/platform/darwin/src/MLNTypes.h index 8824ad4d5fc5..f2c956e44982 100644 --- a/platform/darwin/src/MLNTypes.h +++ b/platform/darwin/src/MLNTypes.h @@ -1,5 +1,6 @@ #import #import +#import #import "MLNFoundation.h" @@ -101,6 +102,8 @@ typedef struct __attribute__((objc_boxable)) MLNTransition { The amount of time in seconds to wait before beginning the animation. */ NSTimeInterval delay; + + CAMediaTimingFunctionName ease; } MLNTransition; NS_INLINE NSString *MLNStringFromMLNTransition(MLNTransition transition) { @@ -118,10 +121,12 @@ NS_INLINE NSString *MLNStringFromMLNTransition(MLNTransition transition) { @return Returns a ``MLNTransition`` struct containing the transition attributes. */ -NS_INLINE MLNTransition MLNTransitionMake(NSTimeInterval duration, NSTimeInterval delay) { +NS_INLINE MLNTransition MLNTransitionMake(NSTimeInterval duration, NSTimeInterval delay, + CAMediaTimingFunctionName ease) { MLNTransition transition; transition.duration = duration; transition.delay = delay; + transition.ease = ease; return transition; } diff --git a/platform/darwin/test/MLNLightTest.mm.ejs b/platform/darwin/test/MLNLightTest.mm.ejs index 2c481ddf6bf4..2dc120292507 100644 --- a/platform/darwin/test/MLNLightTest.mm.ejs +++ b/platform/darwin/test/MLNLightTest.mm.ejs @@ -23,8 +23,8 @@ - (void)testProperties { - MLNTransition defaultTransition = MLNTransitionMake(0, 0); - MLNTransition transition = MLNTransitionMake(6, 3); + MLNTransition defaultTransition = MLNTransitionMake(0, 0, kCAMediaTimingFunctionDefault); + MLNTransition transition = MLNTransitionMake(6, 3, kCAMediaTimingFunctionDefault); mbgl::style::TransitionOptions transitionOptions { { MLNDurationFromTimeInterval(6) }, { MLNDurationFromTimeInterval(3) } }; <% for (const property of properties) { -%> diff --git a/platform/darwin/test/MLNStyleLayerTests.mm.ejs b/platform/darwin/test/MLNStyleLayerTests.mm.ejs index 225f32128607..8c0399631e6c 100644 --- a/platform/darwin/test/MLNStyleLayerTests.mm.ejs +++ b/platform/darwin/test/MLNStyleLayerTests.mm.ejs @@ -60,7 +60,7 @@ XCTAssertEqualObjects(@(layer.rawLayer->getTypeInfo()->type), @"<%- type %>"); auto rawLayer = static_castLayer*>(layer.rawLayer); - MLNTransition transitionTest = MLNTransitionMake(5, 4); + MLNTransition transitionTest = MLNTransitionMake(5, 4, kCAMediaTimingFunctionDefault); <% for (const property of properties) { -%> <% if (property['property-type'] === 'color-ramp') continue; -%> diff --git a/platform/darwin/test/MLNStyleTests.mm b/platform/darwin/test/MLNStyleTests.mm index 5c4d69fbb799..c74e79b5731e 100644 --- a/platform/darwin/test/MLNStyleTests.mm +++ b/platform/darwin/test/MLNStyleTests.mm @@ -406,7 +406,7 @@ - (void)testLanguageMatching { - (void)testTransition { - MLNTransition transitionTest = MLNTransitionMake(5, 4); + MLNTransition transitionTest = MLNTransitionMake(5, 4, kCAMediaTimingFunctionDefault); self.style.transition = transitionTest; diff --git a/src/mbgl/style/properties.hpp b/src/mbgl/style/properties.hpp index 571da06a210d..046db61298f4 100644 --- a/src/mbgl/style/properties.hpp +++ b/src/mbgl/style/properties.hpp @@ -10,8 +10,10 @@ #include #include #include +#include #include +#include #include namespace mbgl { @@ -31,6 +33,7 @@ class Transitioning { Transitioning(Value value_, Transitioning prior_, const TransitionOptions& transition, TimePoint now) : begin(now + transition.delay.value_or(Duration::zero())), end(begin + transition.duration.value_or(Duration::zero())), + ease(transition.ease.value_or(util::DEFAULT_TRANSITION_EASE)), value(std::move(value_)) { if (transition.isDefined()) { prior = {std::move(prior_)}; @@ -60,9 +63,8 @@ class Transitioning { } else { // Interpolate between recursively-calculated prior value and final. float t = std::chrono::duration(now - begin) / (end - begin); - return util::interpolate(prior->get().evaluate(evaluator, now), - finalValue, - static_cast(util::DEFAULT_TRANSITION_EASE.solve(t, 0.001))); + return util::interpolate( + prior->get().evaluate(evaluator, now), finalValue, static_cast(ease.solve(t, 0.001))); } } @@ -81,6 +83,7 @@ class Transitioning { mutable std::optional>> prior; TimePoint begin; TimePoint end; + util::UnitBezier ease = util::DEFAULT_TRANSITION_EASE; Value value; }; From b0b20ca3b1ea7dac9c58390a4de9d32340346a0e Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 16 Apr 2025 19:50:45 +0300 Subject: [PATCH 060/221] reintroduce the location indicator layer for ios --- platform/darwin/bazel/files.bzl | 4 +++ .../darwin/scripts/generate-style-code.mjs | 17 +++++++++--- .../scripts/style-spec-overrides-v8.json | 3 +++ platform/darwin/src/MLNStyle.mm | 1 + platform/darwin/src/MLNStyleLayer.h.ejs | 6 ++--- platform/darwin/src/MLNStyleLayer.mm.ejs | 2 +- platform/darwin/src/MLNStyleLayerManager.mm | 6 +++++ platform/darwin/src/MLNStyleValue_Private.h | 27 +++++++++++++++++++ .../src/NSValue+MLNStyleAttributeAdditions.h | 2 ++ .../src/NSValue+MLNStyleAttributeAdditions.mm | 18 +++++++++++++ platform/ios/src/Mapbox.h | 1 + 11 files changed, 80 insertions(+), 7 deletions(-) diff --git a/platform/darwin/bazel/files.bzl b/platform/darwin/bazel/files.bzl index 08125a3024ad..a2a1bdeb32c4 100644 --- a/platform/darwin/bazel/files.bzl +++ b/platform/darwin/bazel/files.bzl @@ -91,6 +91,7 @@ MLN_GENERATED_DARWIN_STYLE_SOURCE = [ "src/MLNLineStyleLayer.mm", "src/MLNRasterStyleLayer.mm", "src/MLNSymbolStyleLayer.mm", + "src/MLNLocationIndicatorStyleLayer.mm", ] MLN_GENERATED_DARWIN_STYLE_PUBLIC_HEADERS = [ @@ -104,6 +105,7 @@ MLN_GENERATED_DARWIN_STYLE_PUBLIC_HEADERS = [ "src/MLNFillStyleLayer.h", "src/MLNHillshadeStyleLayer.h", "src/MLNRasterStyleLayer.h", + "src/MLNLocationIndicatorStyleLayer.h", ] MLN_GENERATED_DARWIN_STYLE_HEADERS = [ @@ -116,6 +118,7 @@ MLN_GENERATED_DARWIN_STYLE_HEADERS = [ "src/MLNCircleStyleLayer_Private.h", "src/MLNFillStyleLayer_Private.h", "src/MLNHillshadeStyleLayer_Private.h", + "src/MLNLocationIndicatorStyleLayer_Private.h", ] + MLN_GENERATED_DARWIN_STYLE_PUBLIC_HEADERS MLN_GENERATED_DARWIN_TEST_CODE = [ @@ -129,6 +132,7 @@ MLN_GENERATED_DARWIN_TEST_CODE = [ "test/MLNHillshadeStyleLayerTests.mm", "test/MLNLineStyleLayerTests.mm", "test/MLNSymbolStyleLayerTests.mm", + "test/MLNLocationIndicatorStyleLayerTests.mm", ] MLN_DARWIN_OBJC_HEADERS = [ diff --git a/platform/darwin/scripts/generate-style-code.mjs b/platform/darwin/scripts/generate-style-code.mjs index f532739cd1b2..78270384f1b3 100644 --- a/platform/darwin/scripts/generate-style-code.mjs +++ b/platform/darwin/scripts/generate-style-code.mjs @@ -8,9 +8,6 @@ import { readAndCompile, writeIfModified, camelize, unhyphenate } from "../../.. import styleSpec from "../../../scripts/style-spec.mjs"; -delete styleSpec.layer.type.values["location-indicator"]; -delete styleSpec["layout_location-indicator"] -delete styleSpec["paint_location-indicator"]; import cocoaConventions from './style-spec-cocoa-conventions-v8.json' with { type: "json" }; import styleSpecOverrides from './style-spec-overrides-v8.json' with { type: "json" }; @@ -232,6 +229,8 @@ global.objCTestValue = function (property, layerType, arraysAsStructs, indent) { return `@"{'top','bottom'}"`; case 'mode': return `@"{'horizontal','vertical'}"`; + case 'location': + return '@"{1, 2, 3}"'; default: throw new Error(`unknown array type for ${property.name}`); } @@ -288,6 +287,8 @@ global.mbglTestValue = function (property, layerType) { return '{ mbgl::style::SymbolAnchorType::Top, mbgl::style::SymbolAnchorType::Bottom }'; case 'mode': return '{ mbgl::style::TextWritingModeType::Horizontal, mbgl::style::TextWritingModeType::Vertical }'; + case 'location': + return '{1, 2, 3}'; default: throw new Error(`unknown array type for ${property.name}`); } @@ -702,6 +703,7 @@ global.propertyType = function (property) { case 'position': case 'offset': case 'translate': + case 'location': return 'NSValue *'; case 'anchor': case 'mode': @@ -731,6 +733,11 @@ global.valueTransformerArguments = function (property) { case 'boolean': return ['bool', objCType]; case 'number': + if (/bearing$/.test(property.name) && + property.period == 360 && + property.units =='degrees') { + return ['mbgl::style::Rotation', objCType]; + } return ['float', objCType]; case 'formatted': return ['mbgl::style::expression::Formatted', objCType]; @@ -763,6 +770,8 @@ global.valueTransformerArguments = function (property) { return ['std::vector', objCType, 'mbgl::style::SymbolAnchorType', 'MLNTextAnchor']; case 'mode': return ['std::vector', objCType, 'mbgl::style::TextWritingModeType', 'MLNTextWritingMode']; + case 'location': + return ['std::array', objCType]; default: throw new Error(`unknown array type for ${property.name}`); } @@ -822,6 +831,8 @@ global.mbglType = function(property) { return 'std::vector'; case 'mode': return 'std::vector'; + case 'location': + return 'std::array'; default: throw new Error(`unknown array type for ${property.name}`); } diff --git a/platform/darwin/scripts/style-spec-overrides-v8.json b/platform/darwin/scripts/style-spec-overrides-v8.json index 882707b9358c..3e4f6c123896 100644 --- a/platform/darwin/scripts/style-spec-overrides-v8.json +++ b/platform/darwin/scripts/style-spec-overrides-v8.json @@ -42,6 +42,9 @@ }, "background": { "doc": "An ``MLNBackgroundStyleLayer`` is a style layer that covers the entire map. Use a background style layer to configure a color or pattern to show below all other map content. If the style’s other layers use the Mapbox Streets source, the background style layer is responsible for drawing land, whereas the oceans and other bodies of water are drawn by ``MLNBackgroundStyleLayer`` objects.\n\nA background style layer is typically the bottommost layer in a style, because it covers the entire map and can occlude any layers below it. You can therefore access it by getting the last item in the ``MLNStyle/layers`` array.\n\nIf the background style layer is transparent or omitted from the style, any portion of the map view that does not show another style layer is transparent." + }, + "location-indicator": { + "doc": "An ``MLNLocationIndicatorStyleLayer`` is a style layer that renders a visual representation of the device's current location on the map.\n\nUse a location-indicator style layer to display a puck-like indicator that shows the user’s position, heading, and accuracy radius. This layer is typically used in conjunction with the device’s location services to track and highlight the user’s movement in real time. The appearance of the indicator can be customized using style properties such as image, color, and bearing.\n\nUnlike other style layers that render geographic features from vector or raster sources, a location-indicator layer displays dynamic, device-driven data provided by the location manager. This layer does not rely on source data and is updated automatically as the device location changes." } } } diff --git a/platform/darwin/src/MLNStyle.mm b/platform/darwin/src/MLNStyle.mm index 48cbe1727ac5..c27da954758e 100644 --- a/platform/darwin/src/MLNStyle.mm +++ b/platform/darwin/src/MLNStyle.mm @@ -12,6 +12,7 @@ #import "MLNHillshadeStyleLayer.h" #import "MLNRasterStyleLayer.h" #import "MLNBackgroundStyleLayer.h" +#import "MLNLocationIndicatorStyleLayer.h" #import "MLNStyleLayerManager.h" #import "MLNSource.h" diff --git a/platform/darwin/src/MLNStyleLayer.h.ejs b/platform/darwin/src/MLNStyleLayer.h.ejs index 50d17ffa493f..a4b98e5024fb 100644 --- a/platform/darwin/src/MLNStyleLayer.h.ejs +++ b/platform/darwin/src/MLNStyleLayer.h.ejs @@ -11,7 +11,7 @@ #import "MLNFoundation.h" #import "MLN<%- -(type === 'background' ? '' : +(type === 'background' || type == 'location-indicator' ? '' : (type === 'raster' || type === 'hillshade' ? 'Foreground' : 'Vector')) %>StyleLayer.h" @@ -83,11 +83,11 @@ typedef NS_ENUM(NSUInteger, MLN<%- camelize(enumName(property)) %>) { <% } -%> MLN_EXPORT @interface MLN<%- camelize(type) %>StyleLayer : MLN<%- -(type === 'background' ? '' : +(type === 'background' || type === 'location-indicator' ? '' : (type === 'raster' || type === 'hillshade' ? 'Foreground' : 'Vector')) %>StyleLayer -<% if (type === 'background') { -%> +<% if (type === 'background' || type === 'location-indicator') { -%> /** Returns a <%- type %> style layer initialized with an identifier. diff --git a/platform/darwin/src/MLNStyleLayer.mm.ejs b/platform/darwin/src/MLNStyleLayer.mm.ejs index c706aa02ede5..c79061445523 100644 --- a/platform/darwin/src/MLNStyleLayer.mm.ejs +++ b/platform/darwin/src/MLNStyleLayer.mm.ejs @@ -58,7 +58,7 @@ namespace mbgl { @implementation MLN<%- camelize(type) %>StyleLayer -<% if (type == 'background') { -%> +<% if (type == 'background' || type == "location-indicator") { -%> - (instancetype)initWithIdentifier:(NSString *)identifier { MLNLogDebug(@"Initializing %@ with identifier: %@", NSStringFromClass([self class]), identifier); diff --git a/platform/darwin/src/MLNStyleLayerManager.mm b/platform/darwin/src/MLNStyleLayerManager.mm index cb6fcbe08813..40a8f137d11d 100644 --- a/platform/darwin/src/MLNStyleLayerManager.mm +++ b/platform/darwin/src/MLNStyleLayerManager.mm @@ -10,6 +10,7 @@ #import "MLNRasterStyleLayer_Private.h" #import "MLNSymbolStyleLayer_Private.h" #import "MLNCustomStyleLayer_Private.h" +#import "MLNLocationIndicatorStyleLayer_Private.h" #import "MLNCustomDrawableStyleLayer_Private.h" @@ -68,6 +69,11 @@ #elif !defined(MBGL_LAYER_CUSTOM_DISABLE_ALL) addLayerType(std::make_unique()); #endif +#if !defined(MBGL_LAYER_LOCATION_INDICATOR_DISABLE_ALL) + addLayerTypeCoreOnly(std::make_unique()); +#elif !defined(MBGL_LAYER_HEATMAP_DISABLE_ALL) + addLayerType(std::make_unique()); +#endif #if defined(MLN_LAYER_CUSTOM_DRAWABLE_DISABLE_RUNTIME) addLayerTypeCoreOnly(std::make_unique()); diff --git a/platform/darwin/src/MLNStyleValue_Private.h b/platform/darwin/src/MLNStyleValue_Private.h index a15c6b0b8203..2885aac7d987 100644 --- a/platform/darwin/src/MLNStyleValue_Private.h +++ b/platform/darwin/src/MLNStyleValue_Private.h @@ -189,6 +189,12 @@ class MLNStyleValueTransformer { // Float void getMBGLValue(NSNumber *rawValue, float &mbglValue) { mbglValue = rawValue.floatValue; } + void getMBGLValue(NSNumber *rawValue, double &mbglValue) { mbglValue = rawValue.doubleValue; } + + void getMBGLValue(NSNumber *rawValue, mbgl::style::Rotation &mbglValue) { + mbglValue = rawValue.floatValue; + } + // String void getMBGLValue(NSString *rawValue, std::string &mbglValue) { mbglValue = rawValue.UTF8String; } @@ -222,6 +228,17 @@ class MLNStyleValueTransformer { } } + void getMBGLValue(id rawValue, std::array &mbglValue) { + if ([rawValue isKindOfClass:[NSValue class]]) { + mbglValue = [rawValue mgl_locationArrayValue]; + } else if ([rawValue isKindOfClass:[NSArray class]]) { + NSArray *array = (NSArray *)rawValue; + getMBGLValue(array[0], mbglValue[0]); + getMBGLValue(array[1], mbglValue[1]); + getMBGLValue(array[2], mbglValue[2]); + } + } + // Padding type (supports numbers and float arrays w/ sizes 1 to 4) void getMBGLValue(id rawValue, mbgl::Padding &mbglValue) { if ([rawValue isKindOfClass:[NSNumber class]]) { @@ -320,6 +337,12 @@ class MLNStyleValueTransformer { // Float static NSNumber *toMLNRawStyleValue(const float mbglStopValue) { return @(mbglStopValue); } + static NSNumber *toMLNRawStyleValue(const double mbglStopValue) { return @(mbglStopValue); } + + static NSNumber *toMLNRawStyleValue(const mbgl::style::Rotation mbglStopValue) { + return @(mbglStopValue.getAngle()); + } + // Integer static NSNumber *toMLNRawStyleValue(const int64_t mbglStopValue) { return @(mbglStopValue); } @@ -343,6 +366,10 @@ class MLNStyleValueTransformer { return [NSValue mgl_valueWithPaddingArray:mbglStopValue]; } + static NSValue *toMLNRawStyleValue(const std::array &mbglStopValue) { + return [NSValue mgl_valueWithLocationArray:mbglStopValue]; + } + // Padding type static NSValue *toMLNRawStyleValue(const mbgl::Padding &mbglStopValue) { return [NSValue mgl_valueWithPaddingArray:mbglStopValue.toArray()]; diff --git a/platform/darwin/src/NSValue+MLNStyleAttributeAdditions.h b/platform/darwin/src/NSValue+MLNStyleAttributeAdditions.h index 3d1d8e896d8d..2ea7c835ab6c 100644 --- a/platform/darwin/src/NSValue+MLNStyleAttributeAdditions.h +++ b/platform/darwin/src/NSValue+MLNStyleAttributeAdditions.h @@ -6,9 +6,11 @@ + (instancetype)mgl_valueWithOffsetArray:(std::array)offsetArray; + (instancetype)mgl_valueWithPaddingArray:(std::array)paddingArray; ++ (instancetype)mgl_valueWithLocationArray:(std::array)positionArray; - (std::array)mgl_offsetArrayValue; - (std::array)mgl_paddingArrayValue; +- (std::array)mgl_locationArrayValue; - (std::array)mgl_lightPositionArrayValue; @end diff --git a/platform/darwin/src/NSValue+MLNStyleAttributeAdditions.mm b/platform/darwin/src/NSValue+MLNStyleAttributeAdditions.mm index 5a8151102bec..ba5fba3c2fbd 100644 --- a/platform/darwin/src/NSValue+MLNStyleAttributeAdditions.mm +++ b/platform/darwin/src/NSValue+MLNStyleAttributeAdditions.mm @@ -32,6 +32,12 @@ + (instancetype)mgl_valueWithPaddingArray:(std::array)paddingArray return [NSValue value:&insets withObjCType:@encode(MLNEdgeInsets)]; } ++ (instancetype)mgl_valueWithLocationArray:(std::array)locationArray +{ + CLLocation* location = [[CLLocation alloc] initWithLatitude:locationArray[0] longitude:locationArray[1]]; + return [NSValue value:&location withObjCType:@encode(CLLocation)]; +} + - (std::array)mgl_offsetArrayValue { MLNAssert(strcmp(self.objCType, @encode(CGVector)) == 0, @"Value does not represent a CGVector"); @@ -60,6 +66,18 @@ + (instancetype)mgl_valueWithPaddingArray:(std::array)paddingArray }; } +- (std::array)mgl_locationArrayValue +{ + MLNAssert(strcmp(self.objCType, @encode(CLLocation)) == 0, @"Value does not represent an CLLocation"); + CLLocation* location; + [self getValue:&location]; + return { + static_cast(location.coordinate.latitude), + static_cast(location.coordinate.longitude), + static_cast(location.altitude), + }; +} + - (std::array)mgl_lightPositionArrayValue { MLNAssert(strcmp(self.objCType, @encode(MLNSphericalPosition)) == 0, @"Value does not represent an MLNSphericalPosition"); diff --git a/platform/ios/src/Mapbox.h b/platform/ios/src/Mapbox.h index ae1ee305761c..645481a0dbdd 100644 --- a/platform/ios/src/Mapbox.h +++ b/platform/ios/src/Mapbox.h @@ -34,6 +34,7 @@ FOUNDATION_EXPORT MLN_EXPORT const unsigned char MapboxVersionString[]; #import "MLNImageSource.h" #import "MLNLight.h" #import "MLNLineStyleLayer.h" +#import "MLNLocationIndicatorStyleLayer.h" #import "MLNLocationManager.h" #import "MLNLoggingConfiguration.h" #import "MLNMapCamera.h" From 98f6bd210ef7fbb8feb9441f8be1c01f52e43d68 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 16 Apr 2025 19:51:14 +0300 Subject: [PATCH 061/221] implement custom user location annotation using indicator layer --- platform/ios/bazel/files.bzl | 2 + ...ationIndicatorUserLocationAnnotationView.h | 13 ++ ...tionIndicatorUserLocationAnnotationView.mm | 111 ++++++++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 platform/ios/src/MLNLocationIndicatorUserLocationAnnotationView.h create mode 100644 platform/ios/src/MLNLocationIndicatorUserLocationAnnotationView.mm diff --git a/platform/ios/bazel/files.bzl b/platform/ios/bazel/files.bzl index 4667a1da83ed..c93bd2cadf70 100644 --- a/platform/ios/bazel/files.bzl +++ b/platform/ios/bazel/files.bzl @@ -42,6 +42,7 @@ MLN_IOS_PRIVATE_HEADERS = [ "src/MLNMapView+Impl.h", "src/MLNMapView+Metal.h", "src/MLNMapView+OpenGL.h", + "src/MLNLocationIndicatorUserLocationAnnotationView.h", ] MLN_IOS_PUBLIC_OBJC_SOURCE = [ @@ -63,6 +64,7 @@ MLN_IOS_PUBLIC_OBJCPP_SOURCE = [ "src/MLNAnnotationView.mm", "src/MLNCompassButton.mm", "src/MLNFaux3DUserLocationAnnotationView.mm", + "src/MLNLocationIndicatorUserLocationAnnotationView.mm", "src/MLNMapAccessibilityElement.mm", "src/MLNMapProjection.mm", "src/MLNMapView.mm", diff --git a/platform/ios/src/MLNLocationIndicatorUserLocationAnnotationView.h b/platform/ios/src/MLNLocationIndicatorUserLocationAnnotationView.h new file mode 100644 index 000000000000..8a6c612821c5 --- /dev/null +++ b/platform/ios/src/MLNLocationIndicatorUserLocationAnnotationView.h @@ -0,0 +1,13 @@ +#import +#import "MLNUserLocationAnnotationView.h" + +typedef NS_ENUM(NSUInteger, MLNRenderMode) { + MLNRenderModeNone = 0, + MLNRenderModeCompass, + MLNRenderModeGps, + MLNRenderModeNormal, +}; + +@interface MLNLocationIndicatorUserLocationAnnotationView : MLNUserLocationAnnotationView + +@end diff --git a/platform/ios/src/MLNLocationIndicatorUserLocationAnnotationView.mm b/platform/ios/src/MLNLocationIndicatorUserLocationAnnotationView.mm new file mode 100644 index 000000000000..ea535dafff38 --- /dev/null +++ b/platform/ios/src/MLNLocationIndicatorUserLocationAnnotationView.mm @@ -0,0 +1,111 @@ +#import "MLNLocationIndicatorUserLocationAnnotationView.h" +#include +#include +#include + +#import "MLNLocationIndicatorStyleLayer.h" +#import "MLNUserLocation.h" +#import "UIImage+MLNAdditions.h" +#import "MLNMapView.h" +#import "NSExpression+MLNAdditions.h" + +const CGFloat MLNUserLocationAnnotationPuckSize = 45.0; +const CGFloat MLNUserLocationAnnotationArrowSize = MLNUserLocationAnnotationPuckSize * 0.5; + + +@implementation MLNLocationIndicatorUserLocationAnnotationView { + MLNLocationIndicatorStyleLayer* location_layer; + + CLLocation* _oldLocation; + CLLocationDirection _oldHeading; + MLNRenderMode _renderMode; +} + +- (void)update { + if (self.mapView.style && !self->location_layer) { + self->_renderMode = MLNRenderModeNone; + + self->location_layer = [[MLNLocationIndicatorStyleLayer alloc] initWithIdentifier:@"location_indicator_layer"]; + + [self.mapView.style setImage:[UIImage mgl_resourceImageNamed:@"user_bearing_icon"] forName:@"user_bearing_icon"]; + [self.mapView.style setImage:[UIImage mgl_resourceImageNamed:@"user_icon_stale"] forName:@"user_icon_stale"]; + [self.mapView.style setImage:[UIImage mgl_resourceImageNamed:@"user_icon"] forName:@"user_icon"]; + [self.mapView.style setImage:[UIImage mgl_resourceImageNamed:@"user_puck_icon"] forName:@"user_puck_icon"]; + [self.mapView.style setImage:[UIImage mgl_resourceImageNamed:@"user_stroke_icon"] forName:@"user_stroke_icon"]; + [self.mapView.style setImage:[UIImage mgl_resourceImageNamed:@"user_icon_shadow"] forName:@"user_icon_shadow"]; + + NSDictionary *opacityStops = @{@(self.mapView.minimumZoomLevel): @0.6f, + @(self.mapView.maximumZoomLevel): @1.0f }; + NSExpression *stops = [NSExpression expressionForConstantValue:opacityStops]; + NSExpression *styleScaling = [NSExpression mgl_expressionForInterpolatingExpression:NSExpression.zoomLevelVariableExpression withCurveType:MLNExpressionInterpolationModeLinear parameters:nil stops:stops]; + self->location_layer.topImageSize = styleScaling; + self->location_layer.bearingImageSize = styleScaling; + + NSDictionary *backgroundOpacityStops = @{@(self.mapView.minimumZoomLevel): @1.2f, + @(self.mapView.maximumZoomLevel): @1.5f }; + NSExpression *backgroundStops = [NSExpression expressionForConstantValue:backgroundOpacityStops]; + NSExpression *backgroundStyleScaling = [NSExpression mgl_expressionForInterpolatingExpression:NSExpression.zoomLevelVariableExpression withCurveType:MLNExpressionInterpolationModeLinear parameters:nil stops:backgroundStops]; + self->location_layer.shadowImageSize = backgroundStyleScaling; + self->location_layer.imageTiltDisplacement = [NSExpression expressionForConstantValue:@2.0]; + self->location_layer.perspectiveCompensation = [NSExpression expressionForConstantValue:@0.9]; + + self->location_layer.bearingTransition = MLNTransitionMake(1.0, 0, kCAMediaTimingFunctionLinear); + + [self.mapView.style addLayer:self->location_layer]; + } + + if (self.mapView.userTrackingMode == MLNUserTrackingModeFollowWithCourse) { + if (self.userLocation.location.course >= 0) { + self->location_layer.bearing = [NSExpression expressionForConstantValue:@(self.userLocation.location.course)]; + } + + if (self->_renderMode != MLNRenderModeGps) { + self->location_layer.bearingImage = [NSExpression expressionForConstantValue:@"user_puck_icon"]; + self->location_layer.topImage = [NSExpression expressionForConstantValue:@"user_puck_icon"]; + self->location_layer.shadowImage = [NSExpression expressionForConstantValue:@"user_stroke_icon"]; + + self->_renderMode = MLNRenderModeGps; + } + } else { + if (self->_renderMode != MLNRenderModeNormal && self.mapView.userTrackingMode == MLNUserTrackingModeFollow) { + self->location_layer.bearingImage = self.mapView.showsUserHeadingIndicator ? [NSExpression expressionForConstantValue:@"user_bearing_icon"] : [NSExpression expressionForConstantValue:@"user_icon"]; + self->location_layer.topImage = [NSExpression expressionForConstantValue:@"user_icon"]; + self->location_layer.shadowImage = [NSExpression expressionForConstantValue:@"user_stroke_icon"]; + + self->_renderMode = MLNRenderModeNormal; + } else if (self->_renderMode != MLNRenderModeCompass && self.mapView.userTrackingMode == MLNUserTrackingModeFollowWithHeading) { + self->location_layer.bearingImage = [NSExpression expressionForConstantValue:@"user_bearing_icon"]; + self->location_layer.topImage = [NSExpression expressionForConstantValue:@"user_icon"]; + self->location_layer.shadowImage = [NSExpression expressionForConstantValue:@"user_stroke_icon"]; + + self->_renderMode = MLNRenderModeCompass; + } + + bool showHeading = self.mapView.showsUserHeadingIndicator || self.mapView.userTrackingMode == MLNUserTrackingModeFollowWithHeading; + if (showHeading) { + CLLocationDirection headingDirection = (self.userLocation.heading.trueHeading >= 0 ? self.userLocation.heading.trueHeading : self.userLocation.heading.magneticHeading); + if (headingDirection >= 0) { + self->location_layer.bearing = [NSExpression expressionForConstantValue:@(headingDirection)]; + } + } + } + + CLLocation* newLocation = self.userLocation.location; + + if (self->location_layer) { + NSTimeInterval duration = 0.3; + if(_oldLocation) { + duration = MIN([newLocation.timestamp timeIntervalSinceDate:_oldLocation.timestamp], 1.0); + } + if (duration > 0) { + MLNTransition transition = MLNTransitionMake(duration, 0, kCAMediaTimingFunctionLinear); + self->location_layer.locationTransition = transition; + } + NSArray *location = @[@(newLocation.coordinate.latitude), @(newLocation.coordinate.longitude), @0]; + self->location_layer.location = [NSExpression expressionForConstantValue:location]; + } + + _oldLocation = newLocation; +} + +@end From acde9b5565e4c8061417aed8a46c24b05e4ca0ea Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 16 Apr 2025 19:51:37 +0300 Subject: [PATCH 062/221] add ability to select new indicator layer instead of faux 3d user location indicator Also release a new version for ios --- platform/ios/src/MLNMapView.h | 6 ++++++ platform/ios/src/MLNMapView.mm | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/platform/ios/src/MLNMapView.h b/platform/ios/src/MLNMapView.h index 7e837e321a6f..0291b218dd78 100644 --- a/platform/ios/src/MLNMapView.h +++ b/platform/ios/src/MLNMapView.h @@ -511,6 +511,12 @@ MLN_EXPORT */ @property (nonatomic, assign) BOOL showsUserLocation; +/** + A boolean value indicating whether the location indicator is drawn using the location + indicator layer or the location indication annotation. + */ +@property (nonatomic, assign) BOOL useLocationIndicatorLayer; + /** A Boolean value indicating whether the map may request authorization to use location services. diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 35525bf0f9d6..52777964ad23 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -24,7 +24,6 @@ #include #include #include -#include #import "Mapbox.h" #import "MLNShape_Private.h" @@ -69,6 +68,7 @@ #import "MLNReachability.h" #import "MLNSettings_Private.h" #import "MLNMapProjection.h" +#import "MLNLocationIndicatorUserLocationAnnotationView.h" #include #include @@ -5955,7 +5955,7 @@ - (void)setShowsUserLocation:(BOOL)showsUserLocation } } - self.userLocationAnnotationView = userLocationAnnotationView ?: [[MLNFaux3DUserLocationAnnotationView alloc] init]; + self.userLocationAnnotationView = userLocationAnnotationView ?: self.useLocationIndicatorLayer ? [[MLNLocationIndicatorUserLocationAnnotationView alloc] init] : [[MLNFaux3DUserLocationAnnotationView alloc] init]; self.userLocationAnnotationView.mapView = self; self.userLocationAnnotationView.userLocation = self.userLocation; From 623ee42f8e53aceebd0da5a3cae3f625096c5ecc Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 16 Apr 2025 19:54:59 +0300 Subject: [PATCH 063/221] add icons for indicator layer --- .../user_bearing_icon.imageset/Contents.json | 21 ++++++++++++++++++ .../user_bearing_icon.svg | 9 ++++++++ .../user_icon.imageset/Contents.json | 21 ++++++++++++++++++ .../user_icon.imageset/user_icon.svg | 9 ++++++++ .../user_icon_shadow.imageset/Contents.json | 21 ++++++++++++++++++ .../user_icon_shadow.png | Bin 0 -> 359 bytes .../user_icon_stale.imageset/Contents.json | 21 ++++++++++++++++++ .../user_icon_stale.svg | 9 ++++++++ .../user_puck_icon.imageset/Contents.json | 21 ++++++++++++++++++ .../user_puck_icon.svg | 18 +++++++++++++++ .../user_stroke_icon.imageset/Contents.json | 21 ++++++++++++++++++ .../user_stroke_icon.svg | 9 ++++++++ 12 files changed, 180 insertions(+) create mode 100644 platform/ios/resources/Images.xcassets/user_bearing_icon.imageset/Contents.json create mode 100644 platform/ios/resources/Images.xcassets/user_bearing_icon.imageset/user_bearing_icon.svg create mode 100644 platform/ios/resources/Images.xcassets/user_icon.imageset/Contents.json create mode 100644 platform/ios/resources/Images.xcassets/user_icon.imageset/user_icon.svg create mode 100644 platform/ios/resources/Images.xcassets/user_icon_shadow.imageset/Contents.json create mode 100644 platform/ios/resources/Images.xcassets/user_icon_shadow.imageset/user_icon_shadow.png create mode 100644 platform/ios/resources/Images.xcassets/user_icon_stale.imageset/Contents.json create mode 100644 platform/ios/resources/Images.xcassets/user_icon_stale.imageset/user_icon_stale.svg create mode 100644 platform/ios/resources/Images.xcassets/user_puck_icon.imageset/Contents.json create mode 100644 platform/ios/resources/Images.xcassets/user_puck_icon.imageset/user_puck_icon.svg create mode 100644 platform/ios/resources/Images.xcassets/user_stroke_icon.imageset/Contents.json create mode 100644 platform/ios/resources/Images.xcassets/user_stroke_icon.imageset/user_stroke_icon.svg diff --git a/platform/ios/resources/Images.xcassets/user_bearing_icon.imageset/Contents.json b/platform/ios/resources/Images.xcassets/user_bearing_icon.imageset/Contents.json new file mode 100644 index 000000000000..525f85fd1cd2 --- /dev/null +++ b/platform/ios/resources/Images.xcassets/user_bearing_icon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "user_bearing_icon.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/platform/ios/resources/Images.xcassets/user_bearing_icon.imageset/user_bearing_icon.svg b/platform/ios/resources/Images.xcassets/user_bearing_icon.imageset/user_bearing_icon.svg new file mode 100644 index 000000000000..ba7f4c47f3ac --- /dev/null +++ b/platform/ios/resources/Images.xcassets/user_bearing_icon.imageset/user_bearing_icon.svg @@ -0,0 +1,9 @@ + + + diff --git a/platform/ios/resources/Images.xcassets/user_icon.imageset/Contents.json b/platform/ios/resources/Images.xcassets/user_icon.imageset/Contents.json new file mode 100644 index 000000000000..be1b4bcb7e62 --- /dev/null +++ b/platform/ios/resources/Images.xcassets/user_icon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "user_icon.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/platform/ios/resources/Images.xcassets/user_icon.imageset/user_icon.svg b/platform/ios/resources/Images.xcassets/user_icon.imageset/user_icon.svg new file mode 100644 index 000000000000..fcac127bd46e --- /dev/null +++ b/platform/ios/resources/Images.xcassets/user_icon.imageset/user_icon.svg @@ -0,0 +1,9 @@ + + + diff --git a/platform/ios/resources/Images.xcassets/user_icon_shadow.imageset/Contents.json b/platform/ios/resources/Images.xcassets/user_icon_shadow.imageset/Contents.json new file mode 100644 index 000000000000..f6592a561e1f --- /dev/null +++ b/platform/ios/resources/Images.xcassets/user_icon_shadow.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "user_icon_shadow.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/platform/ios/resources/Images.xcassets/user_icon_shadow.imageset/user_icon_shadow.png b/platform/ios/resources/Images.xcassets/user_icon_shadow.imageset/user_icon_shadow.png new file mode 100644 index 0000000000000000000000000000000000000000..5ea50fe5c96dca7e4ac88a24ecf62324e59d56d4 GIT binary patch literal 359 zcmV-t0hs=YP)9gE3xJ+lfoEz|n@3^m38l8Qsmz2&u0`6m;GVW2U`9>Ri1kD_g)5lQYXS+^%>*+I zo~8q?V1-?as2v=IoofeJb2>~t9UiSiCx9T>3+4_k28m5-c#;@+R-NCzfosHPY3TqO z!3yo>Knn^y`&Qd+fjXGd@OlasloAdSMg!2i@&6_R>%G@GFtO%Pqn-B83uA0RTHz)@ zr2QriCJIMm1Ff3h+l}z3;Ot|CRacm6!0KG#>g2e2-ZtK+yDLq&J6L7~^ZCh4sG{Z< z4rWof*`uxIf=7Lf&FTgDcF-@mJp)sIdYaC_`p?&o=>wSBsy3e_u;l;%002ovPDHLk FV1gb{ox1=4 literal 0 HcmV?d00001 diff --git a/platform/ios/resources/Images.xcassets/user_icon_stale.imageset/Contents.json b/platform/ios/resources/Images.xcassets/user_icon_stale.imageset/Contents.json new file mode 100644 index 000000000000..e08508836c39 --- /dev/null +++ b/platform/ios/resources/Images.xcassets/user_icon_stale.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "user_icon_stale.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/platform/ios/resources/Images.xcassets/user_icon_stale.imageset/user_icon_stale.svg b/platform/ios/resources/Images.xcassets/user_icon_stale.imageset/user_icon_stale.svg new file mode 100644 index 000000000000..42361ea6dfe2 --- /dev/null +++ b/platform/ios/resources/Images.xcassets/user_icon_stale.imageset/user_icon_stale.svg @@ -0,0 +1,9 @@ + + + diff --git a/platform/ios/resources/Images.xcassets/user_puck_icon.imageset/Contents.json b/platform/ios/resources/Images.xcassets/user_puck_icon.imageset/Contents.json new file mode 100644 index 000000000000..1df1fea05642 --- /dev/null +++ b/platform/ios/resources/Images.xcassets/user_puck_icon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "user_puck_icon.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/platform/ios/resources/Images.xcassets/user_puck_icon.imageset/user_puck_icon.svg b/platform/ios/resources/Images.xcassets/user_puck_icon.imageset/user_puck_icon.svg new file mode 100644 index 000000000000..cb26bc7bee7d --- /dev/null +++ b/platform/ios/resources/Images.xcassets/user_puck_icon.imageset/user_puck_icon.svg @@ -0,0 +1,18 @@ + + + + + diff --git a/platform/ios/resources/Images.xcassets/user_stroke_icon.imageset/Contents.json b/platform/ios/resources/Images.xcassets/user_stroke_icon.imageset/Contents.json new file mode 100644 index 000000000000..7c83043a811f --- /dev/null +++ b/platform/ios/resources/Images.xcassets/user_stroke_icon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "user_stroke_icon.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/platform/ios/resources/Images.xcassets/user_stroke_icon.imageset/user_stroke_icon.svg b/platform/ios/resources/Images.xcassets/user_stroke_icon.imageset/user_stroke_icon.svg new file mode 100644 index 000000000000..1be237b6452c --- /dev/null +++ b/platform/ios/resources/Images.xcassets/user_stroke_icon.imageset/user_stroke_icon.svg @@ -0,0 +1,9 @@ + + + From 8137dc69bb7cd5dd63da3fbeb5438bc87c6cf2fc Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 17 Apr 2025 11:07:33 +0300 Subject: [PATCH 064/221] fix cmake build --- platform/darwin/darwin.cmake | 3 +++ platform/ios/src/Mapbox.h | 1 + 2 files changed, 4 insertions(+) diff --git a/platform/darwin/darwin.cmake b/platform/darwin/darwin.cmake index 158ed0a35135..24ab01c0e8ca 100644 --- a/platform/darwin/darwin.cmake +++ b/platform/darwin/darwin.cmake @@ -92,6 +92,7 @@ set(MLN_GENERATED_DARWIN_STYLE_SOURCE "${MLN_GENERATED_DARWIN_CODE_DIR}/MLNLineStyleLayer.mm" "${MLN_GENERATED_DARWIN_CODE_DIR}/MLNRasterStyleLayer.mm" "${MLN_GENERATED_DARWIN_CODE_DIR}/MLNSymbolStyleLayer.mm" + "${MLN_GENERATED_DARWIN_CODE_DIR}/MLNLocationIndicatorStyleLayer.mm" ) set(MLN_GENERATED_DARWIN_STYLE_PUBLIC_HEADERS @@ -105,6 +106,7 @@ set(MLN_GENERATED_DARWIN_STYLE_PUBLIC_HEADERS "${MLN_GENERATED_DARWIN_CODE_DIR}/MLNFillStyleLayer.h" "${MLN_GENERATED_DARWIN_CODE_DIR}/MLNHillshadeStyleLayer.h" "${MLN_GENERATED_DARWIN_CODE_DIR}/MLNRasterStyleLayer.h" + "${MLN_GENERATED_DARWIN_CODE_DIR}/MLNLocationIndicatorStyleLayer.h" ) set(MLN_GENERATED_DARWIN_STYLE_HEADERS @@ -117,6 +119,7 @@ set(MLN_GENERATED_DARWIN_STYLE_HEADERS "${MLN_GENERATED_DARWIN_CODE_DIR}/MLNCircleStyleLayer_Private.h" "${MLN_GENERATED_DARWIN_CODE_DIR}/MLNFillStyleLayer_Private.h" "${MLN_GENERATED_DARWIN_CODE_DIR}/MLNHillshadeStyleLayer_Private.h" + "${MLN_GENERATED_DARWIN_CODE_DIR}/MLNLocationIndicatorStyleLayer_Private.h" ${MLN_GENERATED_DARWIN_STYLE_PUBLIC_HEADERS} ) diff --git a/platform/ios/src/Mapbox.h b/platform/ios/src/Mapbox.h index 645481a0dbdd..1b72c72cf0f6 100644 --- a/platform/ios/src/Mapbox.h +++ b/platform/ios/src/Mapbox.h @@ -35,6 +35,7 @@ FOUNDATION_EXPORT MLN_EXPORT const unsigned char MapboxVersionString[]; #import "MLNLight.h" #import "MLNLineStyleLayer.h" #import "MLNLocationIndicatorStyleLayer.h" +#import "MLNLocationIndicatorUserLocationAnnotationView.h" #import "MLNLocationManager.h" #import "MLNLoggingConfiguration.h" #import "MLNMapCamera.h" From afed68680a42da6d0fda1e4cc4b4be87f0d2f6d1 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 17 Apr 2025 12:21:07 +0300 Subject: [PATCH 065/221] prepare android release --- platform/android/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index 2e4e5d91de26..0bbcc87ea492 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -2,6 +2,12 @@ ## main +## 11.8.7 + +### ✨ Features and improvements + +- Change Java Transfrom class from final to normal ([#3332](https://github.com/maplibre/maplibre-native/pull/3332)). + ## 11.8.6 ### ✨ Features and improvements From 9c80eeb97e77b9a83359fecf8b727e0d6b6e62a4 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 17 Apr 2025 15:22:16 +0300 Subject: [PATCH 066/221] don't export the new location indicator layer --- platform/ios/src/Mapbox.h | 1 - 1 file changed, 1 deletion(-) diff --git a/platform/ios/src/Mapbox.h b/platform/ios/src/Mapbox.h index 1b72c72cf0f6..645481a0dbdd 100644 --- a/platform/ios/src/Mapbox.h +++ b/platform/ios/src/Mapbox.h @@ -35,7 +35,6 @@ FOUNDATION_EXPORT MLN_EXPORT const unsigned char MapboxVersionString[]; #import "MLNLight.h" #import "MLNLineStyleLayer.h" #import "MLNLocationIndicatorStyleLayer.h" -#import "MLNLocationIndicatorUserLocationAnnotationView.h" #import "MLNLocationManager.h" #import "MLNLoggingConfiguration.h" #import "MLNMapCamera.h" From 7315399373ca0a77d61d8daf5557ae7c8ef7b82a Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 17 Apr 2025 18:35:07 +0300 Subject: [PATCH 067/221] resolve test failures due to transition option changes --- platform/darwin/src/MLNStyleValue_Private.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/platform/darwin/src/MLNStyleValue_Private.h b/platform/darwin/src/MLNStyleValue_Private.h index 2885aac7d987..dd6d3e7fbadb 100644 --- a/platform/darwin/src/MLNStyleValue_Private.h +++ b/platform/darwin/src/MLNStyleValue_Private.h @@ -1,4 +1,5 @@ #import +#include #import "MLNStyleValue.h" @@ -49,13 +50,18 @@ NS_INLINE MLNTransition MLNTransitionFromOptions(const mbgl::style::TransitionOp } NS_INLINE mbgl::style::TransitionOptions MLNOptionsFromTransition(MLNTransition transition) { - CAMediaTimingFunction *function = [CAMediaTimingFunction functionWithName:transition.ease]; - float p0[2], p3[2]; - [function getControlPointAtIndex:0 values:p0]; - [function getControlPointAtIndex:3 values:p3]; + mbgl::util::UnitBezier ease = mbgl::util::DEFAULT_TRANSITION_EASE; + if (transition.ease) { + CAMediaTimingFunction *function = [CAMediaTimingFunction functionWithName:transition.ease]; + float p0[2], p3[2]; + [function getControlPointAtIndex:0 values:p0]; + [function getControlPointAtIndex:3 values:p3]; + ease = {p0[0], p0[1], p3[0], p3[1]}; + } + mbgl::style::TransitionOptions options{{MLNDurationFromTimeInterval(transition.duration)}, {MLNDurationFromTimeInterval(transition.delay)}, - mbgl::util::UnitBezier({p0[0], p0[1], p3[0], p3[1]})}; + ease}; return options; } From 505999eb91142bc1455a157d1a674118054737c0 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 17 Apr 2025 21:27:11 +0300 Subject: [PATCH 068/221] make ios release --- platform/ios/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/VERSION b/platform/ios/VERSION index ffd41f5c6b29..41b9e040b7fe 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.12.3 +6.12.4 From dbd428686216c0f9ca5b38cbb047c3c5f877303c Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Sat, 19 Apr 2025 18:20:44 +0300 Subject: [PATCH 069/221] follow location indicator during navigation with a flag --- platform/ios/VERSION | 2 +- platform/ios/src/MLNMapView.h | 5 +++++ platform/ios/src/MLNMapView.mm | 39 ++++++++++++++++++++++++---------- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/platform/ios/VERSION b/platform/ios/VERSION index 41b9e040b7fe..aea5e0b5a6fd 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.12.4 +6.12.5 diff --git a/platform/ios/src/MLNMapView.h b/platform/ios/src/MLNMapView.h index 0291b218dd78..57054d8a916f 100644 --- a/platform/ios/src/MLNMapView.h +++ b/platform/ios/src/MLNMapView.h @@ -517,6 +517,11 @@ MLN_EXPORT */ @property (nonatomic, assign) BOOL useLocationIndicatorLayer; +/** + A boolean value indicating whether the camera follows the puck during gesture handling + */ +@property (nonatomic, assign) BOOL followLocationIndicatorDuringGesture; + /** A Boolean value indicating whether the map may request authorization to use location services. diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 52777964ad23..7aed678428ad 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -1335,13 +1335,13 @@ - (void)setContentInset:(UIEdgeInsets)contentInset animated:(BOOL)animated compl if (self.userTrackingMode == MLNUserTrackingModeNone) { // Don’t call -setCenterCoordinate:, which resets the user tracking mode. - [self _setCenterCoordinate:self.centerCoordinate edgePadding:contentInset zoomLevel:self.zoomLevel direction:self.direction duration:animated ? MLNAnimationDuration : 0 animationTimingFunction:nil completionHandler:completion]; + [self _setCenterCoordinate:self.centerCoordinate edgePadding:contentInset zoomLevel:self.zoomLevel direction:self.direction duration:animated ? MLNAnimationDuration : 0 animationTimingFunction:nil completionHandler:completion cancelTransitions:true]; _contentInset = contentInset; } else { _contentInset = contentInset; - [self didUpdateLocationWithUserTrackingAnimated:animated completionHandler:completion]; + [self didUpdateLocationWithUserTrackingAnimated:animated completionHandler:completion cancelTransitions:true]; } // Compass, logo and attribution button constraints needs to be updated.z @@ -2126,6 +2126,9 @@ - (void)handlePanGesture:(UIPanGestureRecognizer *)pan } [self cameraIsChanging]; + if (self.followLocationIndicatorDuringGesture) { + [self didUpdateLocationWithUserTrackingAnimated:true completionHandler:nil cancelTransitions:false]; + } } else if (pan.state == UIGestureRecognizerStateEnded || pan.state == UIGestureRecognizerStateCancelled) { @@ -2212,6 +2215,9 @@ - (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch } } [self cameraIsChanging]; + if (self.followLocationIndicatorDuringGesture) { + [self didUpdateLocationWithUserTrackingAnimated:true completionHandler:nil cancelTransitions:false]; + } } else if (pinch.state == UIGestureRecognizerStateEnded || pinch.state == UIGestureRecognizerStateCancelled) { @@ -2336,7 +2342,9 @@ - (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate } [self cameraIsChanging]; - + if (self.followLocationIndicatorDuringGesture) { + [self didUpdateLocationWithUserTrackingAnimated:true completionHandler:nil cancelTransitions:false]; + } // Trigger a light haptic feedback event when the user rotates to due north. if (@available(iOS 10.0, *)) { @@ -2593,6 +2601,9 @@ - (void)handleQuickZoomGesture:(UILongPressGestureRecognizer *)quickZoom } [self cameraIsChanging]; + if (self.followLocationIndicatorDuringGesture) { + [self didUpdateLocationWithUserTrackingAnimated:true completionHandler:nil cancelTransitions:false]; + } } else if (quickZoom.state == UIGestureRecognizerStateEnded || quickZoom.state == UIGestureRecognizerStateCancelled) { @@ -2660,6 +2671,9 @@ - (void)handleTwoFingerDragGesture:(UIPanGestureRecognizer *)twoFingerDrag } [self cameraIsChanging]; + if (self.followLocationIndicatorDuringGesture) { + [self didUpdateLocationWithUserTrackingAnimated:true completionHandler:nil cancelTransitions:false]; + } } @@ -3786,10 +3800,10 @@ - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:( self.cameraChangeReasonBitmask |= MLNCameraChangeReasonProgrammatic; - [self _setCenterCoordinate:centerCoordinate edgePadding:self.contentInset zoomLevel:zoomLevel direction:direction duration:animated ? MLNAnimationDuration : 0 animationTimingFunction:nil completionHandler:completion]; + [self _setCenterCoordinate:centerCoordinate edgePadding:self.contentInset zoomLevel:zoomLevel direction:direction duration:animated ? MLNAnimationDuration : 0 animationTimingFunction:nil completionHandler:completion cancelTransitions:true]; } -- (void)_setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate edgePadding:(UIEdgeInsets)insets zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion +- (void)_setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate edgePadding:(UIEdgeInsets)insets zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion cancelTransitions:(bool)cancelOtherTransitions { if (!_mbglMap) { @@ -3848,7 +3862,9 @@ - (void)_setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate edgePaddin return; } - [self cancelTransitions]; + if (cancelOtherTransitions) { + [self cancelTransitions]; + } self.cameraChangeReasonBitmask |= MLNCameraChangeReasonProgrammatic; @@ -6201,7 +6217,7 @@ - (void)locationManager:(__unused id)manager didUpdateLocati } } - [self didUpdateLocationWithUserTrackingAnimated:animated completionHandler:completion]; + [self didUpdateLocationWithUserTrackingAnimated:animated completionHandler:completion cancelTransitions:true]; NSTimeInterval duration = MLNAnimationDuration; if (oldLocation && ! CGPointEqualToPoint(self.userLocationAnnotationView.center, CGPointZero)) @@ -6218,7 +6234,7 @@ - (void)locationManager:(__unused id)manager didUpdateLocati } } -- (void)didUpdateLocationWithUserTrackingAnimated:(BOOL)animated completionHandler:(nullable void (^)(void))completion +- (void)didUpdateLocationWithUserTrackingAnimated:(BOOL)animated completionHandler:(nullable void (^)(void))completion cancelTransitions:(bool)cancelTransitions { CLLocation *location = self.userLocation.location; if ( ! _showsUserLocation || ! location @@ -6264,13 +6280,13 @@ - (void)didUpdateLocationWithUserTrackingAnimated:(BOOL)animated completionHandl else if (self.userTrackingState == MLNUserTrackingStateChanged) { // Subsequent updates get a more subtle animation. - [self didUpdateLocationIncrementallyAnimated:animated completionHandler:completion]; + [self didUpdateLocationIncrementallyAnimated:animated completionHandler:completion cancelTransitions:cancelTransitions]; } [self unrotateIfNeededAnimated:YES]; } /// Changes the viewport based on an incremental location update. -- (void)didUpdateLocationIncrementallyAnimated:(BOOL)animated completionHandler:(nullable void (^)(void))completion +- (void)didUpdateLocationIncrementallyAnimated:(BOOL)animated completionHandler:(nullable void (^)(void))completion cancelTransitions:(bool)cancelTransitions { [self _setCenterCoordinate:self.userLocation.location.coordinate edgePadding:self.edgePaddingForFollowing @@ -6278,7 +6294,8 @@ - (void)didUpdateLocationIncrementallyAnimated:(BOOL)animated completionHandler: direction:self.directionByFollowingWithCourse duration:animated ? MLNUserLocationAnimationDuration : 0 animationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear] - completionHandler:completion]; + completionHandler:completion + cancelTransitions:cancelTransitions]; } /// Changes the viewport based on a significant location update, such as the From d13486eca0e700e5d1da51cebe746b2c7b092f9a Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Tue, 22 Apr 2025 17:05:42 +0300 Subject: [PATCH 070/221] push dsym files with ios releases --- .github/workflows/ios-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ios-ci.yml b/.github/workflows/ios-ci.yml index b540c67c8ca4..ed11f901cb7c 100644 --- a/.github/workflows/ios-ci.yml +++ b/.github/workflows/ios-ci.yml @@ -295,6 +295,7 @@ jobs: name: ios-v${{ env.version }} files: | MapLibre.dynamic.xcframework.zip + ${{ env.debug_symbols_ios }} tag_name: ios-v${{ env.version }} prerelease: ${{ github.event.inputs.release == 'pre' }} body_path: platform/ios/changelog_for_version.md From 16ce4460860704b82835f7e79c1e38cbe8160b52 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Tue, 22 Apr 2025 17:06:12 +0300 Subject: [PATCH 071/221] fix mln transition conversion logic for ios --- platform/darwin/src/MLNStyleValue_Private.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/darwin/src/MLNStyleValue_Private.h b/platform/darwin/src/MLNStyleValue_Private.h index dd6d3e7fbadb..220b8d5f2206 100644 --- a/platform/darwin/src/MLNStyleValue_Private.h +++ b/platform/darwin/src/MLNStyleValue_Private.h @@ -53,10 +53,10 @@ NS_INLINE mbgl::style::TransitionOptions MLNOptionsFromTransition(MLNTransition mbgl::util::UnitBezier ease = mbgl::util::DEFAULT_TRANSITION_EASE; if (transition.ease) { CAMediaTimingFunction *function = [CAMediaTimingFunction functionWithName:transition.ease]; - float p0[2], p3[2]; - [function getControlPointAtIndex:0 values:p0]; - [function getControlPointAtIndex:3 values:p3]; - ease = {p0[0], p0[1], p3[0], p3[1]}; + float p1[2], p2[2]; + [function getControlPointAtIndex:1 values:p1]; + [function getControlPointAtIndex:2 values:p2]; + ease = {p1[0], p1[1], p2[0], p2[1]}; } mbgl::style::TransitionOptions options{{MLNDurationFromTimeInterval(transition.duration)}, From 1f89fb1cfc76663f6537c40fed44b908cc1cbda2 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Tue, 22 Apr 2025 17:08:59 +0300 Subject: [PATCH 072/221] handle all cleanup and failure cases due to style changes --- ...ationIndicatorUserLocationAnnotationView.h | 2 + ...tionIndicatorUserLocationAnnotationView.mm | 146 ++++++++++-------- platform/ios/src/MLNMapView.mm | 8 + 3 files changed, 93 insertions(+), 63 deletions(-) diff --git a/platform/ios/src/MLNLocationIndicatorUserLocationAnnotationView.h b/platform/ios/src/MLNLocationIndicatorUserLocationAnnotationView.h index 8a6c612821c5..edc4843e6bbc 100644 --- a/platform/ios/src/MLNLocationIndicatorUserLocationAnnotationView.h +++ b/platform/ios/src/MLNLocationIndicatorUserLocationAnnotationView.h @@ -10,4 +10,6 @@ typedef NS_ENUM(NSUInteger, MLNRenderMode) { @interface MLNLocationIndicatorUserLocationAnnotationView : MLNUserLocationAnnotationView +- (void)removeLayer; + @end diff --git a/platform/ios/src/MLNLocationIndicatorUserLocationAnnotationView.mm b/platform/ios/src/MLNLocationIndicatorUserLocationAnnotationView.mm index ea535dafff38..99b28b6e4f19 100644 --- a/platform/ios/src/MLNLocationIndicatorUserLocationAnnotationView.mm +++ b/platform/ios/src/MLNLocationIndicatorUserLocationAnnotationView.mm @@ -17,82 +17,85 @@ @implementation MLNLocationIndicatorUserLocationAnnotationView { MLNLocationIndicatorStyleLayer* location_layer; CLLocation* _oldLocation; - CLLocationDirection _oldHeading; MLNRenderMode _renderMode; } - (void)update { if (self.mapView.style && !self->location_layer) { - self->_renderMode = MLNRenderModeNone; - - self->location_layer = [[MLNLocationIndicatorStyleLayer alloc] initWithIdentifier:@"location_indicator_layer"]; - - [self.mapView.style setImage:[UIImage mgl_resourceImageNamed:@"user_bearing_icon"] forName:@"user_bearing_icon"]; - [self.mapView.style setImage:[UIImage mgl_resourceImageNamed:@"user_icon_stale"] forName:@"user_icon_stale"]; - [self.mapView.style setImage:[UIImage mgl_resourceImageNamed:@"user_icon"] forName:@"user_icon"]; - [self.mapView.style setImage:[UIImage mgl_resourceImageNamed:@"user_puck_icon"] forName:@"user_puck_icon"]; - [self.mapView.style setImage:[UIImage mgl_resourceImageNamed:@"user_stroke_icon"] forName:@"user_stroke_icon"]; - [self.mapView.style setImage:[UIImage mgl_resourceImageNamed:@"user_icon_shadow"] forName:@"user_icon_shadow"]; - - NSDictionary *opacityStops = @{@(self.mapView.minimumZoomLevel): @0.6f, - @(self.mapView.maximumZoomLevel): @1.0f }; - NSExpression *stops = [NSExpression expressionForConstantValue:opacityStops]; - NSExpression *styleScaling = [NSExpression mgl_expressionForInterpolatingExpression:NSExpression.zoomLevelVariableExpression withCurveType:MLNExpressionInterpolationModeLinear parameters:nil stops:stops]; - self->location_layer.topImageSize = styleScaling; - self->location_layer.bearingImageSize = styleScaling; - - NSDictionary *backgroundOpacityStops = @{@(self.mapView.minimumZoomLevel): @1.2f, - @(self.mapView.maximumZoomLevel): @1.5f }; - NSExpression *backgroundStops = [NSExpression expressionForConstantValue:backgroundOpacityStops]; - NSExpression *backgroundStyleScaling = [NSExpression mgl_expressionForInterpolatingExpression:NSExpression.zoomLevelVariableExpression withCurveType:MLNExpressionInterpolationModeLinear parameters:nil stops:backgroundStops]; - self->location_layer.shadowImageSize = backgroundStyleScaling; - self->location_layer.imageTiltDisplacement = [NSExpression expressionForConstantValue:@2.0]; - self->location_layer.perspectiveCompensation = [NSExpression expressionForConstantValue:@0.9]; - - self->location_layer.bearingTransition = MLNTransitionMake(1.0, 0, kCAMediaTimingFunctionLinear); - - [self.mapView.style addLayer:self->location_layer]; + // Find existing location indicator layer before creating a new one + self->location_layer = (MLNLocationIndicatorStyleLayer*)[self.mapView.style layerWithIdentifier:@"location_indicator_layer"]; + + if (!self->location_layer) { + self->_renderMode = MLNRenderModeNone; + + self->location_layer = [[MLNLocationIndicatorStyleLayer alloc] initWithIdentifier:@"location_indicator_layer"]; + + [self.mapView.style setImage:[UIImage mgl_resourceImageNamed:@"user_bearing_icon"] forName:@"user_bearing_icon"]; + [self.mapView.style setImage:[UIImage mgl_resourceImageNamed:@"user_icon_stale"] forName:@"user_icon_stale"]; + [self.mapView.style setImage:[UIImage mgl_resourceImageNamed:@"user_icon"] forName:@"user_icon"]; + [self.mapView.style setImage:[UIImage mgl_resourceImageNamed:@"user_puck_icon"] forName:@"user_puck_icon"]; + [self.mapView.style setImage:[UIImage mgl_resourceImageNamed:@"user_stroke_icon"] forName:@"user_stroke_icon"]; + [self.mapView.style setImage:[UIImage mgl_resourceImageNamed:@"user_icon_shadow"] forName:@"user_icon_shadow"]; + + NSDictionary *opacityStops = @{@(self.mapView.minimumZoomLevel): @0.6f, + @(self.mapView.maximumZoomLevel): @1.0f }; + NSExpression *stops = [NSExpression expressionForConstantValue:opacityStops]; + NSExpression *styleScaling = [NSExpression mgl_expressionForInterpolatingExpression:NSExpression.zoomLevelVariableExpression withCurveType:MLNExpressionInterpolationModeLinear parameters:nil stops:stops]; + self->location_layer.topImageSize = styleScaling; + self->location_layer.bearingImageSize = styleScaling; + + NSDictionary *backgroundOpacityStops = @{@(self.mapView.minimumZoomLevel): @1.2f, + @(self.mapView.maximumZoomLevel): @1.5f }; + NSExpression *backgroundStops = [NSExpression expressionForConstantValue:backgroundOpacityStops]; + NSExpression *backgroundStyleScaling = [NSExpression mgl_expressionForInterpolatingExpression:NSExpression.zoomLevelVariableExpression withCurveType:MLNExpressionInterpolationModeLinear parameters:nil stops:backgroundStops]; + self->location_layer.shadowImageSize = backgroundStyleScaling; + self->location_layer.imageTiltDisplacement = [NSExpression expressionForConstantValue:@2.0]; + self->location_layer.perspectiveCompensation = [NSExpression expressionForConstantValue:@0.9]; + + self->location_layer.bearingTransition = MLNTransitionMake(1.0, 0, kCAMediaTimingFunctionLinear); + + [self.mapView.style addLayer:self->location_layer]; + } } - if (self.mapView.userTrackingMode == MLNUserTrackingModeFollowWithCourse) { - if (self.userLocation.location.course >= 0) { - self->location_layer.bearing = [NSExpression expressionForConstantValue:@(self.userLocation.location.course)]; - } + CLLocation* newLocation = self.userLocation.location; - if (self->_renderMode != MLNRenderModeGps) { - self->location_layer.bearingImage = [NSExpression expressionForConstantValue:@"user_puck_icon"]; - self->location_layer.topImage = [NSExpression expressionForConstantValue:@"user_puck_icon"]; - self->location_layer.shadowImage = [NSExpression expressionForConstantValue:@"user_stroke_icon"]; + if (self->location_layer) { + if (self.mapView.userTrackingMode == MLNUserTrackingModeFollowWithCourse) { + if (self.userLocation.location.course >= 0) { + self->location_layer.bearing = [NSExpression expressionForConstantValue:@(self.userLocation.location.course)]; + } - self->_renderMode = MLNRenderModeGps; - } - } else { - if (self->_renderMode != MLNRenderModeNormal && self.mapView.userTrackingMode == MLNUserTrackingModeFollow) { - self->location_layer.bearingImage = self.mapView.showsUserHeadingIndicator ? [NSExpression expressionForConstantValue:@"user_bearing_icon"] : [NSExpression expressionForConstantValue:@"user_icon"]; - self->location_layer.topImage = [NSExpression expressionForConstantValue:@"user_icon"]; - self->location_layer.shadowImage = [NSExpression expressionForConstantValue:@"user_stroke_icon"]; - - self->_renderMode = MLNRenderModeNormal; - } else if (self->_renderMode != MLNRenderModeCompass && self.mapView.userTrackingMode == MLNUserTrackingModeFollowWithHeading) { - self->location_layer.bearingImage = [NSExpression expressionForConstantValue:@"user_bearing_icon"]; - self->location_layer.topImage = [NSExpression expressionForConstantValue:@"user_icon"]; - self->location_layer.shadowImage = [NSExpression expressionForConstantValue:@"user_stroke_icon"]; - - self->_renderMode = MLNRenderModeCompass; - } + if (self->_renderMode != MLNRenderModeGps) { + self->location_layer.bearingImage = [NSExpression expressionForConstantValue:@"user_puck_icon"]; + self->location_layer.topImage = [NSExpression expressionForConstantValue:@"user_puck_icon"]; + self->location_layer.shadowImage = [NSExpression expressionForConstantValue:@"user_stroke_icon"]; - bool showHeading = self.mapView.showsUserHeadingIndicator || self.mapView.userTrackingMode == MLNUserTrackingModeFollowWithHeading; - if (showHeading) { - CLLocationDirection headingDirection = (self.userLocation.heading.trueHeading >= 0 ? self.userLocation.heading.trueHeading : self.userLocation.heading.magneticHeading); - if (headingDirection >= 0) { - self->location_layer.bearing = [NSExpression expressionForConstantValue:@(headingDirection)]; + self->_renderMode = MLNRenderModeGps; + } + } else { + if (self->_renderMode != MLNRenderModeNormal && self.mapView.userTrackingMode == MLNUserTrackingModeFollow) { + self->location_layer.bearingImage = self.mapView.showsUserHeadingIndicator ? [NSExpression expressionForConstantValue:@"user_bearing_icon"] : [NSExpression expressionForConstantValue:@"user_icon"]; + self->location_layer.topImage = [NSExpression expressionForConstantValue:@"user_icon"]; + self->location_layer.shadowImage = [NSExpression expressionForConstantValue:@"user_stroke_icon"]; + + self->_renderMode = MLNRenderModeNormal; + } else if (self->_renderMode != MLNRenderModeCompass && self.mapView.userTrackingMode == MLNUserTrackingModeFollowWithHeading) { + self->location_layer.bearingImage = [NSExpression expressionForConstantValue:@"user_bearing_icon"]; + self->location_layer.topImage = [NSExpression expressionForConstantValue:@"user_icon"]; + self->location_layer.shadowImage = [NSExpression expressionForConstantValue:@"user_stroke_icon"]; + + self->_renderMode = MLNRenderModeCompass; + } + bool showHeading = self.mapView.showsUserHeadingIndicator || self.mapView.userTrackingMode == MLNUserTrackingModeFollowWithHeading; + if (showHeading) { + CLLocationDirection headingDirection = (self.userLocation.heading.trueHeading >= 0 ? self.userLocation.heading.trueHeading : self.userLocation.heading.magneticHeading); + if (headingDirection >= 0) { + self->location_layer.bearing = [NSExpression expressionForConstantValue:@(headingDirection)]; + } } } - } - - CLLocation* newLocation = self.userLocation.location; - if (self->location_layer) { NSTimeInterval duration = 0.3; if(_oldLocation) { duration = MIN([newLocation.timestamp timeIntervalSinceDate:_oldLocation.timestamp], 1.0); @@ -101,6 +104,7 @@ - (void)update { MLNTransition transition = MLNTransitionMake(duration, 0, kCAMediaTimingFunctionLinear); self->location_layer.locationTransition = transition; } + NSArray *location = @[@(newLocation.coordinate.latitude), @(newLocation.coordinate.longitude), @0]; self->location_layer.location = [NSExpression expressionForConstantValue:location]; } @@ -108,4 +112,20 @@ - (void)update { _oldLocation = newLocation; } +- (void)removeLayer { + if (self->location_layer) { + if ([self.mapView.style layerWithIdentifier:@"location_indicator_layer"]) { + [self.mapView.style removeLayer:self->location_layer]; + } + self->location_layer = nil; + } + + [super removeFromSuperview]; +} + +- (void)removeFromSuperview { + [self removeLayer]; + [super removeFromSuperview]; +} + @end diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 7aed678428ad..4d629232babb 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -565,6 +565,7 @@ - (void)setStyleURL:(nullable NSURL *)styleURL } MLNLogDebug(@"Setting styleURL: %@", styleURL); styleURL = styleURL.mgl_URLByStandardizingScheme; + [self removeLocationIndicatorLayer]; self.style = nil; self.mbglMap.getStyle().loadURL([[styleURL absoluteString] UTF8String]); } @@ -572,10 +573,17 @@ - (void)setStyleURL:(nullable NSURL *)styleURL - (IBAction)reloadStyle:(__unused id)sender { MLNLogInfo(@"Reloading style."); NSURL *styleURL = self.styleURL; + [self removeLocationIndicatorLayer]; self.mbglMap.getStyle().loadURL(""); self.styleURL = styleURL; } +- (void)removeLocationIndicatorLayer { + if (self.userLocationAnnotationView && [self.userLocationAnnotationView isKindOfClass:[MLNLocationIndicatorUserLocationAnnotationView class]]) { + [(MLNLocationIndicatorUserLocationAnnotationView*)self.userLocationAnnotationView removeLayer]; + } +} + - (mbgl::Map &)mbglMap { if (!_mbglMap) From 0402cc3d8b708a1f2174ac292ee4d1904736b45a Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Tue, 22 Apr 2025 17:09:25 +0300 Subject: [PATCH 073/221] make new ios release --- platform/ios/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/VERSION b/platform/ios/VERSION index aea5e0b5a6fd..d6008de8362c 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.12.5 +6.12.6 From 6ff84143535b03d70bdbd49c62f5f2cf8f7c9ce2 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 1 May 2025 18:18:27 +0300 Subject: [PATCH 074/221] modify the map transform implementation to make it extendable Make some of the map transform functions virtual to allow for overriding by a child implementation and expose some of the previously private functionality as protected. --- src/mbgl/map/transform.cpp | 10 +++++----- src/mbgl/map/transform.hpp | 27 ++++++++++++++++----------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index dbf23ae98827..a2e0fe371169 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -22,7 +22,7 @@ namespace mbgl { /** Converts the given angle (in radians) to be numerically close to the anchor * angle, allowing it to be interpolated properly without sudden jumps. */ -static double _normalizeAngle(double angle, double anchorAngle) { +double normalizeAngle(double angle, double anchorAngle) { if (std::isnan(angle) || std::isnan(anchorAngle)) { return 0; } @@ -152,8 +152,8 @@ void Transform::easeTo(const CameraOptions& inputCamera, const AnimationOptions& pitch = util::clamp(pitch, state.getMinPitch(), state.getMaxPitch()); // Minimize rotation by taking the shorter path around the circle. - bearing = _normalizeAngle(bearing, state.getBearing()); - state.setBearing(_normalizeAngle(state.getBearing(), bearing)); + bearing = normalizeAngle(bearing, state.getBearing()); + state.setBearing(normalizeAngle(state.getBearing(), bearing)); const double startZoom = state.getZoom(); const double startBearing = state.getBearing(); @@ -232,8 +232,8 @@ void Transform::flyTo(const CameraOptions& inputCamera, pitch = util::clamp(pitch, state.getMinPitch(), state.getMaxPitch()); // Minimize rotation by taking the shorter path around the circle. - bearing = _normalizeAngle(bearing, state.getBearing()); - state.setBearing(_normalizeAngle(state.getBearing(), bearing)); + bearing = normalizeAngle(bearing, state.getBearing()); + state.setBearing(normalizeAngle(state.getBearing(), bearing)); const double startZoom = state.scaleZoom(state.getScale()); const double startBearing = state.getBearing(); const double startPitch = state.getPitch(); diff --git a/src/mbgl/map/transform.hpp b/src/mbgl/map/transform.hpp index eac0e8fb99d6..c18ab4f01cb6 100644 --- a/src/mbgl/map/transform.hpp +++ b/src/mbgl/map/transform.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -16,7 +17,9 @@ namespace mbgl { -class Transform : private util::noncopyable { +double normalizeAngle(double, double); + +class Transform { public: Transform(MapObserver& = MapObserver::nullObserver(), ConstrainMode = ConstrainMode::HeightOnly, @@ -26,6 +29,8 @@ class Transform : private util::noncopyable { : observer(MapObserver::nullObserver()), state(state_) {} + virtual ~Transform() = default; + // Map view void resize(Size size); @@ -38,14 +43,14 @@ class Transform : private util::noncopyable { /** Asynchronously transitions all specified camera options linearly along an optional time curve. However, center coordinate is not transitioned linearly as, instead, ground speed is kept linear.*/ - void easeTo(const CameraOptions&, const AnimationOptions& = {}); + virtual void easeTo(const CameraOptions&, const AnimationOptions& = {}); /** Asynchronously zooms out, pans, and zooms back into the given camera along a great circle, as though the viewer is riding a supersonic jetcopter. Parameter linearZoomInterpolation: when true, there is no additional zooming out as zoom is linearly interpolated from current to given camera zoom. This is used for easeTo.*/ - void flyTo(const CameraOptions&, const AnimationOptions& = {}, bool linearZoomInterpolation = false); + virtual void flyTo(const CameraOptions&, const AnimationOptions& = {}, bool linearZoomInterpolation = false); // Position @@ -95,11 +100,11 @@ class Transform : private util::noncopyable { ProjectionMode getProjectionMode() const; // Transitions - bool inTransition() const; - void updateTransitions(const TimePoint& now); + virtual bool inTransition() const; + virtual void updateTransitions(const TimePoint& now); TimePoint getTransitionStart() const { return transitionStart; } Duration getTransitionDuration() const { return transitionDuration; } - void cancelTransitions(); + virtual void cancelTransitions(); // Gesture void setGestureInProgress(bool); @@ -118,14 +123,14 @@ class Transform : private util::noncopyable { FreeCameraOptions getFreeCameraOptions() const; void setFreeCameraOptions(const FreeCameraOptions& options); -private: +protected: MapObserver& observer; TransformState state; - void startTransition(const CameraOptions&, - const AnimationOptions&, - const std::function&, - const Duration&); + virtual void startTransition(const CameraOptions&, + const AnimationOptions&, + const std::function&, + const Duration&); // We don't want to show horizon: limit max pitch based on edge insets. double getMaxPitchForEdgeInsets(const EdgeInsets& insets) const; From 6ac1c6709ff893e2e0801ebb3096add8c9e3cb81 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 1 May 2025 18:20:17 +0300 Subject: [PATCH 075/221] implement the TransformActive class This class inherits from the map Transform class and overrides the virtual functions to allow for concurrent animations for different types of animations at the same time rather than overriding the previous animation with the latest one. --- CMakeLists.txt | 2 + bazel/core.bzl | 2 + include/mbgl/map/camera.hpp | 22 ++ src/mbgl/map/transform_active.cpp | 463 ++++++++++++++++++++++++++++++ src/mbgl/map/transform_active.hpp | 63 ++++ 5 files changed, 552 insertions(+) create mode 100644 src/mbgl/map/transform_active.cpp create mode 100644 src/mbgl/map/transform_active.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 946db28193b8..3128634d9a3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -534,6 +534,8 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/map/map_projection.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/map/transform.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/map/transform.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/map/transform_active.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/map/transform_active.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/map/transform_state.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/map/transform_state.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/map/zoom_history.hpp diff --git a/bazel/core.bzl b/bazel/core.bzl index d5ffae905f0e..b85794ef09a9 100644 --- a/bazel/core.bzl +++ b/bazel/core.bzl @@ -204,6 +204,8 @@ MLN_CORE_SOURCE = [ "src/mbgl/map/map_projection.cpp", "src/mbgl/map/transform.cpp", "src/mbgl/map/transform.hpp", + "src/mbgl/map/transform_active.cpp", + "src/mbgl/map/transform_active.hpp", "src/mbgl/map/transform_state.cpp", "src/mbgl/map/transform_state.hpp", "src/mbgl/map/zoom_history.hpp", diff --git a/include/mbgl/map/camera.hpp b/include/mbgl/map/camera.hpp index 3bdacf5e8bed..35f3ccf91b2a 100644 --- a/include/mbgl/map/camera.hpp +++ b/include/mbgl/map/camera.hpp @@ -74,6 +74,8 @@ constexpr bool operator!=(const CameraOptions& a, const CameraOptions& b) { return !(a == b); } +struct PropertyAnimation; + /** Various options for describing a transition between viewpoints with animation. All fields are optional; the default values depend on how this struct is used. */ @@ -156,4 +158,24 @@ struct FreeCameraOptions { void setPitchBearing(double pitch, double bearing) noexcept; }; +struct PropertyAnimation { + TimePoint start; + Duration duration; + AnimationOptions animation; + bool ran = false, finished = false, done = false; + + double t(TimePoint now) { + bool isAnimated = duration != Duration::zero(); + double t = isAnimated ? (std::chrono::duration(now - start) / duration) : 1.0f; + if (t >= 1.0) { + return 1.0; + } + + util::UnitBezier ease = animation.easing ? *animation.easing : util::DEFAULT_TRANSITION_EASE; + return ease.solve(t, 0.001); + } + + bool isAnimated() const { return duration != Duration::zero(); } +}; + } // namespace mbgl diff --git a/src/mbgl/map/transform_active.cpp b/src/mbgl/map/transform_active.cpp new file mode 100644 index 000000000000..41d6fef33f82 --- /dev/null +++ b/src/mbgl/map/transform_active.cpp @@ -0,0 +1,463 @@ +#include +#include +#include +#include + +using namespace std::numbers; + +namespace mbgl { + +void TransformActive::easeTo(const CameraOptions& inputCamera, const AnimationOptions& animation) { + CameraOptions camera = inputCamera; + + Duration duration = animation.duration.value_or(Duration::zero()); + if (state.getLatLngBounds() == LatLngBounds() && !isGestureInProgress() && duration != Duration::zero()) { + // reuse flyTo, without exaggerated animation, to achieve constant ground speed. + return flyTo(camera, animation, true); + } + + double zoom = camera.zoom.value_or(getZoom()); + state.constrainCameraAndZoomToBounds(camera, zoom); + + const EdgeInsets& padding = camera.padding.value_or(state.getEdgeInsets()); + LatLng startLatLng = getLatLng(LatLng::Unwrapped); + const LatLng& unwrappedLatLng = camera.center.value_or(startLatLng); + const LatLng& latLng = state.getLatLngBounds() != LatLngBounds() ? unwrappedLatLng : unwrappedLatLng.wrapped(); + + double bearing = camera.bearing ? util::deg2rad(-*camera.bearing) : getBearing(); + double pitch = camera.pitch ? util::deg2rad(*camera.pitch) : getPitch(); + + if (std::isnan(zoom) || std::isnan(bearing) || std::isnan(pitch)) { + if (animation.transitionFinishFn) { + animation.transitionFinishFn(); + } + return; + } + + if (state.getLatLngBounds() == LatLngBounds()) { + if (isGestureInProgress()) { + // If gesture in progress, we transfer the wrap rounds from the end + // longitude into start, so the "scroll effect" of rounding the + // world is the same while assuring the end longitude remains + // wrapped. + const double wrap = unwrappedLatLng.longitude() - latLng.longitude(); + startLatLng = LatLng(startLatLng.latitude(), startLatLng.longitude() - wrap); + } else { + // Find the shortest path otherwise. + startLatLng.unwrapForShortestPath(latLng); + } + } + + const Point startPoint = Projection::project(startLatLng, state.getScale()); + const Point endPoint = Projection::project(latLng, state.getScale()); + + // Constrain camera options. + zoom = util::clamp(zoom, state.getMinZoom(), state.getMaxZoom()); + pitch = util::clamp(pitch, state.getMinPitch(), state.getMaxPitch()); + + // Minimize rotation by taking the shorter path around the circle. + bearing = normalizeAngle(bearing, state.getBearing()); + state.setBearing(normalizeAngle(state.getBearing(), bearing)); + + const double startZoom = state.getZoom(); + const double startBearing = state.getBearing(); + const double startPitch = state.getPitch(); + state.setProperties(TransformStateProperties() + .withPanningInProgress(unwrappedLatLng != startLatLng) + .withScalingInProgress(zoom != startZoom) + .withRotatingInProgress(bearing != startBearing)); + const EdgeInsets startEdgeInsets = state.getEdgeInsets(); + + visit_pas([this](std::shared_ptr& pa) { animationFinishFrame(pa); }); + + auto pa = std::make_shared(Clock::now(), duration, animation); + + // NOTE: For tests only + transitionStart = pa->start; + transitionDuration = pa->duration; + + if (!pas.zoom.set || startZoom != zoom) { + pas.zoom = { + .pa = pa, + .current = startZoom, + .target = zoom, + .frameZoomFunc = + [=, this](TimePoint now) { + return util::interpolate(pas.zoom.current, pas.zoom.target, pas.zoom.pa->t(now)); + }, + .set = true, + }; + } + if (!pas.latlng.set || startPoint != endPoint) { + pas.latlng = { + .pa = pa, + .current = startPoint, + .target = endPoint, + .frameLatLngFunc = + [=, this](TimePoint now) { + Point framePoint = util::interpolate( + pas.latlng.current, pas.latlng.target, pas.latlng.pa->t(now)); + return Projection::unproject(framePoint, state.zoomScale(startZoom)); + }, + .set = true, + }; + } + if (!pas.bearing.set || bearing != startBearing) { + pas.bearing = { + .pa = pa, + .current = startBearing, + .target = bearing, + .set = true, + }; + } + if (!pas.padding.set || padding != startEdgeInsets) { + pas.padding = { + .pa = pa, + .current = startEdgeInsets, + .target = padding, + .set = true, + }; + } + if (!pas.pitch.set || pitch != startPitch) { + pas.pitch = { + .pa = pa, + .current = startPitch, + .target = pitch, + .set = true, + }; + } + + startTransition(camera, duration); +} + +void TransformActive::flyTo(const CameraOptions& inputCamera, + const AnimationOptions& animation, + bool linearZoomInterpolation) { + CameraOptions camera = inputCamera; + + double zoom = camera.zoom.value_or(getZoom()); + state.constrainCameraAndZoomToBounds(camera, zoom); + + const EdgeInsets& padding = camera.padding.value_or(state.getEdgeInsets()); + const LatLng& latLng = camera.center.value_or(getLatLng(LatLng::Unwrapped)).wrapped(); + + double bearing = camera.bearing ? util::deg2rad(-*camera.bearing) : getBearing(); + double pitch = camera.pitch ? util::deg2rad(*camera.pitch) : getPitch(); + + if (std::isnan(zoom) || std::isnan(bearing) || std::isnan(pitch) || state.getSize().isEmpty()) { + if (animation.transitionFinishFn) { + animation.transitionFinishFn(); + } + return; + } + + // Determine endpoints. + LatLng startLatLng = getLatLng(LatLng::Unwrapped).wrapped(); + startLatLng.unwrapForShortestPath(latLng); + + const Point startPoint = Projection::project(startLatLng, state.getScale()); + const Point endPoint = Projection::project(latLng, state.getScale()); + + // Constrain camera options. + zoom = util::clamp(zoom, state.getMinZoom(), state.getMaxZoom()); + pitch = util::clamp(pitch, state.getMinPitch(), state.getMaxPitch()); + + // Minimize rotation by taking the shorter path around the circle. + bearing = normalizeAngle(bearing, state.getBearing()); + state.setBearing(normalizeAngle(state.getBearing(), bearing)); + const double startZoom = state.scaleZoom(state.getScale()); + const double startBearing = state.getBearing(); + const double startPitch = state.getPitch(); + + /// w₀: Initial visible span, measured in pixels at the initial scale. + /// Known henceforth as a screenful. + + double w0 = std::max(state.getSize().width - padding.left() - padding.right(), + state.getSize().height - padding.top() - padding.bottom()); + /// w₁: Final visible span, measured in pixels with respect to the initial + /// scale. + double w1 = w0 / state.zoomScale(zoom - startZoom); + /// Length of the flight path as projected onto the ground plane, measured + /// in pixels from the world image origin at the initial scale. + double u1 = ::hypot((endPoint - startPoint).x, (endPoint - startPoint).y); + + /** ρ: The relative amount of zooming that takes place along the flight + path. A high value maximizes zooming for an exaggerated animation, while + a low value minimizes zooming for something closer to easeTo(). + + 1.42 is the average value selected by participants in the user study in + van Wijk (2003). A value of 6¼ would be equivalent to the + root mean squared average velocity, VRMS. A value of 1 + produces a circular motion. */ + double rho = 1.42; + if (animation.minZoom || linearZoomInterpolation) { + double minZoom = util::min(animation.minZoom.value_or(startZoom), startZoom, zoom); + minZoom = util::clamp(minZoom, state.getMinZoom(), state.getMaxZoom()); + /// wm: Maximum visible span, measured in pixels with respect + /// to the initial scale. + double wMax = w0 / state.zoomScale(minZoom - startZoom); + rho = u1 != 0 ? std::sqrt(wMax / u1 * 2) : 1.0; + } + /// ρ² + double rho2 = rho * rho; + + /** rᵢ: Returns the zoom-out factor at one end of the animation. + + @param i 0 for the ascent or 1 for the descent. */ + auto r = [=](double i) { + /// bᵢ + double b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1); + return std::log(std::sqrt(b * b + 1) - b); + }; + + /// r₀: Zoom-out factor during ascent. + double r0 = u1 != 0 ? r(0) : INFINITY; // Silence division by 0 on sanitize bot. + double r1 = u1 != 0 ? r(1) : INFINITY; + + // When u₀ = u₁, the optimal path doesn’t require both ascent and descent. + bool isClose = std::abs(u1) < 0.000001 || !std::isfinite(r0) || !std::isfinite(r1); + + /** w(s): Returns the visible span on the ground, measured in pixels with + respect to the initial scale. + + Assumes an angular field of view of 2 arctan ½ ≈ 53°. */ + auto w = [=](double s) { + return (isClose ? std::exp((w1 < w0 ? -1 : 1) * rho * s) : (std::cosh(r0) / std::cosh(r0 + rho * s))); + }; + /// u(s): Returns the distance along the flight path as projected onto the + /// ground plane, measured in pixels from the world image origin at the + /// initial scale. + auto u = [=](double s) { + return (isClose ? 0. : (w0 * (std::cosh(r0) * std::tanh(r0 + rho * s) - std::sinh(r0)) / rho2 / u1)); + }; + /// S: Total length of the flight path, measured in ρ-screenfuls. + double S = (isClose ? (std::abs(std::log(w1 / w0)) / rho) : ((r1 - r0) / rho)); + + Duration duration; + if (animation.duration) { + duration = *animation.duration; + } else { + /// V: Average velocity, measured in ρ-screenfuls per second. + double velocity = 1.2; + if (animation.velocity) { + velocity = *animation.velocity / rho; + } + duration = std::chrono::duration_cast(std::chrono::duration(S / velocity)); + } + if (duration == Duration::zero()) { + // Perform an instantaneous transition. + jumpTo(camera); + if (animation.transitionFinishFn) { + animation.transitionFinishFn(); + } + return; + } + + const double startScale = state.getScale(); + state.setProperties( + TransformStateProperties().withPanningInProgress(true).withScalingInProgress(true).withRotatingInProgress( + bearing != startBearing)); + const EdgeInsets startEdgeInsets = state.getEdgeInsets(); + + visit_pas([this](std::shared_ptr& pa) { animationFinishFrame(pa); }); + + auto pa = std::make_shared(Clock::now(), duration, animation); + + // NOTE: For tests only + transitionStart = pa->start; + transitionDuration = pa->duration; + + if (!pas.zoom.set || startZoom != zoom) { + pas.zoom = { + .pa = pa, + .current = startZoom, + .target = zoom, + .frameZoomFunc = + [=, this](TimePoint now) { + double t = pas.zoom.pa->t(now); + double s = t * S; + double frameZoom = linearZoomInterpolation ? util::interpolate(pas.zoom.current, pas.zoom.target, t) + : pas.zoom.current + state.scaleZoom(1 / w(s)); + + if (std::isnan(frameZoom)) { + frameZoom = pas.zoom.target; + } + + return frameZoom; + }, + .set = true, + }; + } + if (!pas.latlng.set || startPoint != endPoint) { + pas.latlng = { + .pa = pa, + .current = startPoint, + .target = endPoint, + .frameLatLngFunc = + [=, this](TimePoint now) { + double t = pas.latlng.pa->t(now); + double s = t * S; + double us = t == 1.0 ? 1.0 : u(s); + + Point framePoint = util::interpolate(pas.latlng.current, pas.latlng.target, us); + return Projection::unproject(framePoint, startScale); + }, + .set = true, + }; + } + if (!pas.bearing.set || bearing != startBearing) { + pas.bearing = { + .pa = pa, + .current = startBearing, + .target = bearing, + .set = true, + }; + } + if (!pas.padding.set || padding != startEdgeInsets) { + pas.padding = {.pa = pa, .current = startEdgeInsets, .target = padding, .set = true}; + } + if (!pas.pitch.set || pitch != startPitch) { + pas.pitch = { + .pa = pa, + .current = startPitch, + .target = pitch, + .set = true, + }; + } + + startTransition(camera, duration); +} + +bool TransformActive::animationTransitionFrame(std::shared_ptr& pa, double t) { + if (pa->ran) { + return pa->done; + } + + pa->ran = true; + if (t < 1.0) { + if (pa->animation.transitionFrameFn) { + pa->animation.transitionFrameFn(t); + } + + observer.onCameraIsChanging(); + pa->done = false; + } else { + pa->done = true; + } + + return pa->done; +} + +void TransformActive::animationFinishFrame(std::shared_ptr& pa) { + if (!pa || pa->finished) { + return; + } + + // TODO(yousifd): The state isn't necessarily all set to false for all properties, double check what you can do + state.setProperties( + TransformStateProperties().withPanningInProgress(false).withScalingInProgress(false).withRotatingInProgress( + false)); + + if (pa->animation.transitionFinishFn) { + pa->animation.transitionFinishFn(); + } + + pa->finished = true; + + observer.onCameraDidChange(pa->isAnimated() ? MapObserver::CameraChangeMode::Animated + : MapObserver::CameraChangeMode::Immediate); +} + +void TransformActive::startTransition(const CameraOptions& camera, const Duration& duration) { + bool isAnimated = duration != Duration::zero(); + observer.onCameraWillChange(isAnimated ? MapObserver::CameraChangeMode::Animated + : MapObserver::CameraChangeMode::Immediate); + + // Associate the anchor, if given, with a coordinate. + // Anchor and center points are mutually exclusive, with preference for the + // center point when both are set. + pas.latlng.anchor = camera.center ? std::nullopt : camera.anchor; + if (pas.latlng.anchor) { + pas.latlng.anchor->y = state.getSize().height - pas.latlng.anchor->y; + pas.latlng.anchorLatLng = state.screenCoordinateToLatLng(*pas.latlng.anchor); + } + + if (!isAnimated) { + activeAnimation = false; + updateTransitions(Clock::now()); + } +} + +bool TransformActive::inTransition() const { + return pas.latlng.set || pas.zoom.set || pas.bearing.set || pas.padding.set || pas.pitch.set; +} + +void TransformActive::updateTransitions(const TimePoint& now) { + if (!activeAnimation) { + activeAnimation = true; + + if (pas.latlng.frameLatLngFunc && pas.zoom.frameZoomFunc) { + if (pas.latlng.set || pas.zoom.set) { + state.setLatLngZoom(pas.latlng.frameLatLngFunc(now), pas.zoom.frameZoomFunc(now)); + if (animationTransitionFrame(pas.latlng.pa, pas.latlng.pa->t(now))) { + pas.latlng.set = false; + } + if (animationTransitionFrame(pas.zoom.pa, pas.zoom.pa->t(now))) { + pas.zoom.set = false; + } + } + } + + if (pas.bearing.set) { + double bearing_t = pas.bearing.pa->t(now); + state.setBearing( + util::wrap(util::interpolate(pas.bearing.current, pas.bearing.target, bearing_t), -pi, pi)); + if (animationTransitionFrame(pas.bearing.pa, bearing_t)) { + pas.bearing.set = false; + } + } + + if (pas.padding.set) { + double padding_t = pas.padding.pa->t(now); + state.setEdgeInsets( + {util::interpolate(pas.padding.current.top(), pas.padding.target.top(), padding_t), + util::interpolate(pas.padding.current.left(), pas.padding.target.left(), padding_t), + util::interpolate(pas.padding.current.bottom(), pas.padding.target.bottom(), padding_t), + util::interpolate(pas.padding.current.right(), pas.padding.target.right(), padding_t)}); + if (animationTransitionFrame(pas.padding.pa, padding_t)) { + pas.padding.set = false; + } + } + + double maxPitch = getMaxPitchForEdgeInsets(state.getEdgeInsets()); + if (pas.pitch.set || maxPitch < pas.pitch.current) { + double pitch_t = pas.pitch.pa->t(now); + state.setPitch(std::min(maxPitch, util::interpolate(pas.pitch.current, pas.pitch.target, pitch_t))); + if (animationTransitionFrame(pas.pitch.pa, pitch_t)) { + pas.pitch.set = false; + } + } + + if (pas.latlng.anchor) { + state.moveLatLng(pas.latlng.anchorLatLng, *pas.latlng.anchor); + } + + visit_pas([this](std::shared_ptr& pa) { + if (pa) { + if (pa->done) animationFinishFrame(pa); + pa->ran = false; + } + }); + + activeAnimation = false; + } +} + +void TransformActive::cancelTransitions() { + visit_pas([this](std::shared_ptr& pa) { animationFinishFrame(pa); }); + + pas = {}; + activeAnimation = false; +} + +} // namespace mbgl diff --git a/src/mbgl/map/transform_active.hpp b/src/mbgl/map/transform_active.hpp new file mode 100644 index 000000000000..22b0c10896ca --- /dev/null +++ b/src/mbgl/map/transform_active.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include + +namespace mbgl { + +template +struct TransformProperty { + std::shared_ptr pa; + T current, target; + bool set = false; + + std::function frameLatLngFunc = nullptr; + std::function frameZoomFunc = nullptr; + + // Anchor + std::optional anchor; + LatLng anchorLatLng; +}; + +struct PropertyAnimations { + TransformProperty> latlng; + TransformProperty zoom, bearing, pitch; + TransformProperty padding; +}; + +class TransformActive : public Transform { +public: + using Transform::Transform; + + void easeTo(const CameraOptions&, const AnimationOptions& = {}) override; + void flyTo(const CameraOptions&, const AnimationOptions& = {}, bool linearZoomInterpolation = false) override; + + bool inTransition() const override; + void updateTransitions(const TimePoint&) override; + void cancelTransitions() override; + +private: + void startTransition(const CameraOptions&, + const AnimationOptions&, + const std::function&, + const Duration&) override { + assert(false); + }; + + void startTransition(const CameraOptions&, const Duration&); + + bool animationTransitionFrame(std::shared_ptr&, double); + void animationFinishFrame(std::shared_ptr&); + + void visit_pas(const std::function&)>& f) { + f(pas.latlng.pa); + f(pas.zoom.pa); + f(pas.bearing.pa); + f(pas.pitch.pa); + f(pas.padding.pa); + } + + PropertyAnimations pas; + bool activeAnimation = false; +}; + +} // namespace mbgl From a1e1460bbdf4ed873c58b9d01e9990fca80a3359 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 1 May 2025 18:23:51 +0300 Subject: [PATCH 076/221] make map transform tests parameterized to test the new TransformActive class --- test/map/transform.test.cpp | 1184 ++++++++++++++++++----------------- 1 file changed, 602 insertions(+), 582 deletions(-) diff --git a/test/map/transform.test.cpp b/test/map/transform.test.cpp index c2efcf9d70b2..7b9c37184926 100644 --- a/test/map/transform.test.cpp +++ b/test/map/transform.test.cpp @@ -6,92 +6,95 @@ #include #include #include +#include #include using namespace std::numbers; using namespace mbgl; -TEST(Transform, InvalidZoom) { - Transform transform; - transform.resize({1, 1}); +class TransfromParametrized : public testing::TestWithParam> {}; - ASSERT_DOUBLE_EQ(0, transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(0, transform.getLatLng().longitude()); - ASSERT_DOUBLE_EQ(0, transform.getZoom()); +TEST_P(TransfromParametrized, InvalidZoom) { + std::shared_ptr transform = GetParam(); + transform->resize({1, 1}); - transform.jumpTo(CameraOptions().withZoom(1.0)); + ASSERT_DOUBLE_EQ(0, transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(0, transform->getLatLng().longitude()); + ASSERT_DOUBLE_EQ(0, transform->getZoom()); - ASSERT_DOUBLE_EQ(1, transform.getZoom()); + transform->jumpTo(CameraOptions().withZoom(1.0)); + + ASSERT_DOUBLE_EQ(1, transform->getZoom()); const double invalid = NAN; - transform.jumpTo(CameraOptions().withZoom(invalid)); + transform->jumpTo(CameraOptions().withZoom(invalid)); - ASSERT_DOUBLE_EQ(0, transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(0, transform.getLatLng().longitude()); - ASSERT_DOUBLE_EQ(1, transform.getZoom()); + ASSERT_DOUBLE_EQ(0, transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(0, transform->getLatLng().longitude()); + ASSERT_DOUBLE_EQ(1, transform->getZoom()); - transform.jumpTo(CameraOptions().withCenter(LatLng()).withZoom(invalid)); + transform->jumpTo(CameraOptions().withCenter(LatLng()).withZoom(invalid)); - ASSERT_DOUBLE_EQ(0, transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(0, transform.getLatLng().longitude()); - ASSERT_DOUBLE_EQ(1, transform.getZoom()); + ASSERT_DOUBLE_EQ(0, transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(0, transform->getLatLng().longitude()); + ASSERT_DOUBLE_EQ(1, transform->getZoom()); - transform.jumpTo(CameraOptions().withZoom(transform.getState().getMaxZoom() + 0.1)); - ASSERT_DOUBLE_EQ(transform.getZoom(), transform.getState().getMaxZoom()); + transform->jumpTo(CameraOptions().withZoom(transform->getState().getMaxZoom() + 0.1)); + ASSERT_DOUBLE_EQ(transform->getZoom(), transform->getState().getMaxZoom()); // Executing flyTo with an empty size causes frameZoom to be NaN. - transform.flyTo(CameraOptions() - .withCenter(LatLng{util::LATITUDE_MAX, util::LONGITUDE_MAX}) - .withZoom(transform.getState().getMaxZoom())); - transform.updateTransitions(transform.getTransitionStart() + transform.getTransitionDuration()); - ASSERT_DOUBLE_EQ(transform.getZoom(), transform.getState().getMaxZoom()); + transform->flyTo(CameraOptions() + .withCenter(LatLng{util::LATITUDE_MAX, util::LONGITUDE_MAX}) + .withZoom(transform->getState().getMaxZoom())); + transform->updateTransitions(transform->getTransitionStart() + transform->getTransitionDuration()); + ASSERT_DOUBLE_EQ(transform->getZoom(), transform->getState().getMaxZoom()); // Executing flyTo with maximum zoom level to the same zoom level causes // frameZoom to be bigger than maximum zoom. - transform.resize(Size{100, 100}); - transform.flyTo(CameraOptions() - .withCenter(LatLng{util::LATITUDE_MAX, util::LONGITUDE_MAX}) - .withZoom(transform.getState().getMaxZoom())); - transform.updateTransitions(transform.getTransitionStart() + transform.getTransitionDuration()); - - ASSERT_TRUE(transform.getState().valid()); - ASSERT_DOUBLE_EQ(transform.getState().getMaxZoom(), transform.getZoom()); + transform->resize(Size{100, 100}); + transform->flyTo(CameraOptions() + .withCenter(LatLng{util::LATITUDE_MAX, util::LONGITUDE_MAX}) + .withZoom(transform->getState().getMaxZoom())); + transform->updateTransitions(transform->getTransitionStart() + transform->getTransitionDuration()); + + ASSERT_TRUE(transform->getState().valid()); + ASSERT_DOUBLE_EQ(transform->getState().getMaxZoom(), transform->getZoom()); } -TEST(Transform, InvalidBearing) { - Transform transform; - transform.resize({1, 1}); +TEST_P(TransfromParametrized, InvalidBearing) { + std::shared_ptr transform = GetParam(); + transform->resize({1, 1}); - ASSERT_DOUBLE_EQ(0, transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(0, transform.getLatLng().longitude()); - ASSERT_DOUBLE_EQ(0, transform.getZoom()); + ASSERT_DOUBLE_EQ(0, transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(0, transform->getLatLng().longitude()); + ASSERT_DOUBLE_EQ(0, transform->getZoom()); - transform.jumpTo(CameraOptions().withZoom(1.0).withBearing(2.0)); - ASSERT_DOUBLE_EQ(0, transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(0, transform.getLatLng().longitude()); - ASSERT_DOUBLE_EQ(1, transform.getZoom()); - ASSERT_DOUBLE_EQ(util::deg2rad(-2.0), transform.getBearing()); + transform->jumpTo(CameraOptions().withZoom(1.0).withBearing(2.0)); + ASSERT_DOUBLE_EQ(0, transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(0, transform->getLatLng().longitude()); + ASSERT_DOUBLE_EQ(1, transform->getZoom()); + ASSERT_DOUBLE_EQ(util::deg2rad(-2.0), transform->getBearing()); const double invalid = NAN; - transform.jumpTo(CameraOptions().withBearing(invalid)); - ASSERT_DOUBLE_EQ(0, transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(0, transform.getLatLng().longitude()); - ASSERT_DOUBLE_EQ(1, transform.getZoom()); - ASSERT_DOUBLE_EQ(util::deg2rad(-2.0), transform.getBearing()); + transform->jumpTo(CameraOptions().withBearing(invalid)); + ASSERT_DOUBLE_EQ(0, transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(0, transform->getLatLng().longitude()); + ASSERT_DOUBLE_EQ(1, transform->getZoom()); + ASSERT_DOUBLE_EQ(util::deg2rad(-2.0), transform->getBearing()); } -TEST(Transform, IntegerZoom) { - Transform transform; - transform.resize({1, 1}); +TEST_P(TransfromParametrized, IntegerZoom) { + std::shared_ptr transform = GetParam(); + transform->resize({1, 1}); auto checkIntegerZoom = [&transform](uint8_t zoomInt, double zoom) { - transform.jumpTo(CameraOptions().withZoom(zoom)); - ASSERT_NEAR(transform.getZoom(), zoom, 1e-8); - ASSERT_EQ(transform.getState().getIntegerZoom(), zoomInt); - ASSERT_NEAR(transform.getState().getZoomFraction(), zoom - zoomInt, 1e-8); + transform->jumpTo(CameraOptions().withZoom(zoom)); + ASSERT_NEAR(transform->getZoom(), zoom, 1e-8); + ASSERT_EQ(transform->getState().getIntegerZoom(), zoomInt); + ASSERT_NEAR(transform->getState().getZoomFraction(), zoom - zoomInt, 1e-8); }; for (uint8_t zoomInt = 0; zoomInt < 20; ++zoomInt) { @@ -105,56 +108,56 @@ TEST(Transform, IntegerZoom) { checkIntegerZoom(20, 20.0); } -TEST(Transform, PerspectiveProjection) { +TEST_P(TransfromParametrized, PerspectiveProjection) { LatLng loc; - Transform transform; - transform.resize({1000, 1000}); + std::shared_ptr transform = GetParam(); + transform->resize({1000, 1000}); // 0.9 rad ~ 51.56620156 deg - transform.jumpTo(CameraOptions().withCenter(LatLng{38.0, -77.0}).withZoom(10.0).withPitch(51.56620156)); + transform->jumpTo(CameraOptions().withCenter(LatLng{38.0, -77.0}).withZoom(10.0).withPitch(51.56620156)); // expected values are from maplibre-gl-js - loc = transform.getLatLng(); + loc = transform->getLatLng(); ASSERT_DOUBLE_EQ(-77, loc.longitude()); ASSERT_DOUBLE_EQ(38, loc.latitude()); - loc = transform.getState().screenCoordinateToLatLng({0, 1000}); + loc = transform->getState().screenCoordinateToLatLng({0, 1000}); ASSERT_NEAR(-77.59198961199148, loc.longitude(), 1e-6); ASSERT_NEAR(38.74661326302018, loc.latitude(), 1e-6); - loc = transform.getState().screenCoordinateToLatLng({1000, 0}); + loc = transform->getState().screenCoordinateToLatLng({1000, 0}); ASSERT_NEAR(-76.75823239205641, loc.longitude(), 1e-6); ASSERT_NEAR(37.692872969426375, loc.latitude(), 1e-6); - ScreenCoordinate point = transform.getState().latLngToScreenCoordinate({38.74661326302018, -77.59198961199148}); + ScreenCoordinate point = transform->getState().latLngToScreenCoordinate({38.74661326302018, -77.59198961199148}); ASSERT_NEAR(point.x, 0.0, 1e-5); ASSERT_NEAR(point.y, 1000.0, 1e-4); - point = transform.getState().latLngToScreenCoordinate({37.692872969426375, -76.75823239205641}); + point = transform->getState().latLngToScreenCoordinate({37.692872969426375, -76.75823239205641}); ASSERT_NEAR(point.x, 1000.0, 1e-5); ASSERT_NEAR(point.y, 0.0, 1e-4); mbgl::vec4 p; - point = transform.getState().latLngToScreenCoordinate({37.692872969426375, -76.75823239205641}, p); + point = transform->getState().latLngToScreenCoordinate({37.692872969426375, -76.75823239205641}, p); ASSERT_NEAR(point.x, 1000.0, 1e-5); ASSERT_NEAR(point.y, 0.0, 1e-4); ASSERT_GT(p[3], 0.0); - transform.jumpTo(CameraOptions().withCenter(LatLng{38.0, -77.0}).withZoom(18.0).withPitch(51.56620156)); - point = transform.getState().latLngToScreenCoordinate({7.692872969426375, -76.75823239205641}, p); + transform->jumpTo(CameraOptions().withCenter(LatLng{38.0, -77.0}).withZoom(18.0).withPitch(51.56620156)); + point = transform->getState().latLngToScreenCoordinate({7.692872969426375, -76.75823239205641}, p); ASSERT_LT(p[3], 0.0); } -TEST(Transform, UnwrappedLatLng) { - Transform transform; - transform.resize({1000, 1000}); +TEST_P(TransfromParametrized, UnwrappedLatLng) { + std::shared_ptr transform = GetParam(); + transform->resize({1000, 1000}); // 0.9 rad ~ 51.56620156 deg - transform.jumpTo(CameraOptions().withCenter(LatLng{38.0, -77.0}).withZoom(10.0).withPitch(51.56620156)); + transform->jumpTo(CameraOptions().withCenter(LatLng{38.0, -77.0}).withZoom(10.0).withPitch(51.56620156)); - const TransformState& state = transform.getState(); + const TransformState& state = transform->getState(); LatLng fromGetLatLng = state.getLatLng(); ASSERT_DOUBLE_EQ(fromGetLatLng.latitude(), 38.0); @@ -177,148 +180,150 @@ TEST(Transform, UnwrappedLatLng) { ASSERT_NEAR(wrappedLeftwards.longitude(), -77.0, 1e-8); } -TEST(Transform, ConstrainHeightOnly) { - Transform transform(MapObserver::nullObserver(), ConstrainMode::HeightOnly); - transform.resize({2, 2}); +TEST_P(TransfromParametrized, ConstrainHeightOnly) { + std::shared_ptr transform = GetParam(); + transform->setConstrainMode(ConstrainMode::HeightOnly); + transform->resize({2, 2}); - transform.jumpTo(CameraOptions().withCenter(LatLngBounds::world().southwest()).withZoom(util::MAX_ZOOM)); - ASSERT_NEAR(-util::LATITUDE_MAX, transform.getLatLng().latitude(), 1e-7); - ASSERT_NEAR(-util::LONGITUDE_MAX, transform.getLatLng().longitude(), 1e-7); + transform->jumpTo(CameraOptions().withCenter(LatLngBounds::world().southwest()).withZoom(util::MAX_ZOOM)); + ASSERT_NEAR(-util::LATITUDE_MAX, transform->getLatLng().latitude(), 1e-7); + ASSERT_NEAR(-util::LONGITUDE_MAX, transform->getLatLng().longitude(), 1e-7); - transform.jumpTo(CameraOptions().withCenter(LatLngBounds::world().northeast())); - ASSERT_NEAR(util::LATITUDE_MAX, transform.getLatLng().latitude(), 1e-7); - ASSERT_NEAR(-util::LONGITUDE_MAX, transform.getLatLng().longitude(), 1e-7); + transform->jumpTo(CameraOptions().withCenter(LatLngBounds::world().northeast())); + ASSERT_NEAR(util::LATITUDE_MAX, transform->getLatLng().latitude(), 1e-7); + ASSERT_NEAR(-util::LONGITUDE_MAX, transform->getLatLng().longitude(), 1e-7); } -TEST(Transform, ConstrainWidthAndHeight) { - Transform transform(MapObserver::nullObserver(), ConstrainMode::WidthAndHeight); - transform.resize({2, 2}); +TEST_P(TransfromParametrized, ConstrainWidthAndHeight) { + std::shared_ptr transform = GetParam(); + transform->setConstrainMode(ConstrainMode::WidthAndHeight); + transform->resize({2, 2}); - transform.jumpTo(CameraOptions().withCenter(LatLngBounds::world().southwest()).withZoom(util::MAX_ZOOM)); - ASSERT_NEAR(-util::LATITUDE_MAX, transform.getLatLng().latitude(), 1e-7); - ASSERT_NEAR(-util::LONGITUDE_MAX, transform.getLatLng().longitude(), 1e-6); + transform->jumpTo(CameraOptions().withCenter(LatLngBounds::world().southwest()).withZoom(util::MAX_ZOOM)); + ASSERT_NEAR(-util::LATITUDE_MAX, transform->getLatLng().latitude(), 1e-7); + ASSERT_NEAR(-util::LONGITUDE_MAX, transform->getLatLng().longitude(), 1e-6); - transform.jumpTo(CameraOptions().withCenter(LatLngBounds::world().northeast())); - ASSERT_NEAR(util::LATITUDE_MAX, transform.getLatLng().latitude(), 1e-7); - ASSERT_NEAR(-util::LONGITUDE_MAX, transform.getLatLng().longitude(), 1e-6); + transform->jumpTo(CameraOptions().withCenter(LatLngBounds::world().northeast())); + ASSERT_NEAR(util::LATITUDE_MAX, transform->getLatLng().latitude(), 1e-7); + ASSERT_NEAR(-util::LONGITUDE_MAX, transform->getLatLng().longitude(), 1e-6); } -TEST(Transform, Anchor) { - Transform transform; - transform.resize({1000, 1000}); +TEST_P(TransfromParametrized, Anchor) { + std::shared_ptr transform = GetParam(); + transform->resize({1000, 1000}); const LatLng latLng{10, -100}; const ScreenCoordinate anchorPoint = {150, 150}; - transform.jumpTo(CameraOptions().withCenter(latLng).withZoom(10.0)); - ASSERT_DOUBLE_EQ(latLng.latitude(), transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(latLng.longitude(), transform.getLatLng().longitude()); - ASSERT_DOUBLE_EQ(10, transform.getZoom()); - ASSERT_DOUBLE_EQ(0, transform.getBearing()); + transform->jumpTo(CameraOptions().withCenter(latLng).withZoom(10.0)); + ASSERT_DOUBLE_EQ(latLng.latitude(), transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(latLng.longitude(), transform->getLatLng().longitude()); + ASSERT_DOUBLE_EQ(10, transform->getZoom()); + ASSERT_DOUBLE_EQ(0, transform->getBearing()); - const LatLng anchorLatLng = transform.getState().screenCoordinateToLatLng(anchorPoint); + const LatLng anchorLatLng = transform->getState().screenCoordinateToLatLng(anchorPoint); ASSERT_NE(latLng.latitude(), anchorLatLng.latitude()); ASSERT_NE(latLng.longitude(), anchorLatLng.longitude()); - transform.jumpTo(CameraOptions().withCenter(latLng).withZoom(3.0)); - ASSERT_DOUBLE_EQ(3, transform.getZoom()); - ASSERT_DOUBLE_EQ(latLng.latitude(), transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(latLng.longitude(), transform.getLatLng().longitude()); - - transform.jumpTo(CameraOptions().withZoom(3.5)); - ASSERT_DOUBLE_EQ(3.5, transform.getZoom()); - ASSERT_DOUBLE_EQ(latLng.latitude(), transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(latLng.longitude(), transform.getLatLng().longitude()); - - transform.jumpTo(CameraOptions().withZoom(5.5).withAnchor(anchorPoint)); - ASSERT_DOUBLE_EQ(5.5, transform.getZoom()); - ASSERT_NE(latLng.latitude(), transform.getLatLng().latitude()); - ASSERT_NE(latLng.longitude(), transform.getLatLng().longitude()); - - transform.jumpTo(CameraOptions().withCenter(latLng).withZoom(3.0)); - ASSERT_DOUBLE_EQ(3, transform.getZoom()); - ASSERT_DOUBLE_EQ(latLng.latitude(), transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(latLng.longitude(), transform.getLatLng().longitude()); - - transform.jumpTo(CameraOptions().withZoom(5.0)); - ASSERT_DOUBLE_EQ(5, transform.getZoom()); - ASSERT_DOUBLE_EQ(latLng.latitude(), transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(latLng.longitude(), transform.getLatLng().longitude()); - - transform.jumpTo(CameraOptions().withZoom(7.0).withAnchor(anchorPoint)); - ASSERT_DOUBLE_EQ(7, transform.getZoom()); - ASSERT_NE(latLng.latitude(), transform.getLatLng().latitude()); - ASSERT_NE(latLng.longitude(), transform.getLatLng().longitude()); - - transform.jumpTo(CameraOptions().withCenter(latLng).withZoom(2.0)); - ASSERT_DOUBLE_EQ(2, transform.getZoom()); - ASSERT_DOUBLE_EQ(latLng.latitude(), transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(latLng.longitude(), transform.getLatLng().longitude()); - - transform.jumpTo(CameraOptions().withZoom(4.0)); - ASSERT_DOUBLE_EQ(4, transform.getZoom()); - ASSERT_DOUBLE_EQ(latLng.latitude(), transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(latLng.longitude(), transform.getLatLng().longitude()); - - transform.jumpTo(CameraOptions().withZoom(8.0).withAnchor(anchorPoint)); - ASSERT_DOUBLE_EQ(8, transform.getZoom()); - ASSERT_NE(latLng.latitude(), transform.getLatLng().latitude()); - ASSERT_NE(latLng.longitude(), transform.getLatLng().longitude()); - - transform.jumpTo(CameraOptions().withCenter(latLng).withZoom(10.0).withBearing(-45.0)); - ASSERT_DOUBLE_EQ(pi / 4, transform.getBearing()); - ASSERT_DOUBLE_EQ(latLng.latitude(), transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(latLng.longitude(), transform.getLatLng().longitude()); - - transform.jumpTo(CameraOptions().withBearing(0.0)); - ASSERT_DOUBLE_EQ(0, transform.getBearing()); - ASSERT_DOUBLE_EQ(latLng.latitude(), transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(latLng.longitude(), transform.getLatLng().longitude()); - - transform.jumpTo(CameraOptions().withBearing(45.0).withAnchor(anchorPoint)); - ASSERT_DOUBLE_EQ(util::deg2rad(-45.0), transform.getBearing()); + transform->jumpTo(CameraOptions().withCenter(latLng).withZoom(3.0)); + ASSERT_DOUBLE_EQ(3, transform->getZoom()); + ASSERT_DOUBLE_EQ(latLng.latitude(), transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(latLng.longitude(), transform->getLatLng().longitude()); + + transform->jumpTo(CameraOptions().withZoom(3.5)); + ASSERT_DOUBLE_EQ(3.5, transform->getZoom()); + ASSERT_DOUBLE_EQ(latLng.latitude(), transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(latLng.longitude(), transform->getLatLng().longitude()); + + transform->jumpTo(CameraOptions().withZoom(5.5).withAnchor(anchorPoint)); + ASSERT_DOUBLE_EQ(5.5, transform->getZoom()); + ASSERT_NE(latLng.latitude(), transform->getLatLng().latitude()); + ASSERT_NE(latLng.longitude(), transform->getLatLng().longitude()); + + transform->jumpTo(CameraOptions().withCenter(latLng).withZoom(3.0)); + ASSERT_DOUBLE_EQ(3, transform->getZoom()); + ASSERT_DOUBLE_EQ(latLng.latitude(), transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(latLng.longitude(), transform->getLatLng().longitude()); + + transform->jumpTo(CameraOptions().withZoom(5.0)); + ASSERT_DOUBLE_EQ(5, transform->getZoom()); + ASSERT_DOUBLE_EQ(latLng.latitude(), transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(latLng.longitude(), transform->getLatLng().longitude()); + + transform->jumpTo(CameraOptions().withZoom(7.0).withAnchor(anchorPoint)); + ASSERT_DOUBLE_EQ(7, transform->getZoom()); + ASSERT_NE(latLng.latitude(), transform->getLatLng().latitude()); + ASSERT_NE(latLng.longitude(), transform->getLatLng().longitude()); + + transform->jumpTo(CameraOptions().withCenter(latLng).withZoom(2.0)); + ASSERT_DOUBLE_EQ(2, transform->getZoom()); + ASSERT_DOUBLE_EQ(latLng.latitude(), transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(latLng.longitude(), transform->getLatLng().longitude()); + + transform->jumpTo(CameraOptions().withZoom(4.0)); + ASSERT_DOUBLE_EQ(4, transform->getZoom()); + ASSERT_DOUBLE_EQ(latLng.latitude(), transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(latLng.longitude(), transform->getLatLng().longitude()); + + transform->jumpTo(CameraOptions().withZoom(8.0).withAnchor(anchorPoint)); + ASSERT_DOUBLE_EQ(8, transform->getZoom()); + ASSERT_NE(latLng.latitude(), transform->getLatLng().latitude()); + ASSERT_NE(latLng.longitude(), transform->getLatLng().longitude()); + + transform->jumpTo(CameraOptions().withCenter(latLng).withZoom(10.0).withBearing(-45.0)); + ASSERT_DOUBLE_EQ(pi / 4, transform->getBearing()); + ASSERT_DOUBLE_EQ(latLng.latitude(), transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(latLng.longitude(), transform->getLatLng().longitude()); + + transform->jumpTo(CameraOptions().withBearing(0.0)); + ASSERT_DOUBLE_EQ(0, transform->getBearing()); + ASSERT_DOUBLE_EQ(latLng.latitude(), transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(latLng.longitude(), transform->getLatLng().longitude()); + + transform->jumpTo(CameraOptions().withBearing(45.0).withAnchor(anchorPoint)); + ASSERT_DOUBLE_EQ(util::deg2rad(-45.0), transform->getBearing()); // Anchor coordinates are imprecise because we are converting from an integer pixel. - ASSERT_NEAR(anchorLatLng.latitude(), transform.getLatLng().latitude(), 0.5); - ASSERT_NEAR(anchorLatLng.longitude(), transform.getLatLng().longitude(), 0.5); + ASSERT_NEAR(anchorLatLng.latitude(), transform->getLatLng().latitude(), 0.5); + ASSERT_NEAR(anchorLatLng.longitude(), transform->getLatLng().longitude(), 0.5); - transform.jumpTo(CameraOptions().withCenter(latLng).withZoom(10.0).withPitch(10.0)); - ASSERT_DOUBLE_EQ(util::deg2rad(10.0), transform.getPitch()); - ASSERT_DOUBLE_EQ(latLng.latitude(), transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(latLng.longitude(), transform.getLatLng().longitude()); + transform->jumpTo(CameraOptions().withCenter(latLng).withZoom(10.0).withPitch(10.0)); + ASSERT_DOUBLE_EQ(util::deg2rad(10.0), transform->getPitch()); + ASSERT_DOUBLE_EQ(latLng.latitude(), transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(latLng.longitude(), transform->getLatLng().longitude()); - transform.jumpTo(CameraOptions().withPitch(15.0)); - ASSERT_DOUBLE_EQ(util::deg2rad(15.0), transform.getPitch()); - ASSERT_DOUBLE_EQ(latLng.latitude(), transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(latLng.longitude(), transform.getLatLng().longitude()); + transform->jumpTo(CameraOptions().withPitch(15.0)); + ASSERT_DOUBLE_EQ(util::deg2rad(15.0), transform->getPitch()); + ASSERT_DOUBLE_EQ(latLng.latitude(), transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(latLng.longitude(), transform->getLatLng().longitude()); - transform.jumpTo(CameraOptions().withPitch(20.0).withAnchor(anchorPoint)); - ASSERT_DOUBLE_EQ(util::deg2rad(20.0), transform.getPitch()); + transform->jumpTo(CameraOptions().withPitch(20.0).withAnchor(anchorPoint)); + ASSERT_DOUBLE_EQ(util::deg2rad(20.0), transform->getPitch()); // Anchor coordinates are imprecise because we are converting from an integer pixel. - ASSERT_NEAR(anchorLatLng.latitude(), transform.getLatLng().latitude(), 0.5); - ASSERT_NEAR(anchorLatLng.longitude(), transform.getLatLng().longitude(), 0.5); + ASSERT_NEAR(anchorLatLng.latitude(), transform->getLatLng().latitude(), 0.5); + ASSERT_NEAR(anchorLatLng.longitude(), transform->getLatLng().longitude(), 0.5); } -TEST(Transform, Padding) { - Transform transform; - transform.resize({1000, 1000}); +TEST_P(TransfromParametrized, Padding) { + std::shared_ptr transform = GetParam(); + transform->resize({1000, 1000}); - ASSERT_DOUBLE_EQ(0, transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(0, transform.getLatLng().longitude()); + ASSERT_DOUBLE_EQ(0, transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(0, transform->getLatLng().longitude()); CameraOptions nonPaddedCameraOptions = CameraOptions().withCenter(LatLng{10, -100}).withZoom(10.0); - transform.jumpTo(nonPaddedCameraOptions); + transform->jumpTo(nonPaddedCameraOptions); - const LatLng trueCenter = transform.getLatLng(); + const LatLng trueCenter = transform->getLatLng(); ASSERT_DOUBLE_EQ(10, trueCenter.latitude()); ASSERT_DOUBLE_EQ(-100, trueCenter.longitude()); - ASSERT_DOUBLE_EQ(10, transform.getZoom()); + ASSERT_DOUBLE_EQ(10, transform->getZoom()); - const LatLng screenCenter = transform.screenCoordinateToLatLng({ + const LatLng screenCenter = transform->screenCoordinateToLatLng({ 1000.0 / 2.0, 1000.0 / 2.0, }); - const LatLng upperHalfCenter = transform.screenCoordinateToLatLng({ + const LatLng upperHalfCenter = transform->screenCoordinateToLatLng({ 1000.0 / 2.0, 1000.0 * 0.25, }); @@ -327,14 +332,14 @@ TEST(Transform, Padding) { // CameraOption center and zoom don't change when padding changes: center of // viewport remains the same as padding defines viwport center offset in rendering. CameraOptions paddedOptions = CameraOptions().withPadding(padding); - transform.jumpTo(paddedOptions); - const LatLng theSameCenter = transform.getLatLng(); + transform->jumpTo(paddedOptions); + const LatLng theSameCenter = transform->getLatLng(); ASSERT_DOUBLE_EQ(trueCenter.latitude(), theSameCenter.latitude()); ASSERT_DOUBLE_EQ(trueCenter.longitude(), theSameCenter.longitude()); // However, LatLng is now at the center of lower half - verify conversion // from screen coordinate to LatLng. - const LatLng paddedLowerHalfScreenCenter = transform.screenCoordinateToLatLng({ + const LatLng paddedLowerHalfScreenCenter = transform->screenCoordinateToLatLng({ 1000.0 / 2.0, 1000.0 * 0.75, }); @@ -342,7 +347,7 @@ TEST(Transform, Padding) { ASSERT_NEAR(screenCenter.longitude(), paddedLowerHalfScreenCenter.longitude(), 1e-10); // LatLng previously in upper half center, should now be under screen center. - const LatLng paddedScreenCenter = transform.screenCoordinateToLatLng({ + const LatLng paddedScreenCenter = transform->screenCoordinateToLatLng({ 1000.0 / 2.0, 1000.0 / 2.0, }); @@ -350,25 +355,25 @@ TEST(Transform, Padding) { ASSERT_NEAR(upperHalfCenter.longitude(), paddedScreenCenter.longitude(), 1e-10); } -TEST(Transform, MoveBy) { - Transform transform; - transform.resize({1000, 1000}); +TEST_P(TransfromParametrized, MoveBy) { + std::shared_ptr transform = GetParam(); + transform->resize({1000, 1000}); - transform.jumpTo(CameraOptions().withCenter(LatLng()).withZoom(10.0)); + transform->jumpTo(CameraOptions().withCenter(LatLng()).withZoom(10.0)); - LatLng trueCenter = transform.getLatLng(); + LatLng trueCenter = transform->getLatLng(); ASSERT_DOUBLE_EQ(0, trueCenter.latitude()); ASSERT_DOUBLE_EQ(0, trueCenter.longitude()); - ASSERT_DOUBLE_EQ(10, transform.getZoom()); + ASSERT_DOUBLE_EQ(10, transform->getZoom()); for (uint8_t x = 0; x < 20; ++x) { bool odd = x % 2; bool forward = x % 10; - LatLng coordinate = transform.screenCoordinateToLatLng({odd ? 400. : 600., forward ? 400. : 600}); - transform.moveBy({odd ? 100. : -100., forward ? 100. : -100}); + LatLng coordinate = transform->screenCoordinateToLatLng({odd ? 400. : 600., forward ? 400. : 600}); + transform->moveBy({odd ? 100. : -100., forward ? 100. : -100}); - trueCenter = transform.getLatLng(); + trueCenter = transform->getLatLng(); ASSERT_NEAR(coordinate.latitude(), trueCenter.latitude(), 1e-8); ASSERT_NEAR(coordinate.longitude(), trueCenter.longitude(), 1e-8); } @@ -378,190 +383,171 @@ TEST(Transform, MoveBy) { ASSERT_NEAR(0.0, trueCenter.longitude(), 1.1); } -TEST(Transform, Antimeridian) { - Transform transform; - transform.resize({1000, 1000}); +TEST_P(TransfromParametrized, Antimeridian) { + std::shared_ptr transform = GetParam(); + transform->resize({1000, 1000}); - transform.jumpTo(CameraOptions().withCenter(LatLng()).withZoom(1.0)); + transform->jumpTo(CameraOptions().withCenter(LatLng()).withZoom(1.0)); // San Francisco const LatLng coordinateSanFrancisco{37.7833, -122.4167}; - ScreenCoordinate pixelSF = transform.latLngToScreenCoordinate(coordinateSanFrancisco); + ScreenCoordinate pixelSF = transform->latLngToScreenCoordinate(coordinateSanFrancisco); ASSERT_DOUBLE_EQ(151.79249437176432, pixelSF.x); ASSERT_DOUBLE_EQ(383.76720782527661, pixelSF.y); - transform.jumpTo(CameraOptions().withCenter(LatLng{0.0, -181.0})); + transform->jumpTo(CameraOptions().withCenter(LatLng{0.0, -181.0})); - ScreenCoordinate pixelSFLongest = transform.latLngToScreenCoordinate(coordinateSanFrancisco); + ScreenCoordinate pixelSFLongest = transform->latLngToScreenCoordinate(coordinateSanFrancisco); ASSERT_DOUBLE_EQ(-357.36306616412816, pixelSFLongest.x); ASSERT_DOUBLE_EQ(pixelSF.y, pixelSFLongest.y); LatLng unwrappedSF = coordinateSanFrancisco.wrapped(); - unwrappedSF.unwrapForShortestPath(transform.getLatLng()); + unwrappedSF.unwrapForShortestPath(transform->getLatLng()); - ScreenCoordinate pixelSFShortest = transform.latLngToScreenCoordinate(unwrappedSF); + ScreenCoordinate pixelSFShortest = transform->latLngToScreenCoordinate(unwrappedSF); ASSERT_DOUBLE_EQ(666.63694385219173, pixelSFShortest.x); ASSERT_DOUBLE_EQ(pixelSF.y, pixelSFShortest.y); - transform.jumpTo(CameraOptions().withCenter(LatLng{0.0, 179.0})); - pixelSFShortest = transform.latLngToScreenCoordinate(coordinateSanFrancisco); + transform->jumpTo(CameraOptions().withCenter(LatLng{0.0, 179.0})); + pixelSFShortest = transform->latLngToScreenCoordinate(coordinateSanFrancisco); ASSERT_DOUBLE_EQ(pixelSFLongest.x, pixelSFShortest.x); ASSERT_DOUBLE_EQ(pixelSFLongest.y, pixelSFShortest.y); // Waikiri const LatLng coordinateWaikiri{-16.9310, 179.9787}; - transform.jumpTo(CameraOptions().withCenter(coordinateWaikiri).withZoom(10.0)); - ScreenCoordinate pixelWaikiri = transform.latLngToScreenCoordinate(coordinateWaikiri); + transform->jumpTo(CameraOptions().withCenter(coordinateWaikiri).withZoom(10.0)); + ScreenCoordinate pixelWaikiri = transform->latLngToScreenCoordinate(coordinateWaikiri); ASSERT_DOUBLE_EQ(500, pixelWaikiri.x); ASSERT_DOUBLE_EQ(500, pixelWaikiri.y); - transform.jumpTo(CameraOptions().withCenter(LatLng{coordinateWaikiri.latitude(), 180.0213})); - ScreenCoordinate pixelWaikiriLongest = transform.latLngToScreenCoordinate(coordinateWaikiri); + transform->jumpTo(CameraOptions().withCenter(LatLng{coordinateWaikiri.latitude(), 180.0213})); + ScreenCoordinate pixelWaikiriLongest = transform->latLngToScreenCoordinate(coordinateWaikiri); ASSERT_DOUBLE_EQ(524725.96438108233, pixelWaikiriLongest.x); ASSERT_DOUBLE_EQ(pixelWaikiri.y, pixelWaikiriLongest.y); LatLng unwrappedWaikiri = coordinateWaikiri.wrapped(); - unwrappedWaikiri.unwrapForShortestPath(transform.getLatLng()); - ScreenCoordinate pixelWaikiriShortest = transform.latLngToScreenCoordinate(unwrappedWaikiri); + unwrappedWaikiri.unwrapForShortestPath(transform->getLatLng()); + ScreenCoordinate pixelWaikiriShortest = transform->latLngToScreenCoordinate(unwrappedWaikiri); ASSERT_DOUBLE_EQ(437.95925272648344, pixelWaikiriShortest.x); ASSERT_DOUBLE_EQ(pixelWaikiri.y, pixelWaikiriShortest.y); - LatLng coordinateFromPixel = transform.screenCoordinateToLatLng(pixelWaikiriLongest); + LatLng coordinateFromPixel = transform->screenCoordinateToLatLng(pixelWaikiriLongest); ASSERT_NEAR(coordinateWaikiri.latitude(), coordinateFromPixel.latitude(), 1e-4); ASSERT_NEAR(coordinateWaikiri.longitude(), coordinateFromPixel.longitude(), 1e-4); - transform.jumpTo(CameraOptions().withCenter(LatLng{coordinateWaikiri.latitude(), 180.0213})); - pixelWaikiriShortest = transform.latLngToScreenCoordinate(coordinateWaikiri); + transform->jumpTo(CameraOptions().withCenter(LatLng{coordinateWaikiri.latitude(), 180.0213})); + pixelWaikiriShortest = transform->latLngToScreenCoordinate(coordinateWaikiri); ASSERT_DOUBLE_EQ(pixelWaikiriLongest.x, pixelWaikiriShortest.x); ASSERT_DOUBLE_EQ(pixelWaikiriLongest.y, pixelWaikiriShortest.y); - coordinateFromPixel = transform.screenCoordinateToLatLng(pixelWaikiriShortest); + coordinateFromPixel = transform->screenCoordinateToLatLng(pixelWaikiriShortest); ASSERT_NEAR(coordinateWaikiri.latitude(), coordinateFromPixel.latitude(), 1e-4); ASSERT_NEAR(coordinateWaikiri.longitude(), coordinateFromPixel.longitude(), 1e-4); } -TEST(Transform, Camera) { - Transform transform; - transform.resize({1000, 1000}); +TEST_P(TransfromParametrized, Camera) { + std::shared_ptr transform = GetParam(); + transform->resize({1000, 1000}); const LatLng latLng1{45, 135}; CameraOptions cameraOptions1 = CameraOptions().withCenter(latLng1).withZoom(20.0); - transform.jumpTo(cameraOptions1); - ASSERT_DOUBLE_EQ(latLng1.latitude(), transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(latLng1.longitude(), transform.getLatLng().longitude()); - ASSERT_DOUBLE_EQ(20, transform.getZoom()); + transform->jumpTo(cameraOptions1); + ASSERT_DOUBLE_EQ(latLng1.latitude(), transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(latLng1.longitude(), transform->getLatLng().longitude()); + ASSERT_DOUBLE_EQ(20, transform->getZoom()); const LatLng latLng2{-45, -135}; CameraOptions cameraOptions2 = CameraOptions().withCenter(latLng2).withZoom(10.0); - transform.jumpTo(cameraOptions2); - ASSERT_DOUBLE_EQ(latLng2.latitude(), transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(latLng2.longitude(), transform.getLatLng().longitude()); - ASSERT_DOUBLE_EQ(10, transform.getZoom()); + transform->jumpTo(cameraOptions2); + ASSERT_DOUBLE_EQ(latLng2.latitude(), transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(latLng2.longitude(), transform->getLatLng().longitude()); + ASSERT_DOUBLE_EQ(10, transform->getZoom()); AnimationOptions easeOptions(Seconds(1)); easeOptions.transitionFrameFn = [&](double t) { ASSERT_TRUE(t >= 0 && t <= 1); - ASSERT_GE(latLng1.latitude(), transform.getLatLng().latitude()); - ASSERT_LE(latLng1.longitude(), transform.getLatLng().longitude()); + ASSERT_GE(latLng1.latitude(), transform->getLatLng().latitude()); + ASSERT_LE(latLng1.longitude(), transform->getLatLng().longitude()); }; easeOptions.transitionFinishFn = [&]() { - ASSERT_DOUBLE_EQ(latLng1.latitude(), transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(latLng1.longitude(), transform.getLatLng().longitude()); - ASSERT_DOUBLE_EQ(20, transform.getZoom()); + ASSERT_DOUBLE_EQ(latLng1.latitude(), transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(latLng1.longitude(), transform->getLatLng().longitude()); + ASSERT_DOUBLE_EQ(20, transform->getZoom()); }; - transform.easeTo(cameraOptions1, easeOptions); - ASSERT_TRUE(transform.inTransition()); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(250)); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(500)); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(750)); - transform.updateTransitions(transform.getTransitionStart() + transform.getTransitionDuration()); - ASSERT_FALSE(transform.inTransition()); + transform->easeTo(cameraOptions1, easeOptions); + ASSERT_TRUE(transform->inTransition()); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(250)); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(500)); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(750)); + transform->updateTransitions(transform->getTransitionStart() + transform->getTransitionDuration()); + ASSERT_FALSE(transform->inTransition()); AnimationOptions flyOptions(Seconds(1)); flyOptions.transitionFrameFn = [&](double t) { ASSERT_TRUE(t >= 0 && t <= 1); - ASSERT_LE(latLng2.latitude(), transform.getLatLng().latitude()); - ASSERT_GE(latLng2.longitude(), transform.getLatLng(LatLng::Unwrapped).longitude()); + ASSERT_LE(latLng2.latitude(), transform->getLatLng().latitude()); + ASSERT_GE(latLng2.longitude(), transform->getLatLng(LatLng::Unwrapped).longitude()); }; flyOptions.transitionFinishFn = [&]() { // XXX Fix precision loss in flyTo: // https://github.com/mapbox/mapbox-gl-native/issues/4298 - ASSERT_DOUBLE_EQ(latLng2.latitude(), transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(latLng2.longitude(), transform.getLatLng().longitude()); - ASSERT_NEAR(10.0, transform.getZoom(), 1e-5); + ASSERT_DOUBLE_EQ(latLng2.latitude(), transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(latLng2.longitude(), transform->getLatLng().longitude()); + ASSERT_NEAR(10.0, transform->getZoom(), 1e-5); }; - transform.flyTo(cameraOptions2, flyOptions); - ASSERT_TRUE(transform.inTransition()); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(250)); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(500)); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(750)); - transform.updateTransitions(transform.getTransitionStart() + transform.getTransitionDuration()); - ASSERT_FALSE(transform.inTransition()); + transform->flyTo(cameraOptions2, flyOptions); + ASSERT_TRUE(transform->inTransition()); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(250)); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(500)); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(750)); + transform->updateTransitions(transform->getTransitionStart() + transform->getTransitionDuration()); + ASSERT_FALSE(transform->inTransition()); // Anchor and center points are mutually exclusive. CameraOptions camera; camera.center = LatLng{0, 0}; camera.anchor = ScreenCoordinate{0, 0}; // top-left - camera.zoom = transform.getState().getMaxZoom(); - transform.easeTo(camera, AnimationOptions(Seconds(1))); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(250)); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(500)); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(750)); - transform.updateTransitions(transform.getTransitionStart() + transform.getTransitionDuration()); - ASSERT_DOUBLE_EQ(transform.getLatLng().latitude(), 0); - ASSERT_DOUBLE_EQ(transform.getLatLng().longitude(), 0); + camera.zoom = transform->getState().getMaxZoom(); + transform->easeTo(camera, AnimationOptions(Seconds(1))); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(250)); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(500)); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(750)); + transform->updateTransitions(transform->getTransitionStart() + transform->getTransitionDuration()); + ASSERT_DOUBLE_EQ(transform->getLatLng().latitude(), 0); + ASSERT_DOUBLE_EQ(transform->getLatLng().longitude(), 0); } -TEST(Transform, ProjectionMode) { - Transform transform; +TEST_P(TransfromParametrized, ProjectionMode) { + std::shared_ptr transform = GetParam(); - transform.setProjectionMode(ProjectionMode().withAxonometric(true).withXSkew(1.0).withYSkew(0.0)); - auto options = transform.getProjectionMode(); + transform->setProjectionMode(ProjectionMode().withAxonometric(true).withXSkew(1.0).withYSkew(0.0)); + auto options = transform->getProjectionMode(); EXPECT_TRUE(*options.axonometric); EXPECT_EQ(*options.xSkew, 1.0); EXPECT_EQ(*options.ySkew, 0.0); } -TEST(Transform, IsPanning) { - Transform transform; +TEST_P(TransfromParametrized, IsPanning) { + std::shared_ptr transform = GetParam(); AnimationOptions easeOptions(Seconds(1)); easeOptions.transitionFrameFn = [&transform](double) { - ASSERT_TRUE(transform.getState().isPanning()); + ASSERT_TRUE(transform->getState().isPanning()); }; - transform.resize({1000, 1000}); - transform.easeTo(CameraOptions().withCenter(LatLng(0, 360.0)), easeOptions); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(250)); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(500)); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(750)); - transform.updateTransitions(transform.getTransitionStart() + transform.getTransitionDuration()); + transform->resize({1000, 1000}); + transform->easeTo(CameraOptions().withCenter(LatLng(0, 360.0)), easeOptions); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(250)); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(500)); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(750)); + transform->updateTransitions(transform->getTransitionStart() + transform->getTransitionDuration()); } -TEST(Transform, DefaultTransform) { - struct TransformObserver : public mbgl::MapObserver { - void onCameraWillChange(MapObserver::CameraChangeMode) final { cameraWillChangeCallback(); }; - - void onCameraDidChange(MapObserver::CameraChangeMode) final { cameraDidChangeCallback(); }; - - std::function cameraWillChangeCallback; - std::function cameraDidChangeCallback; - }; - - uint32_t cameraWillChangeCount = 0; - uint32_t cameraDidChangeCount = 0; - - TransformObserver observer; - observer.cameraWillChangeCallback = [&cameraWillChangeCount]() { - cameraWillChangeCount++; - }; - observer.cameraDidChangeCallback = [&cameraDidChangeCount]() { - cameraDidChangeCount++; - }; - - Transform transform(observer); +void testDefaultTransform(Transform& transform, + const uint32_t& cameraWillChangeCount, + const uint32_t& cameraDidChangeCount) { const TransformState& state = transform.getState(); ASSERT_FALSE(state.valid()); @@ -633,34 +619,64 @@ TEST(Transform, DefaultTransform) { ASSERT_NEAR(transform.getState().getScale(), 38.1529, 1e-4); } -TEST(Transform, LatLngBounds) { +TEST(Transfrom, DefaultTransform) { + struct TransformObserver : public mbgl::MapObserver { + void onCameraWillChange(MapObserver::CameraChangeMode) final { cameraWillChangeCallback(); }; + + void onCameraDidChange(MapObserver::CameraChangeMode) final { cameraDidChangeCallback(); }; + + std::function cameraWillChangeCallback; + std::function cameraDidChangeCallback; + }; + + uint32_t cameraWillChangeCount = 0; + uint32_t cameraDidChangeCount = 0; + + TransformObserver observer; + observer.cameraWillChangeCallback = [&cameraWillChangeCount]() { + cameraWillChangeCount++; + }; + observer.cameraDidChangeCallback = [&cameraDidChangeCount]() { + cameraDidChangeCount++; + }; + + Transform transform(observer); + testDefaultTransform(transform, cameraWillChangeCount, cameraDidChangeCount); + + cameraWillChangeCount = 0; + cameraDidChangeCount = 0; + TransformActive transformActive(observer); + testDefaultTransform(transformActive, cameraWillChangeCount, cameraDidChangeCount); +} + +TEST_P(TransfromParametrized, LatLngBounds) { const LatLng nullIsland{}; const LatLng sanFrancisco{37.7749, -122.4194}; - Transform transform; - transform.resize({1000, 1000}); + std::shared_ptr transform = GetParam(); + transform->resize({1000, 1000}); - transform.jumpTo(CameraOptions().withCenter(LatLng()).withZoom(transform.getState().getMaxZoom())); + transform->jumpTo(CameraOptions().withCenter(LatLng()).withZoom(transform->getState().getMaxZoom())); // Default bounds. - ASSERT_EQ(transform.getState().getLatLngBounds(), LatLngBounds()); - ASSERT_EQ(transform.getLatLng(), nullIsland); + ASSERT_EQ(transform->getState().getLatLngBounds(), LatLngBounds()); + ASSERT_EQ(transform->getLatLng(), nullIsland); // Invalid bounds. try { - transform.setLatLngBounds(LatLngBounds::empty()); + transform->setLatLngBounds(LatLngBounds::empty()); ASSERT_TRUE(false) << "Should throw"; } catch (...) { - ASSERT_EQ(transform.getState().getLatLngBounds(), LatLngBounds()); + ASSERT_EQ(transform->getState().getLatLngBounds(), LatLngBounds()); } - transform.jumpTo(CameraOptions().withCenter(sanFrancisco)); - ASSERT_NEAR(transform.getLatLng().latitude(), sanFrancisco.latitude(), 1e-8); - ASSERT_NEAR(transform.getLatLng().longitude(), sanFrancisco.longitude(), 1e-8); + transform->jumpTo(CameraOptions().withCenter(sanFrancisco)); + ASSERT_NEAR(transform->getLatLng().latitude(), sanFrancisco.latitude(), 1e-8); + ASSERT_NEAR(transform->getLatLng().longitude(), sanFrancisco.longitude(), 1e-8); // Single location. - transform.setLatLngBounds(LatLngBounds::singleton(sanFrancisco)); - ASSERT_EQ(transform.getLatLng(), sanFrancisco); + transform->setLatLngBounds(LatLngBounds::singleton(sanFrancisco)); + ASSERT_EQ(transform->getLatLng(), sanFrancisco); // -1 | 0 | +1 // ┌───┬───┰───┬───┰───┬───┐ @@ -668,19 +684,19 @@ TEST(Transform, LatLngBounds) { // ├───┼───╂───┼───╂───┼───┤ // │ │ ┃▓▓▓│▓▓▓┃ │ │ // └───┴───┸───┴───┸───┴───┘ - transform.setLatLngBounds(LatLngBounds::hull({-90.0, -180.0}, {0.0, 180.0})); - transform.jumpTo(CameraOptions().withCenter(sanFrancisco)); - ASSERT_EQ(transform.getLatLng().latitude(), 0.0); - ASSERT_EQ(transform.getLatLng().longitude(), sanFrancisco.longitude()); + transform->setLatLngBounds(LatLngBounds::hull({-90.0, -180.0}, {0.0, 180.0})); + transform->jumpTo(CameraOptions().withCenter(sanFrancisco)); + ASSERT_EQ(transform->getLatLng().latitude(), 0.0); + ASSERT_EQ(transform->getLatLng().longitude(), sanFrancisco.longitude()); // Try crossing the antimeridian from the left. - transform.jumpTo(CameraOptions().withCenter(LatLng{0.0, -200.0})); - ASSERT_DOUBLE_EQ(transform.getLatLng().longitude(), -180.0); + transform->jumpTo(CameraOptions().withCenter(LatLng{0.0, -200.0})); + ASSERT_DOUBLE_EQ(transform->getLatLng().longitude(), -180.0); // Try crossing the antimeridian from the right. - transform.jumpTo(CameraOptions().withCenter(LatLng{0.0, 200.0})); - ASSERT_DOUBLE_EQ(transform.getLatLng(LatLng::Unwrapped).longitude(), 180.0); - ASSERT_DOUBLE_EQ(transform.getLatLng().longitude(), -180.0); + transform->jumpTo(CameraOptions().withCenter(LatLng{0.0, 200.0})); + ASSERT_DOUBLE_EQ(transform->getLatLng(LatLng::Unwrapped).longitude(), 180.0); + ASSERT_DOUBLE_EQ(transform->getLatLng().longitude(), -180.0); // -1 | 0 | +1 // ┌───┬───┰───┬───┰───┬───┐ @@ -688,10 +704,10 @@ TEST(Transform, LatLngBounds) { // ├───┼───╂───┼───╂───┼───┤ // │ │ ┃ │▓▓▓┃ │ │ // └───┴───┸───┴───┸───┴───┘ - transform.setLatLngBounds(LatLngBounds::hull({-90.0, 0.0}, {90.0, 180.0})); - transform.jumpTo(CameraOptions().withCenter(sanFrancisco)); - ASSERT_NEAR(transform.getLatLng().latitude(), sanFrancisco.latitude(), 1e-8); - ASSERT_EQ(transform.getLatLng().longitude(), 0.0); + transform->setLatLngBounds(LatLngBounds::hull({-90.0, 0.0}, {90.0, 180.0})); + transform->jumpTo(CameraOptions().withCenter(sanFrancisco)); + ASSERT_NEAR(transform->getLatLng().latitude(), sanFrancisco.latitude(), 1e-8); + ASSERT_EQ(transform->getLatLng().longitude(), 0.0); // -1 | 0 | +1 // ┌───┬───┰───┬───┰───┬───┐ @@ -699,10 +715,10 @@ TEST(Transform, LatLngBounds) { // ├───┼───╂───┼───╂───┼───┤ // │ │ ┃ │▓▓▓┃ │ │ // └───┴───┸───┴───┸───┴───┘ - transform.setLatLngBounds(LatLngBounds::hull({-90.0, 0.0}, {0.0, 180.0})); - transform.jumpTo(CameraOptions().withCenter(sanFrancisco)); - ASSERT_EQ(transform.getLatLng().latitude(), 0.0); - ASSERT_EQ(transform.getLatLng().longitude(), 0.0); + transform->setLatLngBounds(LatLngBounds::hull({-90.0, 0.0}, {0.0, 180.0})); + transform->jumpTo(CameraOptions().withCenter(sanFrancisco)); + ASSERT_EQ(transform->getLatLng().latitude(), 0.0); + ASSERT_EQ(transform->getLatLng().longitude(), 0.0); // -1 | 0 | +1 // ┌───┬───┰───┬───┰───┬───┐ @@ -711,69 +727,69 @@ TEST(Transform, LatLngBounds) { // │ │ ┃ │ ┃ │ │ // └───┴───┸───┴───┸───┴───┘ LatLng inside{45.0, 150.0}; - transform.setLatLngBounds(LatLngBounds::hull({0.0, 120.0}, {90.0, 240.0})); - transform.jumpTo(CameraOptions().withCenter(inside)); - ASSERT_EQ(transform.getLatLng().latitude(), inside.latitude()); - ASSERT_EQ(transform.getLatLng().longitude(), inside.longitude()); + transform->setLatLngBounds(LatLngBounds::hull({0.0, 120.0}, {90.0, 240.0})); + transform->jumpTo(CameraOptions().withCenter(inside)); + ASSERT_EQ(transform->getLatLng().latitude(), inside.latitude()); + ASSERT_EQ(transform->getLatLng().longitude(), inside.longitude()); - transform.jumpTo(CameraOptions().withCenter(LatLng{0.0, 140.0})); - ASSERT_DOUBLE_EQ(transform.getLatLng().longitude(), 140.0); + transform->jumpTo(CameraOptions().withCenter(LatLng{0.0, 140.0})); + ASSERT_DOUBLE_EQ(transform->getLatLng().longitude(), 140.0); - transform.jumpTo(CameraOptions().withCenter(LatLng{0.0, 160.0})); - ASSERT_DOUBLE_EQ(transform.getLatLng().longitude(), 160.0); + transform->jumpTo(CameraOptions().withCenter(LatLng{0.0, 160.0})); + ASSERT_DOUBLE_EQ(transform->getLatLng().longitude(), 160.0); // Constrain latitude only. - transform.jumpTo(CameraOptions().withCenter(LatLng{-45.0, inside.longitude()})); - ASSERT_EQ(transform.getLatLng().latitude(), 0.0); - ASSERT_EQ(transform.getLatLng().longitude(), inside.longitude()); + transform->jumpTo(CameraOptions().withCenter(LatLng{-45.0, inside.longitude()})); + ASSERT_EQ(transform->getLatLng().latitude(), 0.0); + ASSERT_EQ(transform->getLatLng().longitude(), inside.longitude()); // Crossing the antimeridian, within bounds. - transform.jumpTo(CameraOptions().withCenter(LatLng{inside.latitude(), 181.0})); - ASSERT_EQ(transform.getLatLng().longitude(), -179.0); + transform->jumpTo(CameraOptions().withCenter(LatLng{inside.latitude(), 181.0})); + ASSERT_EQ(transform->getLatLng().longitude(), -179.0); // Crossing the antimeridian, outside bounds. - transform.jumpTo(CameraOptions().withCenter(inside)); - transform.jumpTo(CameraOptions().withCenter(LatLng{inside.latitude(), 250.0})); - ASSERT_DOUBLE_EQ(transform.getLatLng().longitude(), -120.0); + transform->jumpTo(CameraOptions().withCenter(inside)); + transform->jumpTo(CameraOptions().withCenter(LatLng{inside.latitude(), 250.0})); + ASSERT_DOUBLE_EQ(transform->getLatLng().longitude(), -120.0); // Constrain to the left edge. - transform.jumpTo(CameraOptions().withCenter(LatLng{inside.latitude(), 119.0})); - ASSERT_DOUBLE_EQ(transform.getLatLng().longitude(), 120.0); + transform->jumpTo(CameraOptions().withCenter(LatLng{inside.latitude(), 119.0})); + ASSERT_DOUBLE_EQ(transform->getLatLng().longitude(), 120.0); // Simulate swipe to the left. mbgl::AnimationOptions easeOptions(mbgl::Seconds(1)); easeOptions.transitionFrameFn = [&](double /* t */) { - ASSERT_NEAR(transform.getLatLng().longitude(), 120.0, 1e-4); + ASSERT_NEAR(transform->getLatLng().longitude(), 120.0, 1e-4); }; easeOptions.transitionFinishFn = [&]() { - ASSERT_NEAR(transform.getLatLng().longitude(), 120.0, 1e-4); + ASSERT_NEAR(transform->getLatLng().longitude(), 120.0, 1e-4); }; - transform.moveBy(ScreenCoordinate{-500, -500}, easeOptions); + transform->moveBy(ScreenCoordinate{-500, -500}, easeOptions); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(0)); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(250)); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(500)); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(750)); - transform.updateTransitions(transform.getTransitionStart() + transform.getTransitionDuration()); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(0)); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(250)); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(500)); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(750)); + transform->updateTransitions(transform->getTransitionStart() + transform->getTransitionDuration()); // Constrain to the right edge. - transform.jumpTo(CameraOptions().withCenter(LatLng{inside.latitude(), 241.0})); - ASSERT_DOUBLE_EQ(transform.getLatLng().longitude(), -120.0); + transform->jumpTo(CameraOptions().withCenter(LatLng{inside.latitude(), 241.0})); + ASSERT_DOUBLE_EQ(transform->getLatLng().longitude(), -120.0); // Simulate swipe to the right. easeOptions.transitionFrameFn = [&](double /* t */) { - ASSERT_NEAR(transform.getLatLng().longitude(), -120.0, 1e-4); + ASSERT_NEAR(transform->getLatLng().longitude(), -120.0, 1e-4); }; easeOptions.transitionFinishFn = [&]() { - ASSERT_NEAR(transform.getLatLng().longitude(), -120.0, 1e-4); + ASSERT_NEAR(transform->getLatLng().longitude(), -120.0, 1e-4); }; - transform.moveBy(ScreenCoordinate{500, 500}, easeOptions); + transform->moveBy(ScreenCoordinate{500, 500}, easeOptions); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(0)); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(250)); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(500)); - transform.updateTransitions(transform.getTransitionStart() + Milliseconds(750)); - transform.updateTransitions(transform.getTransitionStart() + transform.getTransitionDuration()); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(0)); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(250)); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(500)); + transform->updateTransitions(transform->getTransitionStart() + Milliseconds(750)); + transform->updateTransitions(transform->getTransitionStart() + transform->getTransitionDuration()); // -1 | 0 | +1 // ┌───┬───┰───┬───┰───┬───┐ @@ -782,171 +798,171 @@ TEST(Transform, LatLngBounds) { // │ │ ▓┃▓ │ ┃ │ │ // └───┴───┸───┴───┸───┴───┘ inside = LatLng{-45.0, -150.0}; - transform.setLatLngBounds(LatLngBounds::hull({-90.0, -240.0}, {0.0, -120.0})); - transform.jumpTo(CameraOptions().withCenter(inside)); - ASSERT_DOUBLE_EQ(transform.getLatLng().latitude(), inside.latitude()); - ASSERT_EQ(transform.getLatLng().longitude(), inside.longitude()); + transform->setLatLngBounds(LatLngBounds::hull({-90.0, -240.0}, {0.0, -120.0})); + transform->jumpTo(CameraOptions().withCenter(inside)); + ASSERT_DOUBLE_EQ(transform->getLatLng().latitude(), inside.latitude()); + ASSERT_EQ(transform->getLatLng().longitude(), inside.longitude()); - transform.jumpTo(CameraOptions().withCenter(LatLng{0.0, -140.0})); - ASSERT_DOUBLE_EQ(transform.getLatLng().longitude(), -140.0); + transform->jumpTo(CameraOptions().withCenter(LatLng{0.0, -140.0})); + ASSERT_DOUBLE_EQ(transform->getLatLng().longitude(), -140.0); - transform.jumpTo(CameraOptions().withCenter(LatLng{0.0, -160.0})); - ASSERT_DOUBLE_EQ(transform.getLatLng().longitude(), -160.0); + transform->jumpTo(CameraOptions().withCenter(LatLng{0.0, -160.0})); + ASSERT_DOUBLE_EQ(transform->getLatLng().longitude(), -160.0); // Constrain latitude only. - transform.jumpTo(CameraOptions().withCenter(LatLng{45.0, inside.longitude()})); - ASSERT_EQ(transform.getLatLng().latitude(), 0.0); - ASSERT_EQ(transform.getLatLng().longitude(), inside.longitude()); + transform->jumpTo(CameraOptions().withCenter(LatLng{45.0, inside.longitude()})); + ASSERT_EQ(transform->getLatLng().latitude(), 0.0); + ASSERT_EQ(transform->getLatLng().longitude(), inside.longitude()); // Crossing the antimeridian, within bounds. - transform.jumpTo(CameraOptions().withCenter(LatLng{inside.latitude(), -181.0})); - ASSERT_DOUBLE_EQ(transform.getLatLng().latitude(), inside.latitude()); - ASSERT_EQ(transform.getLatLng().longitude(), 179.0); + transform->jumpTo(CameraOptions().withCenter(LatLng{inside.latitude(), -181.0})); + ASSERT_DOUBLE_EQ(transform->getLatLng().latitude(), inside.latitude()); + ASSERT_EQ(transform->getLatLng().longitude(), 179.0); // Crossing the antimeridian, outside bounds. - transform.jumpTo(CameraOptions().withCenter(inside)); - transform.jumpTo(CameraOptions().withCenter(LatLng{inside.latitude(), -250.0})); - ASSERT_DOUBLE_EQ(transform.getLatLng().longitude(), 120.0); + transform->jumpTo(CameraOptions().withCenter(inside)); + transform->jumpTo(CameraOptions().withCenter(LatLng{inside.latitude(), -250.0})); + ASSERT_DOUBLE_EQ(transform->getLatLng().longitude(), 120.0); // Constrain to the left edge. - transform.jumpTo(CameraOptions().withCenter(LatLng{inside.latitude(), -119.0})); - ASSERT_DOUBLE_EQ(transform.getLatLng().longitude(), -120.0); + transform->jumpTo(CameraOptions().withCenter(LatLng{inside.latitude(), -119.0})); + ASSERT_DOUBLE_EQ(transform->getLatLng().longitude(), -120.0); - transform.moveBy(ScreenCoordinate{-500, 0}); - ASSERT_DOUBLE_EQ(transform.getLatLng().longitude(), -120.0); + transform->moveBy(ScreenCoordinate{-500, 0}); + ASSERT_DOUBLE_EQ(transform->getLatLng().longitude(), -120.0); // Constrain to the right edge. - transform.jumpTo(CameraOptions().withCenter(LatLng{inside.latitude(), -241.0})); - ASSERT_DOUBLE_EQ(transform.getLatLng().longitude(), 120.0); + transform->jumpTo(CameraOptions().withCenter(LatLng{inside.latitude(), -241.0})); + ASSERT_DOUBLE_EQ(transform->getLatLng().longitude(), 120.0); - transform.moveBy(ScreenCoordinate{500, 0}); - ASSERT_DOUBLE_EQ(transform.getLatLng().longitude(), 120.0); + transform->moveBy(ScreenCoordinate{500, 0}); + ASSERT_DOUBLE_EQ(transform->getLatLng().longitude(), 120.0); } -TEST(Transform, ConstrainScreenToBounds) { - Transform transform; +TEST_P(TransfromParametrized, ConstrainScreenToBounds) { + std::shared_ptr transform = GetParam(); - transform.resize({500, 500}); - transform.setLatLngBounds(LatLngBounds::hull({40.0, -10.0}, {70.0, 40.0})); - transform.setConstrainMode(ConstrainMode::Screen); + transform->resize({500, 500}); + transform->setLatLngBounds(LatLngBounds::hull({40.0, -10.0}, {70.0, 40.0})); + transform->setConstrainMode(ConstrainMode::Screen); // Request impossible zoom - transform.easeTo(CameraOptions().withCenter(LatLng{56, 11}).withZoom(1)); - ASSERT_NEAR(transform.getZoom(), 2.81378, 1e-4); + transform->easeTo(CameraOptions().withCenter(LatLng{56, 11}).withZoom(1)); + ASSERT_NEAR(transform->getZoom(), 2.81378, 1e-4); // Request impossible center left - transform.easeTo(CameraOptions().withCenter(LatLng{56, -65}).withZoom(4)); - ASSERT_NEAR(transform.getLatLng().longitude(), 0.98632, 1e-4); - ASSERT_NEAR(transform.getLatLng().latitude(), 56.0, 1e-4); + transform->easeTo(CameraOptions().withCenter(LatLng{56, -65}).withZoom(4)); + ASSERT_NEAR(transform->getLatLng().longitude(), 0.98632, 1e-4); + ASSERT_NEAR(transform->getLatLng().latitude(), 56.0, 1e-4); // Request impossible center top - transform.easeTo(CameraOptions().withCenter(LatLng{80, 11}).withZoom(4)); - ASSERT_NEAR(transform.getLatLng().longitude(), 11.0, 1e-4); - ASSERT_NEAR(transform.getLatLng().latitude(), 65.88603, 1e-4); + transform->easeTo(CameraOptions().withCenter(LatLng{80, 11}).withZoom(4)); + ASSERT_NEAR(transform->getLatLng().longitude(), 11.0, 1e-4); + ASSERT_NEAR(transform->getLatLng().latitude(), 65.88603, 1e-4); // Request impossible center right - transform.easeTo(CameraOptions().withCenter(LatLng{56, 50}).withZoom(4)); - ASSERT_NEAR(transform.getLatLng().longitude(), 29.01367, 1e-4); - ASSERT_NEAR(transform.getLatLng().latitude(), 56.0, 1e-4); + transform->easeTo(CameraOptions().withCenter(LatLng{56, 50}).withZoom(4)); + ASSERT_NEAR(transform->getLatLng().longitude(), 29.01367, 1e-4); + ASSERT_NEAR(transform->getLatLng().latitude(), 56.0, 1e-4); // Request impossible center bottom - transform.easeTo(CameraOptions().withCenter(LatLng{30, 11}).withZoom(4)); - ASSERT_NEAR(transform.getLatLng().longitude(), 11.0, 1e-4); - ASSERT_NEAR(transform.getLatLng().latitude(), 47.89217, 1e-4); + transform->easeTo(CameraOptions().withCenter(LatLng{30, 11}).withZoom(4)); + ASSERT_NEAR(transform->getLatLng().longitude(), 11.0, 1e-4); + ASSERT_NEAR(transform->getLatLng().latitude(), 47.89217, 1e-4); // Request impossible center with anchor - transform.easeTo(CameraOptions().withAnchor(ScreenCoordinate{250, 250}).withCenter(LatLng{56, -65}).withZoom(4)); - ASSERT_NEAR(transform.getLatLng().longitude(), 0.98632, 1e-4); - ASSERT_NEAR(transform.getLatLng().latitude(), 56.0, 1e-4); + transform->easeTo(CameraOptions().withAnchor(ScreenCoordinate{250, 250}).withCenter(LatLng{56, -65}).withZoom(4)); + ASSERT_NEAR(transform->getLatLng().longitude(), 0.98632, 1e-4); + ASSERT_NEAR(transform->getLatLng().latitude(), 56.0, 1e-4); // Request impossible center (anchor) - transform.easeTo(CameraOptions().withAnchor(ScreenCoordinate{250, 250}).withZoom(4)); - ASSERT_NEAR(transform.getLatLng().longitude(), 0.98632, 1e-4); - ASSERT_NEAR(transform.getLatLng().latitude(), 56.0, 1e-4); + transform->easeTo(CameraOptions().withAnchor(ScreenCoordinate{250, 250}).withZoom(4)); + ASSERT_NEAR(transform->getLatLng().longitude(), 0.98632, 1e-4); + ASSERT_NEAR(transform->getLatLng().latitude(), 56.0, 1e-4); // Fly to impossible center - transform.flyTo(CameraOptions().withCenter(LatLng{56, -65}).withZoom(4)); - ASSERT_NEAR(transform.getZoom(), 4.0, 1e-4); - ASSERT_NEAR(transform.getLatLng().longitude(), 0.98632, 1e-4); - ASSERT_NEAR(transform.getLatLng().latitude(), 56.0, 1e-4); + transform->flyTo(CameraOptions().withCenter(LatLng{56, -65}).withZoom(4)); + ASSERT_NEAR(transform->getZoom(), 4.0, 1e-4); + ASSERT_NEAR(transform->getLatLng().longitude(), 0.98632, 1e-4); + ASSERT_NEAR(transform->getLatLng().latitude(), 56.0, 1e-4); // Fly to impossible center and zoom - transform.flyTo(CameraOptions().withCenter(LatLng{56, -65}).withZoom(2)); - ASSERT_NEAR(transform.getZoom(), 4.0, 1e-4); - ASSERT_NEAR(transform.getLatLng().longitude(), 0.98632, 1e-4); - ASSERT_NEAR(transform.getLatLng().latitude(), 56.0, 1e-4); + transform->flyTo(CameraOptions().withCenter(LatLng{56, -65}).withZoom(2)); + ASSERT_NEAR(transform->getZoom(), 4.0, 1e-4); + ASSERT_NEAR(transform->getLatLng().longitude(), 0.98632, 1e-4); + ASSERT_NEAR(transform->getLatLng().latitude(), 56.0, 1e-4); } -TEST(Transform, InvalidPitch) { - Transform transform; - transform.resize({1, 1}); +TEST_P(TransfromParametrized, InvalidPitch) { + std::shared_ptr transform = GetParam(); + transform->resize({1, 1}); - ASSERT_DOUBLE_EQ(0, transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(0, transform.getLatLng().longitude()); - ASSERT_DOUBLE_EQ(0, transform.getZoom()); - ASSERT_DOUBLE_EQ(0, transform.getPitch()); + ASSERT_DOUBLE_EQ(0, transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(0, transform->getLatLng().longitude()); + ASSERT_DOUBLE_EQ(0, transform->getZoom()); + ASSERT_DOUBLE_EQ(0, transform->getPitch()); - transform.jumpTo(CameraOptions().withZoom(1.0).withPitch(45)); - ASSERT_DOUBLE_EQ(1, transform.getZoom()); - ASSERT_DOUBLE_EQ(util::deg2rad(45), transform.getPitch()); + transform->jumpTo(CameraOptions().withZoom(1.0).withPitch(45)); + ASSERT_DOUBLE_EQ(1, transform->getZoom()); + ASSERT_DOUBLE_EQ(util::deg2rad(45), transform->getPitch()); const double invalid = NAN; - transform.jumpTo(CameraOptions().withPitch(invalid)); - ASSERT_DOUBLE_EQ(util::deg2rad(45), transform.getPitch()); + transform->jumpTo(CameraOptions().withPitch(invalid)); + ASSERT_DOUBLE_EQ(util::deg2rad(45), transform->getPitch()); - transform.jumpTo(CameraOptions().withPitch(60)); - ASSERT_DOUBLE_EQ(util::deg2rad(60), transform.getPitch()); + transform->jumpTo(CameraOptions().withPitch(60)); + ASSERT_DOUBLE_EQ(util::deg2rad(60), transform->getPitch()); } -TEST(Transform, MinMaxPitch) { - Transform transform; - transform.resize({1, 1}); - - ASSERT_DOUBLE_EQ(0, transform.getLatLng().latitude()); - ASSERT_DOUBLE_EQ(0, transform.getLatLng().longitude()); - ASSERT_DOUBLE_EQ(0, transform.getZoom()); - ASSERT_DOUBLE_EQ(0, transform.getPitch()); - - transform.jumpTo(CameraOptions().withZoom(1.0).withPitch(60)); - ASSERT_DOUBLE_EQ(1, transform.getZoom()); - ASSERT_DOUBLE_EQ(transform.getState().getMaxPitch(), transform.getPitch()); - ASSERT_DOUBLE_EQ(util::deg2rad(60), transform.getPitch()); - - transform.setMaxPitch(70); - transform.jumpTo(CameraOptions().withPitch(70)); - ASSERT_DOUBLE_EQ(transform.getState().getMaxPitch(), transform.getPitch()); - ASSERT_DOUBLE_EQ(util::deg2rad(60), transform.getPitch()); - - transform.setMaxPitch(45); - transform.jumpTo(CameraOptions().withPitch(60)); - ASSERT_DOUBLE_EQ(transform.getState().getMaxPitch(), transform.getPitch()); - ASSERT_DOUBLE_EQ(util::deg2rad(45), transform.getPitch()); - - transform.jumpTo(CameraOptions().withPitch(0)); - ASSERT_DOUBLE_EQ(transform.getState().getMinPitch(), transform.getPitch()); - ASSERT_DOUBLE_EQ(0, transform.getPitch()); - - transform.setMinPitch(-10); - transform.jumpTo(CameraOptions().withPitch(-10)); - ASSERT_DOUBLE_EQ(transform.getState().getMinPitch(), transform.getPitch()); - ASSERT_DOUBLE_EQ(0, transform.getPitch()); - - transform.setMinPitch(15); - transform.jumpTo(CameraOptions().withPitch(0)); - ASSERT_DOUBLE_EQ(transform.getState().getMinPitch(), transform.getPitch()); - ASSERT_DOUBLE_EQ(util::deg2rad(15), transform.getPitch()); - - transform.setMinPitch(45); - ASSERT_DOUBLE_EQ(util::deg2rad(45), transform.getState().getMinPitch()); - transform.setMaxPitch(45); - ASSERT_DOUBLE_EQ(util::deg2rad(45), transform.getState().getMaxPitch()); - - transform.setMaxPitch(10); - ASSERT_DOUBLE_EQ(util::deg2rad(45), transform.getState().getMaxPitch()); - - transform.setMinPitch(60); - ASSERT_DOUBLE_EQ(util::deg2rad(45), transform.getState().getMinPitch()); +TEST_P(TransfromParametrized, MinMaxPitch) { + std::shared_ptr transform = GetParam(); + transform->resize({1, 1}); + + ASSERT_DOUBLE_EQ(0, transform->getLatLng().latitude()); + ASSERT_DOUBLE_EQ(0, transform->getLatLng().longitude()); + ASSERT_DOUBLE_EQ(0, transform->getZoom()); + ASSERT_DOUBLE_EQ(0, transform->getPitch()); + + transform->jumpTo(CameraOptions().withZoom(1.0).withPitch(60)); + ASSERT_DOUBLE_EQ(1, transform->getZoom()); + ASSERT_DOUBLE_EQ(transform->getState().getMaxPitch(), transform->getPitch()); + ASSERT_DOUBLE_EQ(util::deg2rad(60), transform->getPitch()); + + transform->setMaxPitch(70); + transform->jumpTo(CameraOptions().withPitch(70)); + ASSERT_DOUBLE_EQ(transform->getState().getMaxPitch(), transform->getPitch()); + ASSERT_DOUBLE_EQ(util::deg2rad(60), transform->getPitch()); + + transform->setMaxPitch(45); + transform->jumpTo(CameraOptions().withPitch(60)); + ASSERT_DOUBLE_EQ(transform->getState().getMaxPitch(), transform->getPitch()); + ASSERT_DOUBLE_EQ(util::deg2rad(45), transform->getPitch()); + + transform->jumpTo(CameraOptions().withPitch(0)); + ASSERT_DOUBLE_EQ(transform->getState().getMinPitch(), transform->getPitch()); + ASSERT_DOUBLE_EQ(0, transform->getPitch()); + + transform->setMinPitch(-10); + transform->jumpTo(CameraOptions().withPitch(-10)); + ASSERT_DOUBLE_EQ(transform->getState().getMinPitch(), transform->getPitch()); + ASSERT_DOUBLE_EQ(0, transform->getPitch()); + + transform->setMinPitch(15); + transform->jumpTo(CameraOptions().withPitch(0)); + ASSERT_DOUBLE_EQ(transform->getState().getMinPitch(), transform->getPitch()); + ASSERT_DOUBLE_EQ(util::deg2rad(15), transform->getPitch()); + + transform->setMinPitch(45); + ASSERT_DOUBLE_EQ(util::deg2rad(45), transform->getState().getMinPitch()); + transform->setMaxPitch(45); + ASSERT_DOUBLE_EQ(util::deg2rad(45), transform->getState().getMaxPitch()); + + transform->setMaxPitch(10); + ASSERT_DOUBLE_EQ(util::deg2rad(45), transform->getState().getMaxPitch()); + + transform->setMinPitch(60); + ASSERT_DOUBLE_EQ(util::deg2rad(45), transform->getState().getMinPitch()); } static const double abs_double_error = 1e-5; @@ -956,16 +972,16 @@ MATCHER_P(Vec3NearEquals1E5, vec, "") { std::fabs(vec[2] - arg[2]) <= abs_double_error; } -TEST(Transform, FreeCameraOptionsInvalidSize) { - Transform transform; +TEST_P(TransfromParametrized, FreeCameraOptionsInvalidSize) { + std::shared_ptr transform = GetParam(); FreeCameraOptions options; options.orientation = vec4{{1.0, 1.0, 1.0, 1.0}}; options.position = vec3{{0.1, 0.2, 0.3}}; - transform.setFreeCameraOptions(options); + transform->setFreeCameraOptions(options); - const auto updatedOrientation = transform.getFreeCameraOptions().orientation.value(); - const auto updatedPosition = transform.getFreeCameraOptions().position.value(); + const auto updatedOrientation = transform->getFreeCameraOptions().orientation.value(); + const auto updatedPosition = transform->getFreeCameraOptions().position.value(); EXPECT_DOUBLE_EQ(0.0, updatedOrientation[0]); EXPECT_DOUBLE_EQ(0.0, updatedOrientation[1]); @@ -975,98 +991,98 @@ TEST(Transform, FreeCameraOptionsInvalidSize) { EXPECT_THAT(updatedPosition, Vec3NearEquals1E5(vec3{{0.0, 0.0, 0.0}})); } -TEST(Transform, FreeCameraOptionsNanInput) { - Transform transform; - transform.resize({100, 100}); +TEST_P(TransfromParametrized, FreeCameraOptionsNanInput) { + std::shared_ptr transform = GetParam(); + transform->resize({100, 100}); FreeCameraOptions options; options.position = vec3{{0.5, 0.5, 0.25}}; - transform.setFreeCameraOptions(options); + transform->setFreeCameraOptions(options); options.position = vec3{{0.0, 0.0, NAN}}; - transform.setFreeCameraOptions(options); - EXPECT_EQ((vec3{{0.5, 0.5, 0.25}}), transform.getFreeCameraOptions().position.value()); + transform->setFreeCameraOptions(options); + EXPECT_EQ((vec3{{0.5, 0.5, 0.25}}), transform->getFreeCameraOptions().position.value()); // Only the invalid parameter should be discarded options.position = vec3{{0.3, 0.1, 0.2}}; options.orientation = vec4{{NAN, 0.0, NAN, 0.0}}; - transform.setFreeCameraOptions(options); - EXPECT_THAT(transform.getFreeCameraOptions().position.value(), Vec3NearEquals1E5(vec3{{0.3, 0.1, 0.2}})); - EXPECT_EQ(Quaternion::identity.m, transform.getFreeCameraOptions().orientation.value()); + transform->setFreeCameraOptions(options); + EXPECT_THAT(transform->getFreeCameraOptions().position.value(), Vec3NearEquals1E5(vec3{{0.3, 0.1, 0.2}})); + EXPECT_EQ(Quaternion::identity.m, transform->getFreeCameraOptions().orientation.value()); } -TEST(Transform, FreeCameraOptionsInvalidZ) { - Transform transform; - transform.resize({100, 100}); +TEST_P(TransfromParametrized, FreeCameraOptionsInvalidZ) { + std::shared_ptr transform = GetParam(); + transform->resize({100, 100}); FreeCameraOptions options; // Invalid z-value (<= 0.0 || > 1) should be clamped to respect both min&max zoom values options.position = vec3{{0.1, 0.1, 0.0}}; - transform.setFreeCameraOptions(options); - EXPECT_DOUBLE_EQ(transform.getState().getMaxZoom(), transform.getState().getZoom()); - EXPECT_GT(transform.getFreeCameraOptions().position.value()[2], 0.0); + transform->setFreeCameraOptions(options); + EXPECT_DOUBLE_EQ(transform->getState().getMaxZoom(), transform->getState().getZoom()); + EXPECT_GT(transform->getFreeCameraOptions().position.value()[2], 0.0); options.position = vec3{{0.5, 0.2, 123.456}}; - transform.setFreeCameraOptions(options); - EXPECT_DOUBLE_EQ(transform.getState().getMinZoom(), transform.getState().getZoom()); - EXPECT_LE(transform.getFreeCameraOptions().position.value()[2], 1.0); + transform->setFreeCameraOptions(options); + EXPECT_DOUBLE_EQ(transform->getState().getMinZoom(), transform->getState().getZoom()); + EXPECT_LE(transform->getFreeCameraOptions().position.value()[2], 1.0); } -TEST(Transform, FreeCameraOptionsInvalidOrientation) { +TEST_P(TransfromParametrized, FreeCameraOptionsInvalidOrientation) { // Invalid orientations that cannot be clamped into a valid range - Transform transform; - transform.resize({100, 100}); + std::shared_ptr transform = GetParam(); + transform->resize({100, 100}); FreeCameraOptions options; options.orientation = vec4{{0.0, 0.0, 0.0, 0.0}}; - transform.setFreeCameraOptions(options); - EXPECT_EQ(Quaternion::identity.m, transform.getFreeCameraOptions().orientation); + transform->setFreeCameraOptions(options); + EXPECT_EQ(Quaternion::identity.m, transform->getFreeCameraOptions().orientation); // Gimbal lock. Both forward and up vectors are on xy-plane options.orientation = Quaternion::fromAxisAngle(vec3{{0.0, 1.0, 0.0}}, pi / 2).m; - transform.setFreeCameraOptions(options); - EXPECT_EQ(Quaternion::identity.m, transform.getFreeCameraOptions().orientation); + transform->setFreeCameraOptions(options); + EXPECT_EQ(Quaternion::identity.m, transform->getFreeCameraOptions().orientation); // Camera is upside down options.orientation = Quaternion::fromAxisAngle(vec3{{1.0, 0.0, 0.0}}, pi / 2 + pi / 4).m; - transform.setFreeCameraOptions(options); - EXPECT_EQ(Quaternion::identity.m, transform.getFreeCameraOptions().orientation); + transform->setFreeCameraOptions(options); + EXPECT_EQ(Quaternion::identity.m, transform->getFreeCameraOptions().orientation); } -TEST(Transform, FreeCameraOptionsSetOrientation) { - Transform transform; - transform.resize({100, 100}); +TEST_P(TransfromParametrized, FreeCameraOptionsSetOrientation) { + std::shared_ptr transform = GetParam(); + transform->resize({100, 100}); FreeCameraOptions options; options.orientation = Quaternion::identity.m; - transform.setFreeCameraOptions(options); - EXPECT_DOUBLE_EQ(0.0, transform.getState().getBearing()); - EXPECT_DOUBLE_EQ(0.0, transform.getState().getPitch()); - EXPECT_DOUBLE_EQ(0.0, transform.getState().getX()); - EXPECT_DOUBLE_EQ(0.0, transform.getState().getY()); + transform->setFreeCameraOptions(options); + EXPECT_DOUBLE_EQ(0.0, transform->getState().getBearing()); + EXPECT_DOUBLE_EQ(0.0, transform->getState().getPitch()); + EXPECT_DOUBLE_EQ(0.0, transform->getState().getX()); + EXPECT_DOUBLE_EQ(0.0, transform->getState().getY()); options.orientation = Quaternion::fromAxisAngle(vec3{{1.0, 0.0, 0.0}}, util::deg2rad(-60.0)).m; - transform.setFreeCameraOptions(options); - EXPECT_DOUBLE_EQ(0.0, transform.getState().getBearing()); - EXPECT_DOUBLE_EQ(util::deg2rad(60.0), transform.getState().getPitch()); - EXPECT_DOUBLE_EQ(0.0, transform.getState().getX()); - EXPECT_DOUBLE_EQ(206.0, transform.getState().getY()); + transform->setFreeCameraOptions(options); + EXPECT_DOUBLE_EQ(0.0, transform->getState().getBearing()); + EXPECT_DOUBLE_EQ(util::deg2rad(60.0), transform->getState().getPitch()); + EXPECT_DOUBLE_EQ(0.0, transform->getState().getX()); + EXPECT_DOUBLE_EQ(206.0, transform->getState().getY()); options.orientation = Quaternion::fromAxisAngle(vec3{{0.0, 0.0, 1.0}}, util::deg2rad(56.0)).m; - transform.setFreeCameraOptions(options); - EXPECT_DOUBLE_EQ(util::deg2rad(-56.0), transform.getState().getBearing()); - EXPECT_DOUBLE_EQ(0.0, transform.getState().getPitch()); - EXPECT_DOUBLE_EQ(0.0, transform.getState().getX()); - EXPECT_NEAR(152.192378, transform.getState().getY(), 1e-6); + transform->setFreeCameraOptions(options); + EXPECT_DOUBLE_EQ(util::deg2rad(-56.0), transform->getState().getBearing()); + EXPECT_DOUBLE_EQ(0.0, transform->getState().getPitch()); + EXPECT_DOUBLE_EQ(0.0, transform->getState().getX()); + EXPECT_NEAR(152.192378, transform->getState().getY(), 1e-6); options.orientation = Quaternion::fromEulerAngles(0.0, 0.0, util::deg2rad(-179.0)) .multiply(Quaternion::fromEulerAngles(util::deg2rad(-30.0), 0.0, 0.0)) .m; - transform.setFreeCameraOptions(options); - EXPECT_DOUBLE_EQ(util::deg2rad(179.0), transform.getState().getBearing()); - EXPECT_DOUBLE_EQ(util::deg2rad(30.0), transform.getState().getPitch()); - EXPECT_NEAR(1.308930, transform.getState().getX(), 1e-6); - EXPECT_NEAR(56.813889, transform.getState().getY(), 1e-6); + transform->setFreeCameraOptions(options); + EXPECT_DOUBLE_EQ(util::deg2rad(179.0), transform->getState().getBearing()); + EXPECT_DOUBLE_EQ(util::deg2rad(30.0), transform->getState().getPitch()); + EXPECT_NEAR(1.308930, transform->getState().getX(), 1e-6); + EXPECT_NEAR(56.813889, transform->getState().getY(), 1e-6); } static std::tuple rotatedFrame(const std::array& quaternion) { @@ -1075,117 +1091,121 @@ static std::tuple rotatedFrame(const std::array& qu q.transform({{1.0, 0.0, 0.0}}), q.transform({{0.0, -1.0, 0.0}}), q.transform({{0.0, 0.0, -1.0}})); } -TEST(Transform, FreeCameraOptionsClampPitch) { - Transform transform; - transform.resize({100, 100}); +TEST_P(TransfromParametrized, FreeCameraOptionsClampPitch) { + std::shared_ptr transform = GetParam(); + transform->resize({100, 100}); FreeCameraOptions options; vec3 right, up, forward; options.orientation = Quaternion::fromAxisAngle(vec3{{1.0, 0.0, 0.0}}, util::deg2rad(-85.0)).m; - transform.setFreeCameraOptions(options); - EXPECT_DOUBLE_EQ(util::PITCH_MAX, transform.getState().getPitch()); - std::tie(right, up, forward) = rotatedFrame(transform.getFreeCameraOptions().orientation.value()); + transform->setFreeCameraOptions(options); + EXPECT_DOUBLE_EQ(util::PITCH_MAX, transform->getState().getPitch()); + std::tie(right, up, forward) = rotatedFrame(transform->getFreeCameraOptions().orientation.value()); EXPECT_THAT(right, Vec3NearEquals1E5(vec3{{1.0, 0.0, 0.0}})); EXPECT_THAT(up, Vec3NearEquals1E5(vec3{{0, -0.5, 0.866025}})); EXPECT_THAT(forward, Vec3NearEquals1E5(vec3{{0, -0.866025, -0.5}})); } -TEST(Transform, FreeCameraOptionsClampToBounds) { - Transform transform; - transform.resize({100, 100}); - transform.setConstrainMode(ConstrainMode::WidthAndHeight); - transform.jumpTo(CameraOptions().withZoom(8.56)); +TEST_P(TransfromParametrized, FreeCameraOptionsClampToBounds) { + std::shared_ptr transform = GetParam(); + transform->resize({100, 100}); + transform->setConstrainMode(ConstrainMode::WidthAndHeight); + transform->jumpTo(CameraOptions().withZoom(8.56)); FreeCameraOptions options; // Place camera to an arbitrary position looking away from the map options.position = vec3{{-100.0, -10000.0, 1000.0}}; options.orientation = Quaternion::fromEulerAngles(util::deg2rad(-45.0), 0.0, 0.0).m; - transform.setFreeCameraOptions(options); + transform->setFreeCameraOptions(options); // Map center should be clamped to width/2 pixels away from map borders - EXPECT_DOUBLE_EQ(206.0, transform.getState().getX()); - EXPECT_DOUBLE_EQ(206.0, transform.getState().getY()); - EXPECT_DOUBLE_EQ(0.0, transform.getState().getBearing()); - EXPECT_DOUBLE_EQ(util::deg2rad(45.0), transform.getState().getPitch()); + EXPECT_DOUBLE_EQ(206.0, transform->getState().getX()); + EXPECT_DOUBLE_EQ(206.0, transform->getState().getY()); + EXPECT_DOUBLE_EQ(0.0, transform->getState().getBearing()); + EXPECT_DOUBLE_EQ(util::deg2rad(45.0), transform->getState().getPitch()); vec3 right, up, forward; - std::tie(right, up, forward) = rotatedFrame(transform.getFreeCameraOptions().orientation.value()); - EXPECT_THAT(transform.getFreeCameraOptions().position.value(), + std::tie(right, up, forward) = rotatedFrame(transform->getFreeCameraOptions().orientation.value()); + EXPECT_THAT(transform->getFreeCameraOptions().position.value(), Vec3NearEquals1E5(vec3{{0.0976562, 0.304816, 0.20716}})); EXPECT_THAT(right, Vec3NearEquals1E5(vec3{{1.0, 0.0, 0.0}})); EXPECT_THAT(up, Vec3NearEquals1E5(vec3{{0, -0.707107, 0.707107}})); EXPECT_THAT(forward, Vec3NearEquals1E5(vec3{{0, -0.707107, -0.707107}})); } -TEST(Transform, FreeCameraOptionsInvalidState) { - Transform transform; +TEST_P(TransfromParametrized, FreeCameraOptionsInvalidState) { + std::shared_ptr transform = GetParam(); // Invalid size - EXPECT_DOUBLE_EQ(0.0, transform.getState().getX()); - EXPECT_DOUBLE_EQ(0.0, transform.getState().getY()); - EXPECT_DOUBLE_EQ(0.0, transform.getState().getBearing()); - EXPECT_DOUBLE_EQ(0.0, transform.getState().getPitch()); + EXPECT_DOUBLE_EQ(0.0, transform->getState().getX()); + EXPECT_DOUBLE_EQ(0.0, transform->getState().getY()); + EXPECT_DOUBLE_EQ(0.0, transform->getState().getBearing()); + EXPECT_DOUBLE_EQ(0.0, transform->getState().getPitch()); - const auto options = transform.getFreeCameraOptions(); + const auto options = transform->getFreeCameraOptions(); EXPECT_THAT(options.position.value(), Vec3NearEquals1E5(vec3{{0.0, 0.0, 0.0}})); } -TEST(Transform, FreeCameraOptionsOrientationRoll) { - Transform transform; +TEST_P(TransfromParametrized, FreeCameraOptionsOrientationRoll) { + std::shared_ptr transform = GetParam(); FreeCameraOptions options; - transform.resize({100, 100}); + transform->resize({100, 100}); const auto orientationWithoutRoll = Quaternion::fromEulerAngles(-pi / 4, 0.0, 0.0); const auto orientationWithRoll = orientationWithoutRoll.multiply(Quaternion::fromEulerAngles(0.0, 0.0, pi / 4)); options.orientation = orientationWithRoll.m; - transform.setFreeCameraOptions(options); - options = transform.getFreeCameraOptions(); + transform->setFreeCameraOptions(options); + options = transform->getFreeCameraOptions(); EXPECT_NEAR(options.orientation.value()[0], orientationWithoutRoll.x, 1e-9); EXPECT_NEAR(options.orientation.value()[1], orientationWithoutRoll.y, 1e-9); EXPECT_NEAR(options.orientation.value()[2], orientationWithoutRoll.z, 1e-9); EXPECT_NEAR(options.orientation.value()[3], orientationWithoutRoll.w, 1e-9); - EXPECT_NEAR(util::deg2rad(45.0), transform.getState().getPitch(), 1e-9); - EXPECT_NEAR(0.0, transform.getState().getBearing(), 1e-9); - EXPECT_NEAR(0.0, transform.getState().getX(), 1e-9); - EXPECT_NEAR(150.0, transform.getState().getY(), 1e-9); + EXPECT_NEAR(util::deg2rad(45.0), transform->getState().getPitch(), 1e-9); + EXPECT_NEAR(0.0, transform->getState().getBearing(), 1e-9); + EXPECT_NEAR(0.0, transform->getState().getX(), 1e-9); + EXPECT_NEAR(150.0, transform->getState().getY(), 1e-9); } -TEST(Transform, FreeCameraOptionsStateSynchronization) { - Transform transform; - transform.resize({100, 100}); +TEST_P(TransfromParametrized, FreeCameraOptionsStateSynchronization) { + std::shared_ptr transform = GetParam(); + transform->resize({100, 100}); vec3 right, up, forward; - transform.jumpTo(CameraOptions().withPitch(0.0).withBearing(0.0)); - std::tie(right, up, forward) = rotatedFrame(transform.getFreeCameraOptions().orientation.value()); - EXPECT_THAT(transform.getFreeCameraOptions().position.value(), Vec3NearEquals1E5(vec3{{0.5, 0.5, 0.29296875}})); + transform->jumpTo(CameraOptions().withPitch(0.0).withBearing(0.0)); + std::tie(right, up, forward) = rotatedFrame(transform->getFreeCameraOptions().orientation.value()); + EXPECT_THAT(transform->getFreeCameraOptions().position.value(), Vec3NearEquals1E5(vec3{{0.5, 0.5, 0.29296875}})); EXPECT_THAT(right, Vec3NearEquals1E5(vec3{{1.0, 0.0, 0.0}})); EXPECT_THAT(up, Vec3NearEquals1E5(vec3{{0.0, -1.0, 0.0}})); EXPECT_THAT(forward, Vec3NearEquals1E5(vec3{{0.0, 0.0, -1.0}})); - transform.jumpTo(CameraOptions().withCenter(LatLng{60.1699, 24.9384})); - EXPECT_THAT(transform.getFreeCameraOptions().position.value(), + transform->jumpTo(CameraOptions().withCenter(LatLng{60.1699, 24.9384})); + EXPECT_THAT(transform->getFreeCameraOptions().position.value(), Vec3NearEquals1E5(vec3{{0.569273, 0.289453, 0.292969}})); - transform.jumpTo(CameraOptions().withPitch(20.0).withBearing(77.0).withCenter(LatLng{-20.0, 20.0})); - EXPECT_THAT(transform.getFreeCameraOptions().position.value(), + transform->jumpTo(CameraOptions().withPitch(20.0).withBearing(77.0).withCenter(LatLng{-20.0, 20.0})); + EXPECT_THAT(transform->getFreeCameraOptions().position.value(), Vec3NearEquals1E5(vec3{{0.457922, 0.57926, 0.275301}})); // Invalid pitch - transform.jumpTo(CameraOptions().withPitch(-10.0).withBearing(0.0)); - std::tie(right, up, forward) = rotatedFrame(transform.getFreeCameraOptions().orientation.value()); - EXPECT_THAT(transform.getFreeCameraOptions().position.value(), + transform->jumpTo(CameraOptions().withPitch(-10.0).withBearing(0.0)); + std::tie(right, up, forward) = rotatedFrame(transform->getFreeCameraOptions().orientation.value()); + EXPECT_THAT(transform->getFreeCameraOptions().position.value(), Vec3NearEquals1E5(vec3{{0.555556, 0.556719, 0.292969}})); EXPECT_THAT(right, Vec3NearEquals1E5(vec3{{1.0, 0.0, 0.0}})); EXPECT_THAT(up, Vec3NearEquals1E5(vec3{{0.0, -1.0, 0.0}})); EXPECT_THAT(forward, Vec3NearEquals1E5(vec3{{0.0, 0.0, -1.0}})); - transform.jumpTo(CameraOptions().withPitch(85.0).withBearing(0.0).withCenter(LatLng{-80.0, 0.0})); - std::tie(right, up, forward) = rotatedFrame(transform.getFreeCameraOptions().orientation.value()); - EXPECT_THAT(transform.getFreeCameraOptions().position.value(), Vec3NearEquals1E5(vec3{{0.5, 1.14146, 0.146484}})); + transform->jumpTo(CameraOptions().withPitch(85.0).withBearing(0.0).withCenter(LatLng{-80.0, 0.0})); + std::tie(right, up, forward) = rotatedFrame(transform->getFreeCameraOptions().orientation.value()); + EXPECT_THAT(transform->getFreeCameraOptions().position.value(), Vec3NearEquals1E5(vec3{{0.5, 1.14146, 0.146484}})); EXPECT_THAT(right, Vec3NearEquals1E5(vec3{{1.0, 0.0, 0.0}})); EXPECT_THAT(up, Vec3NearEquals1E5(vec3{{0, -0.5, 0.866025}})); EXPECT_THAT(forward, Vec3NearEquals1E5(vec3{{0, -0.866025, -0.5}})); } + +INSTANTIATE_TEST_SUITE_P(Transform, + TransfromParametrized, + ::testing::Values(std::make_shared(), std::make_shared())); From de41cbf82abab601126d85800337eda0f22a3628 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 1 May 2025 18:26:04 +0300 Subject: [PATCH 077/221] expose the ability to toggle between the old map transform and the active transform --- include/mbgl/map/map.hpp | 1 + platform/ios/src/MLNMapView.h | 2 + platform/ios/src/MLNMapView.mm | 4 ++ src/mbgl/map/map.cpp | 106 ++++++++++++++++++--------------- src/mbgl/map/map_impl.cpp | 19 +++--- src/mbgl/map/map_impl.hpp | 5 +- 6 files changed, 81 insertions(+), 56 deletions(-) diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 442479ee174a..d11402acf081 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -115,6 +115,7 @@ class Map : private util::noncopyable { // Transform TransformState getTransfromState() const; + void toggleTransform(); // Annotations void addAnnotationImage(std::unique_ptr); diff --git a/platform/ios/src/MLNMapView.h b/platform/ios/src/MLNMapView.h index 56a80d14ded3..70f0154971b6 100644 --- a/platform/ios/src/MLNMapView.h +++ b/platform/ios/src/MLNMapView.h @@ -1613,6 +1613,8 @@ vertically on the map. animated:(BOOL)animated completionHandler:(nullable void (^)(void))completion; +- (void)toggleTransform; + // MARK: Converting Geographic Coordinates /** diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 8e4d4404b96e..29def50c217e 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -1387,6 +1387,10 @@ - (void)setContentInset:(UIEdgeInsets)contentInset animated:(BOOL)animated compl // Compass, logo and attribution button constraints needs to be updated.z [self installConstraints]; } +- (void)toggleTransform +{ + self.mbglMap.toggleTransform(); +} /// Returns the frame of inset content within the map view. - (CGRect)contentFrame diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 8903bb1b71c5..c101236d7dfd 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ #include #include +#include #include namespace mbgl { @@ -74,7 +76,7 @@ void Map::renderStill(StillImageCallback callback) { void Map::renderStill(const CameraOptions& camera, MapDebugOptions debugOptions, StillImageCallback callback) { impl->cameraMutated = true; impl->debugOptions = debugOptions; - impl->transform.jumpTo(camera); + impl->transform->jumpTo(camera); renderStill(std::move(callback)); } @@ -104,35 +106,35 @@ void Map::setStyle(std::unique_ptr diff --git a/platform/android/MapLibreAndroid/src/test/java/org/maplibre/android/location/LocationCameraControllerTest.kt b/platform/android/MapLibreAndroid/src/test/java/org/maplibre/android/location/LocationCameraControllerTest.kt index f675f01d1685..25aadb7c372a 100644 --- a/platform/android/MapLibreAndroid/src/test/java/org/maplibre/android/location/LocationCameraControllerTest.kt +++ b/platform/android/MapLibreAndroid/src/test/java/org/maplibre/android/location/LocationCameraControllerTest.kt @@ -264,6 +264,7 @@ class LocationCameraControllerTest { MapLibreMap::class.java ), ArgumentMatchers.any(CameraUpdate::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.nullable(CancelableCallback::class.java) ) } @@ -290,6 +291,7 @@ class LocationCameraControllerTest { MapLibreMap::class.java ), ArgumentMatchers.any(CameraUpdate::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.nullable(CancelableCallback::class.java) ) } @@ -316,6 +318,7 @@ class LocationCameraControllerTest { MapLibreMap::class.java ), ArgumentMatchers.any(CameraUpdate::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.nullable(CancelableCallback::class.java) ) } @@ -342,6 +345,7 @@ class LocationCameraControllerTest { MapLibreMap::class.java ), ArgumentMatchers.any(CameraUpdate::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.nullable(CancelableCallback::class.java) ) } @@ -369,6 +373,7 @@ class LocationCameraControllerTest { MapLibreMap::class.java ), ArgumentMatchers.any(CameraUpdate::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.nullable(CancelableCallback::class.java) ) } @@ -417,6 +422,7 @@ class LocationCameraControllerTest { MapLibreMap::class.java ), ArgumentMatchers.any(CameraUpdate::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.nullable(CancelableCallback::class.java) ) val uiSettings = Mockito.mock(UiSettings::class.java) @@ -447,6 +453,7 @@ class LocationCameraControllerTest { MapLibreMap::class.java ), ArgumentMatchers.any(CameraUpdate::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.nullable(CancelableCallback::class.java) ) } @@ -473,6 +480,7 @@ class LocationCameraControllerTest { MapLibreMap::class.java ), ArgumentMatchers.any(CameraUpdate::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.nullable(CancelableCallback::class.java) ) } @@ -502,6 +510,7 @@ class LocationCameraControllerTest { ArgumentMatchers.any( CameraUpdate::class.java ), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.nullable(CancelableCallback::class.java) ) } @@ -531,6 +540,7 @@ class LocationCameraControllerTest { ArgumentMatchers.any( CameraUpdate::class.java ), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.nullable(CancelableCallback::class.java) ) } @@ -558,6 +568,7 @@ class LocationCameraControllerTest { MapLibreMap::class.java ), ArgumentMatchers.any(CameraUpdate::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.nullable(CancelableCallback::class.java) ) } @@ -585,6 +596,7 @@ class LocationCameraControllerTest { MapLibreMap::class.java ), ArgumentMatchers.any(CameraUpdate::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.nullable(CancelableCallback::class.java) ) } @@ -612,6 +624,7 @@ class LocationCameraControllerTest { MapLibreMap::class.java ), ArgumentMatchers.any(CameraUpdate::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.nullable(CancelableCallback::class.java) ) } @@ -639,6 +652,7 @@ class LocationCameraControllerTest { MapLibreMap::class.java ), ArgumentMatchers.any(CameraUpdate::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.nullable(CancelableCallback::class.java) ) } @@ -665,6 +679,7 @@ class LocationCameraControllerTest { MapLibreMap::class.java ), ArgumentMatchers.any(CameraUpdate::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.nullable(CancelableCallback::class.java) ) } @@ -691,6 +706,7 @@ class LocationCameraControllerTest { MapLibreMap::class.java ), ArgumentMatchers.any(CameraUpdate::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.nullable(CancelableCallback::class.java) ) } @@ -1099,6 +1115,7 @@ class LocationCameraControllerTest { CameraUpdate::class.java ), ArgumentMatchers.any(Int::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.any(CancelableCallback::class.java) ) } @@ -1139,6 +1156,7 @@ class LocationCameraControllerTest { CameraUpdate::class.java ), ArgumentMatchers.any(Int::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.any(CancelableCallback::class.java) ) } @@ -1182,6 +1200,7 @@ class LocationCameraControllerTest { CameraUpdate::class.java ), ArgumentMatchers.any(Int::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.any(CancelableCallback::class.java) ) camera.setCameraMode( @@ -1201,6 +1220,7 @@ class LocationCameraControllerTest { CameraUpdate::class.java ), ArgumentMatchers.any(Int::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.any(CancelableCallback::class.java) ) } @@ -1273,6 +1293,7 @@ class LocationCameraControllerTest { CameraUpdate::class.java ), ArgumentMatchers.any(Int::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.any(CancelableCallback::class.java) ) } @@ -1325,6 +1346,7 @@ class LocationCameraControllerTest { CameraUpdate::class.java ), ArgumentMatchers.any(Int::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.any(CancelableCallback::class.java) ) camera.setCameraMode( @@ -1345,6 +1367,7 @@ class LocationCameraControllerTest { CameraUpdate::class.java ), ArgumentMatchers.any(Int::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.any(CancelableCallback::class.java) ) } @@ -1388,6 +1411,7 @@ class LocationCameraControllerTest { CameraUpdate::class.java ), ArgumentMatchers.any(Int::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.any(CancelableCallback::class.java) ) camera.setCameraMode( @@ -1407,6 +1431,7 @@ class LocationCameraControllerTest { CameraUpdate::class.java ), ArgumentMatchers.any(Int::class.java), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.any(CancelableCallback::class.java) ) } @@ -1462,6 +1487,7 @@ class LocationCameraControllerTest { ArgumentMatchers.eq(maplibreMap), ArgumentMatchers.eq(newCameraPosition(builder.build())), ArgumentMatchers.eq(LocationComponentConstants.TRANSITION_ANIMATION_DURATION_MS.toInt()), + ArgumentMatchers.any(Boolean::class.java), callbackCaptor.capture() ) Assert.assertTrue(camera.isTransitioning) @@ -1520,6 +1546,7 @@ class LocationCameraControllerTest { Mockito.verify(transform).moveCamera( ArgumentMatchers.eq(maplibreMap), ArgumentMatchers.eq(newCameraPosition(builder.build())), + ArgumentMatchers.any(Boolean::class.java), callbackCaptor.capture() ) Assert.assertTrue(camera.isTransitioning) @@ -1579,6 +1606,7 @@ class LocationCameraControllerTest { ArgumentMatchers.eq(maplibreMap), ArgumentMatchers.eq(newCameraPosition(builder.build())), ArgumentMatchers.eq(LocationComponentConstants.TRANSITION_ANIMATION_DURATION_MS.toInt()), + ArgumentMatchers.any(Boolean::class.java), callbackCaptor.capture() ) Assert.assertTrue(camera.isTransitioning) @@ -1635,6 +1663,7 @@ class LocationCameraControllerTest { ArgumentMatchers.eq(maplibreMap), ArgumentMatchers.eq(newCameraPosition(builder.build())), ArgumentMatchers.eq(LocationComponentConstants.TRANSITION_ANIMATION_DURATION_MS.toInt()), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.any(CancelableCallback::class.java) ) } @@ -1687,6 +1716,7 @@ class LocationCameraControllerTest { ArgumentMatchers.eq(maplibreMap), ArgumentMatchers.eq(newCameraPosition(builder.build())), ArgumentMatchers.eq(LocationComponentConstants.TRANSITION_ANIMATION_DURATION_MS.toInt()), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.any(CancelableCallback::class.java) ) } @@ -1737,6 +1767,7 @@ class LocationCameraControllerTest { ArgumentMatchers.eq(maplibreMap), ArgumentMatchers.any(CameraUpdate::class.java), ArgumentMatchers.eq(LocationComponentConstants.TRANSITION_ANIMATION_DURATION_MS.toInt()), + ArgumentMatchers.any(Boolean::class.java), callbackCaptor.capture() ) val latLng = LatLng(10.0, 10.0) @@ -1761,6 +1792,7 @@ class LocationCameraControllerTest { ArgumentMatchers.any( CameraUpdate::class.java ), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.nullable(CancelableCallback::class.java) ) callbackCaptor.value.onFinish() @@ -1785,6 +1817,7 @@ class LocationCameraControllerTest { ArgumentMatchers.any( CameraUpdate::class.java ), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.nullable(CancelableCallback::class.java) ) } @@ -1830,6 +1863,7 @@ class LocationCameraControllerTest { ArgumentMatchers.eq(maplibreMap), ArgumentMatchers.eq(cameraUpdate), ArgumentMatchers.eq(1200), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.any( CancelableCallback::class.java ) @@ -1878,6 +1912,7 @@ class LocationCameraControllerTest { ArgumentMatchers.eq(maplibreMap), ArgumentMatchers.eq(cameraUpdate), ArgumentMatchers.eq(1200), + ArgumentMatchers.any(Boolean::class.java), ArgumentMatchers.any( CancelableCallback::class.java ) diff --git a/platform/android/MapLibreAndroid/src/test/java/org/maplibre/android/maps/MapLibreMapTest.kt b/platform/android/MapLibreAndroid/src/test/java/org/maplibre/android/maps/MapLibreMapTest.kt index a84cb1542072..c3254f693869 100644 --- a/platform/android/MapLibreAndroid/src/test/java/org/maplibre/android/maps/MapLibreMapTest.kt +++ b/platform/android/MapLibreAndroid/src/test/java/org/maplibre/android/maps/MapLibreMapTest.kt @@ -76,7 +76,7 @@ class MapLibreMapTest { val expected = CameraPosition.Builder().target(target).build() val update = CameraUpdateFactory.newCameraPosition(expected) maplibreMap.moveCamera(update, callback) - verify { transform.moveCamera(maplibreMap, update, callback) } + verify { transform.moveCamera(maplibreMap, update, true, callback) } verify { developerAnimationListener.onDeveloperAnimationStarted() } } @@ -87,7 +87,7 @@ class MapLibreMapTest { val expected = CameraPosition.Builder().target(target).build() val update = CameraUpdateFactory.newCameraPosition(expected) maplibreMap.easeCamera(update, callback) - verify { transform.easeCamera(maplibreMap, update, MapLibreConstants.ANIMATION_DURATION, true, callback) } + verify { transform.easeCamera(maplibreMap, update, MapLibreConstants.ANIMATION_DURATION, true, true, callback) } verify { developerAnimationListener.onDeveloperAnimationStarted() } } @@ -98,7 +98,7 @@ class MapLibreMapTest { val expected = CameraPosition.Builder().target(target).build() val update = CameraUpdateFactory.newCameraPosition(expected) maplibreMap.animateCamera(update, callback) - verify { transform.animateCamera(maplibreMap, update, MapLibreConstants.ANIMATION_DURATION, callback) } + verify { transform.animateCamera(maplibreMap, update, MapLibreConstants.ANIMATION_DURATION, true, callback) } verify { developerAnimationListener.onDeveloperAnimationStarted() } } From be31aab1d00c933fbae41ec86a39098f3bdacd82 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 19 Jun 2025 16:35:36 +0300 Subject: [PATCH 096/221] make new android release --- platform/android/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/android/VERSION b/platform/android/VERSION index d5b7da553866..d9db763c99d6 100644 --- a/platform/android/VERSION +++ b/platform/android/VERSION @@ -1 +1 @@ -11.10.3 +11.10.4 From 0355f3162807fdc769b07e3ff6c9f374d8d832ed Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Sun, 22 Jun 2025 18:42:10 +0300 Subject: [PATCH 097/221] make release notes for android release --- platform/android/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index c2a8bcd1ca92..0bcc6513d75b 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog MapLibre Native for Android +## 11.10.4 + +### ✨ Features and improvements + +- Concurrent camera animations + ## 11.10.3 ### 🐞 Bug fixes From 918b86fdc608ee6596f7fe00a75514602bad039b Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Tue, 24 Jun 2025 11:43:31 +0300 Subject: [PATCH 098/221] fix android ci to make debug releases --- .github/workflows/android-release.yml | 9 ++++++++- .../src/main/kotlin/maplibre.gradle-publish.gradle.kts | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/android-release.yml b/.github/workflows/android-release.yml index 0e26900ffd41..1ea64671f404 100644 --- a/.github/workflows/android-release.yml +++ b/.github/workflows/android-release.yml @@ -79,6 +79,7 @@ jobs: - opengl BUILDTYPE: - Release + - Debug steps: - uses: actions/checkout@v4 with: @@ -134,4 +135,10 @@ jobs: - name: Publish to Github env: GITHUB_TOKEN: ${{ secrets.MAPLIBRE_NATIVE_PRIVATE_TOKEN }} - run: make run-android-publish + run: | + renderer=${{ matrix.RENDERER }} + if [ "$renderer" = "opengl" ]; then + ./gradlew :MapLibreAndroid:publishDefault${{ env.buildtype }}PublicationToGithubPackagesRepository + else + ./gradlew :MapLibreAndroid:publishVulkan${{ env.buildtype }}PublicationToGithubPackagesRepository + fi diff --git a/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts index d8a1b0c4f03f..5c9375f98345 100644 --- a/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts +++ b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts @@ -89,9 +89,9 @@ fun PublishingExtension.configureMavenPublication( afterEvaluate { publishing { configureMavenPublication("opengl", "defaultrelease", "", "") - // configureMavenPublication("opengl", "defaultdebug", "-debug", " (Debug)", "Debug") + configureMavenPublication("opengl", "defaultdebug", "-debug", " (Debug)", "Debug") configureMavenPublication("vulkan", "vulkanrelease", "-vulkan", "(Vulkan)") - // configureMavenPublication("vulkan", "vulkandebug", "-vulkan-debug", "(Vulkan, Debug)", "Debug") + configureMavenPublication("vulkan", "vulkandebug", "-vulkan-debug", "(Vulkan, Debug)", "Debug") repositories { maven { From 036ad4563b9f8ebbaeb7dcfd407752dc077c654e Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Tue, 24 Jun 2025 11:43:51 +0300 Subject: [PATCH 099/221] make android 11.10.5 release --- platform/android/CHANGELOG.md | 6 ++++++ platform/android/VERSION | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index 0bcc6513d75b..051a92115632 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog MapLibre Native for Android +## 11.10.5 + +### ✨ Features and improvements + +- Release debug builds for android + ## 11.10.4 ### ✨ Features and improvements diff --git a/platform/android/VERSION b/platform/android/VERSION index d9db763c99d6..5413747c6827 100644 --- a/platform/android/VERSION +++ b/platform/android/VERSION @@ -1 +1 @@ -11.10.4 +11.10.5 From da0b6a82eea0a5705585fc17038e51a1aafe01f1 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 26 Jun 2025 16:01:24 +0300 Subject: [PATCH 100/221] make ios release 6.15.2 --- platform/ios/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/VERSION b/platform/ios/VERSION index d36e8d82f37f..0bffdbe7afb7 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.15.1 +6.15.2 From 13ce2e57e9c1ad67f574f91cfb69b75fecd5eaf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Tue, 1 Jul 2025 14:00:59 -0400 Subject: [PATCH 101/221] Removed GLTF Custom Layer from map engine --- platform/BUILD.bazel | 4 - platform/darwin/BUILD.bazel | 18 - platform/darwin/bazel/files.bzl | 82 -- platform/darwin/src/gltf/Camera.cpp | 54 - platform/darwin/src/gltf/Camera.hpp | 32 - platform/darwin/src/gltf/GLTFMTLRenderItem.h | 22 - platform/darwin/src/gltf/GLTFMTLRenderItem.mm | 12 - platform/darwin/src/gltf/GLTFManager.hpp | 106 -- platform/darwin/src/gltf/GLTFManager.mm | 170 --- .../gltf/GLTFManagerRenderingEnvironment.hpp | 40 - .../gltf/GLTFManagerRenderingEnvironment.mm | 8 - .../GLTFManagerRenderingEnvironmentMetal.hpp | 41 - .../GLTFManagerRenderingEnvironmentMetal.mm | 8 - platform/darwin/src/gltf/GLTFMath.cpp | 192 --- platform/darwin/src/gltf/GLTFMath.hpp | 139 -- platform/darwin/src/gltf/GLTFModel.cpp | 8 - platform/darwin/src/gltf/GLTFModel.hpp | 46 - platform/darwin/src/gltf/GLTFModelLayer.h | 29 - platform/darwin/src/gltf/GLTFModelLayer.mm | 357 ----- platform/darwin/src/gltf/GLTFModelLoader.h | 23 - platform/darwin/src/gltf/GLTFModelLoader.mm | 74 - platform/darwin/src/gltf/GLTFRenderer.cpp | 71 - platform/darwin/src/gltf/GLTFRenderer.hpp | 70 - .../src/gltf/MetalRenderer+GLTFAsset.mm | 561 -------- platform/darwin/src/gltf/MetalRenderer.hpp | 228 --- platform/darwin/src/gltf/MetalRenderer.mm | 540 ------- .../darwin/src/gltf/gltfkit/GLTFAccessor.h | 40 - .../darwin/src/gltf/gltfkit/GLTFAccessor.mm | 26 - .../darwin/src/gltf/gltfkit/GLTFAnimation.h | 46 - .../darwin/src/gltf/gltfkit/GLTFAnimation.mm | 173 --- platform/darwin/src/gltf/gltfkit/GLTFAsset.h | 70 - platform/darwin/src/gltf/gltfkit/GLTFAsset.mm | 1274 ----------------- .../darwin/src/gltf/gltfkit/GLTFBinaryChunk.h | 35 - .../src/gltf/gltfkit/GLTFBinaryChunk.mm | 23 - platform/darwin/src/gltf/gltfkit/GLTFBuffer.h | 31 - .../src/gltf/gltfkit/GLTFBufferAllocator.h | 29 - .../darwin/src/gltf/gltfkit/GLTFBufferView.h | 32 - .../darwin/src/gltf/gltfkit/GLTFBufferView.mm | 26 - platform/darwin/src/gltf/gltfkit/GLTFCamera.h | 42 - .../darwin/src/gltf/gltfkit/GLTFCamera.mm | 115 -- .../gltf/gltfkit/GLTFDefaultBufferAllocator.h | 27 - .../gltfkit/GLTFDefaultBufferAllocator.mm | 93 -- platform/darwin/src/gltf/gltfkit/GLTFEnums.h | 178 --- .../src/gltf/gltfkit/GLTFExtensionNames.h | 23 - .../src/gltf/gltfkit/GLTFExtensionNames.mm | 23 - platform/darwin/src/gltf/gltfkit/GLTFImage.h | 40 - platform/darwin/src/gltf/gltfkit/GLTFImage.mm | 57 - .../darwin/src/gltf/gltfkit/GLTFKHRLight.h | 53 - .../darwin/src/gltf/gltfkit/GLTFKHRLight.mm | 33 - .../src/gltf/gltfkit/GLTFMTLBufferAllocator.h | 36 - .../gltf/gltfkit/GLTFMTLBufferAllocator.mm | 101 -- .../src/gltf/gltfkit/GLTFMTLShaderBuilder.h | 40 - .../src/gltf/gltfkit/GLTFMTLShaderBuilder.mm | 246 ---- .../src/gltf/gltfkit/GLTFMTLTextureLoader.h | 35 - .../src/gltf/gltfkit/GLTFMTLTextureLoader.mm | 244 ---- .../src/gltf/gltfkit/GLTFMTLUtilities.h | 56 - .../src/gltf/gltfkit/GLTFMTLUtilities.mm | 291 ---- .../darwin/src/gltf/gltfkit/GLTFMaterial.h | 65 - .../darwin/src/gltf/gltfkit/GLTFMaterial.mm | 35 - platform/darwin/src/gltf/gltfkit/GLTFMesh.h | 43 - platform/darwin/src/gltf/gltfkit/GLTFMesh.mm | 69 - platform/darwin/src/gltf/gltfkit/GLTFNode.h | 49 - platform/darwin/src/gltf/gltfkit/GLTFNode.mm | 171 --- .../darwin/src/gltf/gltfkit/GLTFNodeVisitor.h | 31 - platform/darwin/src/gltf/gltfkit/GLTFObject.h | 45 - .../darwin/src/gltf/gltfkit/GLTFObject.mm | 32 - platform/darwin/src/gltf/gltfkit/GLTFScene.h | 35 - platform/darwin/src/gltf/gltfkit/GLTFScene.mm | 57 - platform/darwin/src/gltf/gltfkit/GLTFSkin.h | 30 - platform/darwin/src/gltf/gltfkit/GLTFSkin.mm | 20 - .../darwin/src/gltf/gltfkit/GLTFTexture.h | 63 - .../darwin/src/gltf/gltfkit/GLTFTexture.mm | 44 - .../src/gltf/gltfkit/GLTFTextureSampler.h | 34 - .../src/gltf/gltfkit/GLTFTextureSampler.mm | 60 - .../darwin/src/gltf/gltfkit/GLTFUtilities.h | 72 - .../darwin/src/gltf/gltfkit/GLTFUtilities.mm | 262 ---- .../src/gltf/gltfkit/GLTFVertexDescriptor.h | 54 - .../src/gltf/gltfkit/GLTFVertexDescriptor.mm | 71 - .../src/gltf/gltfkit/shaders/brdf.metal | 230 --- .../darwin/src/gltf/gltfkit/shaders/hdr.metal | 123 -- .../darwin/src/gltf/gltfkit/shaders/pbr.metal | 463 ------ .../darwin/src/gltf/gltfkit/shaders/pbr.txt | 463 ------ platform/ios/BUILD.bazel | 1 - 83 files changed, 9095 deletions(-) delete mode 100644 platform/darwin/src/gltf/Camera.cpp delete mode 100644 platform/darwin/src/gltf/Camera.hpp delete mode 100644 platform/darwin/src/gltf/GLTFMTLRenderItem.h delete mode 100644 platform/darwin/src/gltf/GLTFMTLRenderItem.mm delete mode 100644 platform/darwin/src/gltf/GLTFManager.hpp delete mode 100644 platform/darwin/src/gltf/GLTFManager.mm delete mode 100644 platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp delete mode 100644 platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.mm delete mode 100644 platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp delete mode 100644 platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.mm delete mode 100644 platform/darwin/src/gltf/GLTFMath.cpp delete mode 100644 platform/darwin/src/gltf/GLTFMath.hpp delete mode 100644 platform/darwin/src/gltf/GLTFModel.cpp delete mode 100644 platform/darwin/src/gltf/GLTFModel.hpp delete mode 100644 platform/darwin/src/gltf/GLTFModelLayer.h delete mode 100644 platform/darwin/src/gltf/GLTFModelLayer.mm delete mode 100644 platform/darwin/src/gltf/GLTFModelLoader.h delete mode 100644 platform/darwin/src/gltf/GLTFModelLoader.mm delete mode 100644 platform/darwin/src/gltf/GLTFRenderer.cpp delete mode 100644 platform/darwin/src/gltf/GLTFRenderer.hpp delete mode 100644 platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm delete mode 100644 platform/darwin/src/gltf/MetalRenderer.hpp delete mode 100644 platform/darwin/src/gltf/MetalRenderer.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFAccessor.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFAccessor.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFAnimation.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFAnimation.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFAsset.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFAsset.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFBuffer.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFBufferAllocator.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFBufferView.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFBufferView.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFCamera.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFCamera.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFEnums.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFImage.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFImage.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFKHRLight.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFKHRLight.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMaterial.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMaterial.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMesh.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMesh.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFNode.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFNode.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFNodeVisitor.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFObject.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFObject.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFScene.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFScene.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFSkin.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFSkin.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFTexture.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFTexture.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFUtilities.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFUtilities.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/shaders/brdf.metal delete mode 100644 platform/darwin/src/gltf/gltfkit/shaders/hdr.metal delete mode 100644 platform/darwin/src/gltf/gltfkit/shaders/pbr.metal delete mode 100644 platform/darwin/src/gltf/gltfkit/shaders/pbr.txt diff --git a/platform/BUILD.bazel b/platform/BUILD.bazel index 457e851e6b31..51b56a3ee641 100644 --- a/platform/BUILD.bazel +++ b/platform/BUILD.bazel @@ -5,8 +5,6 @@ load("//bazel:flags.bzl", "CPP_FLAGS", "MAPLIBRE_FLAGS", "WARNING_FLAGS") objc_library( name = "macos-objcpp", srcs = [ - "//platform/darwin:darwin_gltf_hdrs", - "//platform/darwin:darwin_gltf_srcs", "//platform/darwin:darwin_objcpp_custom_drawable_srcs", "//platform/darwin:darwin_objcpp_srcs", "//platform/darwin:darwin_private_hdrs", @@ -138,7 +136,6 @@ objc_library( objc_library( name = "objc-sdk", srcs = [ - "//platform/darwin:darwin_gltf_srcs", "//platform/darwin:darwin_objc_srcs", "//platform/ios:ios_objc_srcs", "//platform/ios:ios_private_hdrs", @@ -199,7 +196,6 @@ objc_library( objc_library( name = "ios-sdk", hdrs = [ - "//platform/darwin:darwin_gltf_hdrs", "//platform/darwin:darwin_objc_hdrs", "//platform/darwin:generated_style_public_hdrs", "//platform/ios:ios_sdk_hdrs", diff --git a/platform/darwin/BUILD.bazel b/platform/darwin/BUILD.bazel index 157c2f16b107..3dc5e8e01d28 100644 --- a/platform/darwin/BUILD.bazel +++ b/platform/darwin/BUILD.bazel @@ -17,8 +17,6 @@ load( "MLN_GENERATED_DARWIN_STYLE_PUBLIC_HEADERS", "MLN_GENERATED_DARWIN_STYLE_SOURCE", "MLN_GENERATED_DARWIN_TEST_CODE", - "MLN_GLTF_HEADERS", - "MLN_GLTF_SOURCE", ) filegroup( @@ -45,18 +43,6 @@ filegroup( visibility = ["//visibility:public"], ) -filegroup( - name = "darwin_gltf_hdrs", - srcs = MLN_GLTF_HEADERS, - visibility = ["//visibility:public"], -) - -filegroup( - name = "darwin_gltf_srcs", - srcs = MLN_GLTF_SOURCE, - visibility = ["//visibility:public"], -) - filegroup( name = "darwin_objcpp_custom_drawable_srcs", srcs = MLN_DARWIN_PUBLIC_OBJCPP_CUSTOM_DRAWABLE_SOURCE, @@ -326,8 +312,6 @@ exports_files( "include/mbgl/util/image+MLNAdditions.hpp", ] + MLN_DARWIN_PUBLIC_OBJC_SOURCE + MLN_DARWIN_PUBLIC_OBJCPP_SOURCE + - MLN_GLTF_HEADERS + - MLN_GLTF_SOURCE + MLN_DARWIN_PUBLIC_OBJCPP_CUSTOM_DRAWABLE_SOURCE + MLN_DARWIN_PRIVATE_HEADERS + MLN_DARWIN_OBJC_HEADERS + @@ -351,8 +335,6 @@ js_binary( js_library( name = "symbols-to-check", srcs = [ - ":darwin_gltf_hdrs", - ":darwin_gltf_srcs", ":darwin_objc_hdrs", ":darwin_objc_srcs", ":darwin_objcpp_hdrs", diff --git a/platform/darwin/bazel/files.bzl b/platform/darwin/bazel/files.bzl index af0e842864be..d510ebe29535 100644 --- a/platform/darwin/bazel/files.bzl +++ b/platform/darwin/bazel/files.bzl @@ -1,85 +1,3 @@ -MLN_GLTF_HEADERS = [ - "src/gltf/GLTFModelLayer.h", -] - -MLN_GLTF_SOURCE = [ - "src/gltf/Camera.hpp", - "src/gltf/Camera.cpp", - "src/gltf/GLTFMath.cpp", - "src/gltf/GLTFMath.hpp", - "src/gltf/GLTFManager.hpp", - "src/gltf/GLTFManager.mm", - "src/gltf/GLTFManagerRenderingEnvironment.hpp", - "src/gltf/GLTFManagerRenderingEnvironment.mm", - "src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp", - "src/gltf/GLTFManagerRenderingEnvironmentMetal.mm", - "src/gltf/GLTFModel.hpp", - "src/gltf/GLTFModel.cpp", - "src/gltf/MetalRenderer.hpp", - "src/gltf/MetalRenderer.mm", - "src/gltf/GLTFModelLayer.h", - "src/gltf/GLTFModelLayer.mm", - "src/gltf/GLTFModelLoader.h", - "src/gltf/GLTFModelLoader.mm", - "src/gltf/GLTFMTLRenderItem.h", - "src/gltf/GLTFMTLRenderItem.mm", - "src/gltf/GLTFRenderer.hpp", - "src/gltf/GLTFRenderer.cpp", - "src/gltf/MetalRenderer+GLTFAsset.mm", - "src/gltf/gltfkit/GLTFAsset.h", - "src/gltf/gltfkit/GLTFAsset.mm", - "src/gltf/gltfkit/GLTFAccessor.h", - "src/gltf/gltfkit/GLTFAccessor.mm", - "src/gltf/gltfkit/GLTFAnimation.h", - "src/gltf/gltfkit/GLTFAnimation.mm", - "src/gltf/gltfkit/GLTFBinaryChunk.h", - "src/gltf/gltfkit/GLTFBinaryChunk.mm", - "src/gltf/gltfkit/GLTFBuffer.h", - "src/gltf/gltfkit/GLTFBufferAllocator.h", - "src/gltf/gltfkit/GLTFBufferView.h", - "src/gltf/gltfkit/GLTFBufferView.mm", - "src/gltf/gltfkit/GLTFCamera.h", - "src/gltf/gltfkit/GLTFCamera.mm", - "src/gltf/gltfkit/GLTFDefaultBufferAllocator.h", - "src/gltf/gltfkit/GLTFDefaultBufferAllocator.mm", - "src/gltf/gltfkit/GLTFEnums.h", - "src/gltf/gltfkit/GLTFExtensionNames.h", - "src/gltf/gltfkit/GLTFExtensionNames.mm", - "src/gltf/gltfkit/GLTFImage.h", - "src/gltf/gltfkit/GLTFImage.mm", - "src/gltf/gltfkit/GLTFKHRLight.h", - "src/gltf/gltfkit/GLTFKHRLight.mm", - "src/gltf/gltfkit/GLTFMaterial.h", - "src/gltf/gltfkit/GLTFMaterial.mm", - "src/gltf/gltfkit/GLTFMesh.h", - "src/gltf/gltfkit/GLTFMesh.mm", - "src/gltf/gltfkit/GLTFMTLBufferAllocator.h", - "src/gltf/gltfkit/GLTFMTLBufferAllocator.mm", - "src/gltf/gltfkit/GLTFMTLShaderBuilder.h", - "src/gltf/gltfkit/GLTFMTLShaderBuilder.mm", - "src/gltf/gltfkit/GLTFMTLTextureLoader.h", - "src/gltf/gltfkit/GLTFMTLTextureLoader.mm", - "src/gltf/gltfkit/GLTFMTLUtilities.h", - "src/gltf/gltfkit/GLTFMTLUtilities.mm", - "src/gltf/gltfkit/GLTFNode.h", - "src/gltf/gltfkit/GLTFNode.mm", - "src/gltf/gltfkit/GLTFNodeVisitor.h", - "src/gltf/gltfkit/GLTFObject.h", - "src/gltf/gltfkit/GLTFObject.mm", - "src/gltf/gltfkit/GLTFScene.h", - "src/gltf/gltfkit/GLTFScene.mm", - "src/gltf/gltfkit/GLTFSkin.h", - "src/gltf/gltfkit/GLTFSkin.mm", - "src/gltf/gltfkit/GLTFTexture.h", - "src/gltf/gltfkit/GLTFTexture.mm", - "src/gltf/gltfkit/GLTFTextureSampler.h", - "src/gltf/gltfkit/GLTFTextureSampler.mm", - "src/gltf/gltfkit/GLTFUtilities.h", - "src/gltf/gltfkit/GLTFUtilities.mm", - "src/gltf/gltfkit/GLTFVertexDescriptor.h", - "src/gltf/gltfkit/GLTFVertexDescriptor.mm", -] - MLN_GENERATED_DARWIN_STYLE_SOURCE = [ "src/MLNLight.mm", "src/MLNBackgroundStyleLayer.mm", diff --git a/platform/darwin/src/gltf/Camera.cpp b/platform/darwin/src/gltf/Camera.cpp deleted file mode 100644 index 6dc63dced2f3..000000000000 --- a/platform/darwin/src/gltf/Camera.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// Camera.cpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#include "Camera.hpp" -#include "GLTFMath.hpp" - -const float GLTFViewerOrbitCameraDefaultDistance = 2; -const float GLTFViewerOrbitCameraZoomDrag = 0.95; -const float GLTFViewerOrbitCameraRotationDrag = 0.6667; -const float GLTFViewerOrbitCameraZoomSensitivity = 2; - -using namespace maplibre::gltf; - -Camera::Camera() { - _rotationAngles = 0; - _rotationVelocity = 0; - _velocity = 0; - _distance = 4; // 0; // 2; -} - -simd_double4x4 Camera::projectionMatrix() { - float fov = M_PI / 3; // original - fov = 0.6435011087932844; // Constant that i found in ML - simd_double4x4 matrix = GLTFPerspectiveProjectionMatrixAspectFovRH(fov, 1.0, 0.01, 250); - return matrix; -} - -void Camera::updateWithTimestep(double timestep) { - _rotationAngles += _rotationVelocity * timestep; - - static double rot = 0; - // rot += 0.03; - // self.rotationAngles = rot; - // _rotationAngles = simd_make_float3(rot, M_PI/4.0, 0); - _rotationAngles = simd_make_float3(rot, 0, 0); - - // Clamp pitch - _rotationAngles = (simd_float3){ - _rotationAngles.x, static_cast(fmax(-M_PI_2, fmin(_rotationAngles.y, M_PI_2))), 0}; - - _rotationVelocity *= GLTFViewerOrbitCameraRotationDrag; - - // _distance += _velocity * timestep; - _velocity *= GLTFViewerOrbitCameraZoomDrag; - - simd_double4x4 pitchRotation = GLTFRotationMatrixFromAxisAngleD(GLTFAxisXD, -_rotationAngles.y); - simd_double4x4 yawRotation = GLTFRotationMatrixFromAxisAngleD(GLTFAxisYD, -_rotationAngles.x); - simd_double4x4 translation = GLTFMatrixFromTranslationD((simd_double3){0, 0, _distance}); - _viewMatrix = matrix_invert(matrix_multiply(matrix_multiply(yawRotation, pitchRotation), translation)); -} diff --git a/platform/darwin/src/gltf/Camera.hpp b/platform/darwin/src/gltf/Camera.hpp deleted file mode 100644 index 89f760c7e035..000000000000 --- a/platform/darwin/src/gltf/Camera.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// -// Camera.hpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#ifndef Camera_hpp -#define Camera_hpp - -#include -#include - -namespace maplibre { -namespace gltf { - -class Camera { -public: - simd_float3 _rotationAngles; - simd_float3 _rotationVelocity; - double _velocity; - float _distance; - Camera(); - simd_double4x4 projectionMatrix(); - simd_double4x4 _viewMatrix; - void updateWithTimestep(double timestep); -}; - -} // namespace gltf -} // namespace maplibre - -#endif /* Camera_hpp */ diff --git a/platform/darwin/src/gltf/GLTFMTLRenderItem.h b/platform/darwin/src/gltf/GLTFMTLRenderItem.h deleted file mode 100644 index 68b0753b1a67..000000000000 --- a/platform/darwin/src/gltf/GLTFMTLRenderItem.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// GLTFMTLRenderItem.h -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#import -#import "gltfkit/GLTFMesh.h" -#import "gltfkit/GLTFNode.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface GLTFMTLRenderItem : NSObject -@property (nonatomic) NSString *label; -@property (nonatomic) GLTFNode *node; -@property (nonatomic, strong) GLTFSubmesh *submesh; -@property (nonatomic, assign) VertexUniforms vertexUniforms; -@property (nonatomic, assign) FragmentUniforms fragmentUniforms; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/GLTFMTLRenderItem.mm b/platform/darwin/src/gltf/GLTFMTLRenderItem.mm deleted file mode 100644 index 9f7ac94705cf..000000000000 --- a/platform/darwin/src/gltf/GLTFMTLRenderItem.mm +++ /dev/null @@ -1,12 +0,0 @@ -// -// GLTFMTLRenderItem.m -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#import "GLTFMTLRenderItem.h" - -@implementation GLTFMTLRenderItem - -@end diff --git a/platform/darwin/src/gltf/GLTFManager.hpp b/platform/darwin/src/gltf/GLTFManager.hpp deleted file mode 100644 index 9fce472cb1e2..000000000000 --- a/platform/darwin/src/gltf/GLTFManager.hpp +++ /dev/null @@ -1,106 +0,0 @@ -// -// GLTFManager.hpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#ifndef GLTFManager_hpp -#define GLTFManager_hpp - -#include -#include -#include -#include -#include -#include "GLTFRenderer.hpp" -#include "GLTFModel.hpp" -#include "GLTFManagerRenderingEnvironment.hpp" - -namespace maplibre { -namespace gltf { - -// The type of rendering environment we're in -typedef enum { - RenderingEnvironmentUnknown, - RenderingEnvironmentMetal, - RenderingEnvironmentOpenGL, - RenderingEnvironmentVulkan -} RenderingEnvironment; - -struct Coordinate2D { - double _lat; - double _lon; -}; - -struct Cartesian3D { - double _x; - double _y; - double _z; -}; - -typedef std::function ProjectionCallback; - -// The GLTF Manager class is the top level entry point -// for all things model based -class GLTFManager { -public: - // Set the callback - void setProjectionCallback(ProjectionCallback projectionCallback); - - // Instantiate the manager with the appropriate environment - GLTFManager(RenderingEnvironment renderingEnvironment); - - // Load a model - void addModel(std::shared_ptr model); - - // Remove a model - void removeModel(std::shared_ptr model); - - // Current meter to screen pixel scale - double _metersPerPixel = 1.0; - - // Set the drawable size - void setDrawableSize(int width, int height); - - // Set the tilt deg - void setTiltDeg(double tiltDeg); - - // Set the rotation deg - void setRotationDeg(double rotationDeg); - - // Set the rendering environment variables - void setRenderingEnvironmentVariables(std::shared_ptr environmentVars); - - // Update any animations - void updateScene(float timeSinceLastDraw); - - // Render - void render(); - -private: - RenderingEnvironment _renderingEnvironment = RenderingEnvironmentUnknown; - - // List of models - std::vector> _models; - - // Projection callback - ProjectionCallback _projectionCallback; - -private: - // Rendering environment - void createRenderingEnvironment(); - - // The renderer - std::shared_ptr _renderer = nullptr; - - int _drawableWidth = 1; - int _drawableHeight = 1; - double _tiltDeg = 0; - double _rotationDeg = 0; -}; - -} // namespace gltf -} // namespace maplibre - -#endif /* GLTFManager_hpp */ diff --git a/platform/darwin/src/gltf/GLTFManager.mm b/platform/darwin/src/gltf/GLTFManager.mm deleted file mode 100644 index 7a3936a53668..000000000000 --- a/platform/darwin/src/gltf/GLTFManager.mm +++ /dev/null @@ -1,170 +0,0 @@ -// -// GLTFManager.cpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#include "GLTFManager.hpp" -#include "MetalRenderer.hpp" -#include "GLTFManagerRenderingEnvironmentMetal.hpp" -#include - -using namespace maplibre::gltf; - -// Set the callback -void GLTFManager::setProjectionCallback(ProjectionCallback projectionCallback) { - _projectionCallback = projectionCallback; -} - -// Instantiate the manager with the appropriate environment -GLTFManager::GLTFManager(RenderingEnvironment renderingEnvironment) { - _renderingEnvironment = renderingEnvironment; - createRenderingEnvironment(); -} - -// Load a model -void GLTFManager::addModel(std::shared_ptr model) { - - _models.push_back(model); - if (_renderer != nullptr) { - _renderer->loadGLTFModel(model); - } - - - -} - -// Remove a model -void GLTFManager::removeModel(std::shared_ptr model) { - - _models.erase(std::find(_models.begin(), _models.end(), model)); - -} - -// Set the drawable size -void GLTFManager::setDrawableSize(int width, int height) { - - _drawableWidth = width; - _drawableHeight = height; - - if (_renderer != nullptr) { - _renderer->setDrawableSize(_drawableWidth, _drawableHeight); - } - -} - - -// Set the tilt deg -void GLTFManager::setTiltDeg(double tiltDeg) { - - _tiltDeg = tiltDeg; - if (_renderer != nullptr) { - _renderer->setTiltDeg(_tiltDeg); - } - -} - - -// Set the rotation deg -void GLTFManager::setRotationDeg(double rotationDeg) { - - _rotationDeg = rotationDeg; - if (_renderer != nullptr) { - _renderer->setRotationDeg(_rotationDeg); - } -} - - - -// Set the rendering environment variables -void GLTFManager::setRenderingEnvironmentVariables(std::shared_ptr environmentVars) { - - if (_renderingEnvironment == RenderingEnvironmentMetal) { - - if (_renderer != nullptr) { - - // Set metal specific stuff - auto mr = std::static_pointer_cast(_renderer); - auto mevars = std::static_pointer_cast(environmentVars); - mr->setMetalDevice(mevars->_metalDevice); - //mr->setCurrentDrawable(mevars->_currentDrawable); - //mr->setCurrentOutputRenderPassDescriptor(mevars->_currentRenderPassDescriptor); - - // TODO: Add depth buffer variable management - - // TODO: Add bloom pass toggle - mr->setUseBloomPass(mevars->_useBloomPass); - - // TODO: Remove all the above and use this instead - mr->setRenderingEnvironemnt(environmentVars); - - - } - - } - -} - - -// Update any animations -void GLTFManager::updateScene(float timeSinceLastDraw) { - if (_renderer == nullptr) { - return; - } - - // Go through all the models and project them. This is a - // hack right now to try and sync the models with the scene - if (_projectionCallback != nullptr) { - - for (auto m: _models) { - Coordinate2D c; - c._lat = m->_referenceLat; - c._lon = m->_referenceLon; - - - - auto cartesian = _projectionCallback(c); - m->_xLateX = cartesian._x; - m->_xLateY = cartesian._y; - m->_xLateZ = cartesian._z; - - } - - } - - - _renderer->setMetersPerPixel(_metersPerPixel); - _renderer->update(timeSinceLastDraw); -} - -// Render -void GLTFManager::render() { - if (_renderer == nullptr) { - return; - } - _renderer->render(); -} - - - -void GLTFManager::createRenderingEnvironment() { - - if (_renderingEnvironment == RenderingEnvironmentMetal) { - - // Create the renderer - _renderer = std::make_shared(); - - // Set the drawable size - _renderer->setDrawableSize(_drawableWidth, _drawableHeight); - - // Set the initial tilt deg - _renderer->setTiltDeg(_tiltDeg); - - // Set metal specific stuff - auto mr = std::static_pointer_cast(_renderer); - - - } - -} diff --git a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp deleted file mode 100644 index 1e37c11260ce..000000000000 --- a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// GLTFManagerRenderingEnvironment.hpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#ifndef GLTFManagerRenderingEnvironment_hpp -#define GLTFManagerRenderingEnvironment_hpp - -#include -#include - -namespace maplibre { -namespace gltf { - -// Bsae class does nothing really, just a place holder -class GLTFManagerRenderingEnvironment { -public: - // If the bloom should be used - bool _useBloomPass = false; - - // FOV - double _currentFOVDEG = 50; - - // Environment projection matrix - simd_double4x4 _currentProjectionMatrix; - - // Current zoom level - double _currentZoomLevel = 1; - - // - simd_float3 _lightDirection; - - GLTFManagerRenderingEnvironment() { _lightDirection = simd_make_float3(0.0, 10000.0, 10000.0); } -}; - -} // namespace gltf -} // namespace maplibre -#endif /* GLTFManagerRenderingEnvironment_hpp */ diff --git a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.mm b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.mm deleted file mode 100644 index c372f7608b8d..000000000000 --- a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.mm +++ /dev/null @@ -1,8 +0,0 @@ -// -// GLTFManagerRenderingEnvironment.cpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#include "GLTFManagerRenderingEnvironment.hpp" diff --git a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp deleted file mode 100644 index b64b422bf6bd..000000000000 --- a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// -// GLTFManagerRenderingEnvironmentMetal.hpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#ifndef GLTFManagerRenderingEnvironmentMetal_hpp -#define GLTFManagerRenderingEnvironmentMetal_hpp - -#include -#include -#include -#include "GLTFManagerRenderingEnvironment.hpp" - -namespace maplibre { -namespace gltf { - -// Bsae class does nothing really, just a place holder -class GLTFManagerRenderingEnvironmentMetal : public GLTFManagerRenderingEnvironment { -public: - // Allows command buffer and render encoder to be passed in. - // if these are nil, then the renderer will create them - id _currentCommandEncoder = nullptr; - id _currentCommandBuffer = nullptr; - - id _currentDrawable = nullptr; - MTLRenderPassDescriptor *_currentRenderPassDescriptor = nullptr; - id _metalDevice = nullptr; - - // TBD: These are placeholders as we noodle how to integrate with ML - // Depth descriptor: If this is null, then use an internal depth - id _depthStencilTexture = nullptr; - - id _colorTexture = nullptr; -}; - -} // namespace gltf -} // namespace maplibre - -#endif /* GLTFManagerRenderingEnvironmentMetal_hpp */ diff --git a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.mm b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.mm deleted file mode 100644 index fd35693ae6bb..000000000000 --- a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.mm +++ /dev/null @@ -1,8 +0,0 @@ -// -// GLTFManagerRenderingEnvironmentMetal.cpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#include "GLTFManagerRenderingEnvironmentMetal.hpp" diff --git a/platform/darwin/src/gltf/GLTFMath.cpp b/platform/darwin/src/gltf/GLTFMath.cpp deleted file mode 100644 index 8a067505ef5d..000000000000 --- a/platform/darwin/src/gltf/GLTFMath.cpp +++ /dev/null @@ -1,192 +0,0 @@ -// -// Math.cpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#include "GLTFMath.hpp" - -simd_float4x4 GLTFMatrixFromScale(const simd_float3 s) { - simd_float4x4 m = matrix_identity_float4x4; - m.columns[0].x = s.x; - m.columns[1].y = s.y; - m.columns[2].z = s.z; - return m; -} - -simd_double4x4 GLTFMatrixFromScaleD(const simd_double3 s) { - simd_double4x4 m = matrix_identity_double4x4; - m.columns[0].x = s.x; - m.columns[1].y = s.y; - m.columns[2].z = s.z; - return m; -} - -simd_float4x4 GLTFMatrixFromUniformScale(float s) { - simd_float4x4 m = matrix_identity_float4x4; - m.columns[0].x = s; - m.columns[1].y = s; - m.columns[2].z = s; - return m; -} - -simd_double4x4 GLTFMatrixFromUniformScaleD(double s) { - simd_double4x4 m = matrix_identity_double4x4; - m.columns[0].x = s; - m.columns[1].y = s; - m.columns[2].z = s; - return m; -} - -simd_double4x4 GLTFMatrixFromTranslationD(simd_double3 t) { - simd_double4x4 m = matrix_identity_double4x4; - m.columns[3] = (simd_double4){t.x, t.y, t.z, 1.0}; - return m; -} - -simd_float4x4 GLTFMatrixFromTranslation(simd_float3 t) { - simd_float4x4 m = matrix_identity_float4x4; - m.columns[3] = (simd_float4){t.x, t.y, t.z, 1.0}; - return m; -} - -GLTFBoundingSphere GLTFBoundingSphereFromBox(const GLTFBoundingBox b) { - GLTFBoundingSphere s; - double midX = (b.maxPoint.x + b.minPoint.x) * 0.5; - double midY = (b.maxPoint.y + b.minPoint.y) * 0.5; - double midZ = (b.maxPoint.z + b.minPoint.z) * 0.5; - - double r = sqrt(pow(b.maxPoint.x - midX, 2) + pow(b.maxPoint.y - midY, 2) + pow(b.maxPoint.z - midZ, 2)); - - s.center = (simd_double3){midX, midY, midZ}; - s.radius = r; - return s; -} - -simd_float4x4 GLTFRotationMatrixFromAxisAngle(simd_float3 axis, float angle) { - float x = axis.x, y = axis.y, z = axis.z; - float c = cosf(angle); - float s = sinf(angle); - float t = 1 - c; - - simd_float4 c0 = {t * x * x + c, t * x * y + z * s, t * x * z - y * s, 0}; - simd_float4 c1 = {t * x * y - z * s, t * y * y + c, t * y * z + x * s, 0}; - simd_float4 c2 = {t * x * z + y * s, t * y * z - x * s, t * z * z + c, 0}; - simd_float4 c3 = {0, 0, 0, 1}; - - return (simd_float4x4){c0, c1, c2, c3}; -} - -simd_double4x4 GLTFRotationMatrixFromAxisAngleD(simd_double3 axis, double angle) { - double x = axis.x, y = axis.y, z = axis.z; - double c = cos(angle); - double s = sin(angle); - double t = 1 - c; - - simd_double4 c0 = {t * x * x + c, t * x * y + z * s, t * x * z - y * s, 0}; - simd_double4 c1 = {t * x * y - z * s, t * y * y + c, t * y * z + x * s, 0}; - simd_double4 c2 = {t * x * z + y * s, t * y * z - x * s, t * z * z + c, 0}; - simd_double4 c3 = {0, 0, 0, 1}; - - return (simd_double4x4){c0, c1, c2, c3}; -} - -simd_float3 GLTFAxisX = (simd_float3){1, 0, 0}; -simd_float3 GLTFAxisY = (simd_float3){0, 1, 0}; -simd_float3 GLTFAxisZ = (simd_float3){0, 0, 1}; - -simd_double3 GLTFAxisXD = (simd_double3){1, 0, 0}; -simd_double3 GLTFAxisYD = (simd_double3){0, 1, 0}; -simd_double3 GLTFAxisZD = (simd_double3){0, 0, 1}; - -simd_double4x4 GLTFPerspectiveProjectionMatrixAspectFovRH(const double fovY, - const double aspect, - const double nearZ, - const double farZ) { - double yscale = 1 / tanf(fovY * 0.5f); // 1 / tan == cot - double xscale = yscale / aspect; - double q = -farZ / (farZ - nearZ); - - simd_double4x4 m = {.columns[0] = {xscale, 0, 0, 0}, - .columns[1] = {0, yscale, 0, 0}, - .columns[2] = {0, 0, q, -1}, - .columns[3] = {0, 0, q * nearZ, 0}}; - - return m; -} - -simd_float4x4 GLTFOrthoProjectionMatrix( - const float left, const float right, const float bottom, const float top, const float nearZ, const float farZ) { - simd_float4x4 m = { - .columns[0] = {2 / (right - left), 0, 0, 0}, - .columns[1] = {0, 2 / (top - bottom), 0, 0}, - .columns[2] = {0, 0, 1 / (farZ - nearZ), 0}, - .columns[3] = {(left + right) / (left - right), (top + bottom) / (bottom - top), nearZ / (nearZ - farZ), 1}}; - - return m; -} - -simd_float3x3 GLTFMatrixUpperLeft3x3(simd_float4x4 m) { - simd_float3x3 mout = {{{m.columns[0][0], m.columns[0][1], m.columns[0][2]}, - {m.columns[1][0], m.columns[1][1], m.columns[1][2]}, - {m.columns[2][0], m.columns[2][1], m.columns[2][2]}}}; - return mout; -} - -simd_double3x3 GLTFMatrixUpperLeft3x3D(simd_double4x4 m) { - simd_double3x3 mout = {{{m.columns[0][0], m.columns[0][1], m.columns[0][2]}, - {m.columns[1][0], m.columns[1][1], m.columns[1][2]}, - {m.columns[2][0], m.columns[2][1], m.columns[2][2]}}}; - return mout; -} - -GLTFTextureTransform GLTFTextureTransformMakeIdentity(void) { - GLTFTextureTransform t = { - .offset = (simd_float2){0, 0}, - .scale = (simd_float2){1, 1}, - .rotation = 0, - }; - return t; -} - -GLTFTextureTransform GLTFTextureTransformMakeSRT(simd_float2 scale, float rotation, simd_float2 offset) { - GLTFTextureTransform t = { - .offset = offset, - .scale = scale, - .rotation = rotation, - }; - return t; -} - -simd_float3x3 GLTFTextureMatrixFromTransform(GLTFTextureTransform transform) { - float rs = sinf(-transform.rotation); - float rc = cosf(-transform.rotation); - float tx = transform.offset.x; - float ty = transform.offset.y; - float sx = transform.scale.x; - float sy = transform.scale.y; - simd_float3 c0 = (simd_float3){rc * sx, rs * sy, 0}; - simd_float3 c1 = (simd_float3){-rs * sx, rc * sy, 0}; - simd_float3 c2 = (simd_float3){tx, ty, 1}; - simd_float3x3 m = (simd_float3x3){c0, c1, c2}; - return m; -} - -simd_float4x4 GLTFNormalMatrixFromModelMatrix(simd_float4x4 m) { - simd_float3x3 nm = simd_inverse(simd_transpose(GLTFMatrixUpperLeft3x3(m))); - simd_float4x4 mout = {{{nm.columns[0][0], nm.columns[0][1], nm.columns[0][2], 0}, - {nm.columns[1][0], nm.columns[1][1], nm.columns[1][2], 0}, - {nm.columns[2][0], nm.columns[2][1], nm.columns[2][2], 0}, - {0, 0, 0, 1}}}; - return mout; -} - -simd_double4x4 GLTFNormalMatrixFromModelMatrixD(simd_double4x4 m) { - simd_double3x3 nm = simd_inverse(simd_transpose(GLTFMatrixUpperLeft3x3D(m))); - simd_double4x4 mout = {{{nm.columns[0][0], nm.columns[0][1], nm.columns[0][2], 0}, - {nm.columns[1][0], nm.columns[1][1], nm.columns[1][2], 0}, - {nm.columns[2][0], nm.columns[2][1], nm.columns[2][2], 0}, - {0, 0, 0, 1}}}; - return mout; -} diff --git a/platform/darwin/src/gltf/GLTFMath.hpp b/platform/darwin/src/gltf/GLTFMath.hpp deleted file mode 100644 index 6e8ce7a4f397..000000000000 --- a/platform/darwin/src/gltf/GLTFMath.hpp +++ /dev/null @@ -1,139 +0,0 @@ -// -// Math.hpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#ifndef Math_hpp -#define Math_hpp - -#include -#include - -typedef enum { - GLTFTextureBindIndexBaseColor, - GLTFTextureBindIndexNormal, - GLTFTextureBindIndexMetallicRoughness, - GLTFTextureBindIndexOcclusion, - GLTFTextureBindIndexEmissive, - GLTFTextureBindIndexDiffuseEnvironment, - GLTFTextureBindIndexSpecularEnvironment, - GLTFTextureBindIndexBRDFLookup, -} GLTFMTLTextureBindIndex; - -#define DEG_RAD (M_PI / 180.0) -#define RAD_DEG (180.0 / M_PI) - -// 0.0174533 -// 57.2958 - -#define GLTFMTLMaximumLightCount 3 -#define GLTFMTLMaximumTextureCount (GLTFTextureBindIndexEmissive + 1) - -typedef struct { - simd_float3 minPoint; - simd_float3 maxPoint; -} GLTFBoundingBox; - -typedef struct { - simd_double3 center; - float radius; -} GLTFBoundingSphere; - -typedef struct { - simd_float4x4 modelMatrix; - simd_float4x4 modelViewProjectionMatrix; - simd_float4x4 normalMatrix; - float scaleFactor; - float brightness; - simd_float3 lightDirection; -} VertexUniforms; - -typedef struct { - simd_float4 position; - simd_float4 color; - float intensity; - float innerConeAngle; - float outerConeAngle; - float range; - simd_float4 spotDirection; -} Light; - -typedef struct { - float normalScale; - simd_float3 emissiveFactor; - float occlusionStrength; - simd_float2 metallicRoughnessValues; - simd_float4 baseColorFactor; - simd_float3 camera; - float alphaCutoff; - float envIntensity; - Light ambientLight; - Light lights[GLTFMTLMaximumLightCount]; - simd_float3x3 textureMatrices[GLTFMTLMaximumTextureCount]; -} FragmentUniforms; - -typedef struct { - simd_float2 offset; - simd_float2 scale; - float rotation; -} GLTFTextureTransform; - -#ifdef __cplusplus -extern "C" { -#endif - -extern simd_float3 GLTFAxisX; -extern simd_float3 GLTFAxisY; -extern simd_float3 GLTFAxisZ; - -extern simd_double3 GLTFAxisXD; -extern simd_double3 GLTFAxisYD; -extern simd_double3 GLTFAxisZD; - -simd_float4x4 GLTFMatrixFromScale(const simd_float3 s); - -simd_double4x4 GLTFMatrixFromScaleD(const simd_double3 s); - -simd_float4x4 GLTFMatrixFromUniformScale(float s); - -simd_double4x4 GLTFMatrixFromUniformScaleD(double s); - -GLTFBoundingSphere GLTFBoundingSphereFromBox(GLTFBoundingBox b); - -simd_float4x4 GLTFMatrixFromTranslation(simd_float3 t); - -simd_double4x4 GLTFMatrixFromTranslationD(simd_double3 t); - -simd_float4x4 GLTFRotationMatrixFromAxisAngle(simd_float3 axis, float angle); - -simd_double4x4 GLTFRotationMatrixFromAxisAngleD(simd_double3 axis, double angle); - -simd_double4x4 GLTFPerspectiveProjectionMatrixAspectFovRH(const double fovY, - const double aspect, - const double nearZ, - const double farZ); - -simd_float4x4 GLTFOrthoProjectionMatrix( - const float left, const float right, const float bottom, const float top, const float nearZ, const float farZ); - -simd_float3x3 GLTFMatrixUpperLeft3x3(simd_float4x4 m); - -simd_double3x3 GLTFMatrixUpperLeft3x3D(simd_double4x4 m); - -GLTFTextureTransform GLTFTextureTransformMakeIdentity(void); - -GLTFTextureTransform GLTFTextureTransformMakeSRT(simd_float2 scale, float rotation, simd_float2 offset); - -simd_float3x3 GLTFTextureMatrixFromTransform(GLTFTextureTransform transform); - -simd_float4x4 GLTFNormalMatrixFromModelMatrix(simd_float4x4 m); - -simd_double4x4 GLTFNormalMatrixFromModelMatrixD(simd_double4x4 m); - -#ifdef __cplusplus -} -#endif - -#endif /* Math_hpp */ diff --git a/platform/darwin/src/gltf/GLTFModel.cpp b/platform/darwin/src/gltf/GLTFModel.cpp deleted file mode 100644 index 4d97152eff71..000000000000 --- a/platform/darwin/src/gltf/GLTFModel.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// -// GLTFModel.cpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#include "GLTFModel.hpp" diff --git a/platform/darwin/src/gltf/GLTFModel.hpp b/platform/darwin/src/gltf/GLTFModel.hpp deleted file mode 100644 index 174b7dd91ee3..000000000000 --- a/platform/darwin/src/gltf/GLTFModel.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// GLTFModel.hpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#ifndef GLTFModel_hpp -#define GLTFModel_hpp - -#include -#include - -namespace maplibre { -namespace gltf { - -// Model -class GLTFModel { -public: - // - double _referenceLat = 0; - double _referenceLon = 0; - - // What it takes to scale this model to meters units - float _scaleFactor = 1; - - // Rotation around the reference point - float _rotationDeg = 0; - - // The URL for the model, used by the loader - std::string _modelURL; - - // The brightness - float _brightness = 1.0; - - // This is a hack to deal with passing in the translation vector. - // NEed to reconcile this with the renderable model's version of it - double _xLateX = 0; - double _xLateY = 0; - double _xLateZ = 0; -}; - -} // namespace gltf -} // namespace maplibre - -#endif /* GLTFModel_hpp */ diff --git a/platform/darwin/src/gltf/GLTFModelLayer.h b/platform/darwin/src/gltf/GLTFModelLayer.h deleted file mode 100644 index 640f37355659..000000000000 --- a/platform/darwin/src/gltf/GLTFModelLayer.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// CustomLayerTest.h -// MapLibreTest -// -// Created by Malcolm Toon on 11/7/24. -// - -#import "MLNCustomStyleLayer.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface GLTFModelLayer : MLNCustomStyleLayer - -// This sets the relative light position for all the models being rendered -// The light position is in meters from the origin of the model. -- (void)setLightPositionX:(float)x y:(float)y z:(float)z; - -- (void)loadModelFromJSON:(NSString *)modelMetadataFilename; - -- (void)loadModel:(NSString *)appResourceFilename - lat:(double)lat - lon:(double)lon - rotationDeg:(double)rotationDeg - scaleFactor:(float)scaleFactor - brightness:(float)brightness; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/GLTFModelLayer.mm b/platform/darwin/src/gltf/GLTFModelLayer.mm deleted file mode 100644 index b71972d27d46..000000000000 --- a/platform/darwin/src/gltf/GLTFModelLayer.mm +++ /dev/null @@ -1,357 +0,0 @@ -// -// CustomLayerTest.m -// MapLibreTest -// -// Created by Malcolm Toon on 11/6/24. -// - -#import "GLTFModelLayer.h" -#import -#import "MLNBackendResource.h" -#import "MLNMapView.h" -#include -#import "GLTFManagerRenderingEnvironmentMetal.hpp" -#import "GLTFManager.hpp" -#import "GLTFMath.hpp" - -using namespace maplibre::gltf; - -// This is here to hold the metadata about the model if load is called before -// the layer is created -@interface GLTFModelMetadata : NSObject -@property NSString *modelPath; -@property CLLocationCoordinate2D modelCoordinate; -@property double modelRotation; -@property BOOL modelLoaded; -@property float modelScale; -@property float brightness; - -@end - -@implementation GLTFModelMetadata --(id)init { - if (self = [super init]) { - self.brightness = 1.0; - } - return self; -} -@end - -@interface GLTFModelLayer () { - std::shared_ptr _metalEnvironment; - std::shared_ptr _manager; - -} - -@property NSMutableArray *models; -@property BOOL managerCreated; - -// Would be nice to change this to a vec3 or something similar at some point -@property BOOL lightSet; -@property float lightX; -@property float lightY; -@property float lightZ; - - -@end - -simd_float4x4 toSimdMatrix4F(const MLNMatrix4 & mlMatrix) { - simd_float4x4 tempResult; - - /* - typedef struct MLNMatrix4 { - double m00, m01, m02, m03; - double m10, m11, m12, m13; - double m20, m21, m22, m23; - double m30, m31, m32, m33; - } MLNMatrix4; -*/ - - tempResult.columns[0][0] = mlMatrix.m00; - tempResult.columns[0][1] = mlMatrix.m01; - tempResult.columns[0][2] = mlMatrix.m02; - tempResult.columns[0][3] = mlMatrix.m03; - tempResult.columns[1][0] = mlMatrix.m10; - tempResult.columns[1][1] = mlMatrix.m11; - tempResult.columns[1][2] = mlMatrix.m12; - tempResult.columns[1][3] = mlMatrix.m13; - tempResult.columns[2][0] = mlMatrix.m20; - tempResult.columns[2][1] = mlMatrix.m21; - tempResult.columns[2][2] = mlMatrix.m22; - tempResult.columns[2][3] = mlMatrix.m23; - tempResult.columns[3][0] = mlMatrix.m30; - tempResult.columns[3][1] = mlMatrix.m31; - tempResult.columns[3][2] = mlMatrix.m32; - tempResult.columns[3][3] = mlMatrix.m33; - - - return tempResult; -} - - - -simd_double4x4 toSimdMatrix4D(const MLNMatrix4 & mlMatrix) { - simd_double4x4 tempResult; - - /* - typedef struct MLNMatrix4 { - double m00, m01, m02, m03; - double m10, m11, m12, m13; - double m20, m21, m22, m23; - double m30, m31, m32, m33; - } MLNMatrix4; -*/ - - tempResult.columns[0][0] = mlMatrix.m00; - tempResult.columns[0][1] = mlMatrix.m01; - tempResult.columns[0][2] = mlMatrix.m02; - tempResult.columns[0][3] = mlMatrix.m03; - tempResult.columns[1][0] = mlMatrix.m10; - tempResult.columns[1][1] = mlMatrix.m11; - tempResult.columns[1][2] = mlMatrix.m12; - tempResult.columns[1][3] = mlMatrix.m13; - tempResult.columns[2][0] = mlMatrix.m20; - tempResult.columns[2][1] = mlMatrix.m21; - tempResult.columns[2][2] = mlMatrix.m22; - tempResult.columns[2][3] = mlMatrix.m23; - tempResult.columns[3][0] = mlMatrix.m30; - tempResult.columns[3][1] = mlMatrix.m31; - tempResult.columns[3][2] = mlMatrix.m32; - tempResult.columns[3][3] = mlMatrix.m33; - - - return tempResult; -} - -@implementation GLTFModelLayer { - // The render pipeline state - id _pipelineState; - id _depthStencilStateWithoutStencil; -} - --(id)initWithIdentifier:(NSString *)identifier { - if (self = [super initWithIdentifier:identifier]) { - self.models = [NSMutableArray array]; - } - return self; -} - -- (void)didMoveToMapView:(MLNMapView *)mapView { - -} - -// This sets the relative light position for all the models being rendered -// The light position is in meters from the origin of the model. --(void)setLightPositionX:(float)x y:(float)y z:(float)z { - - self.lightSet = YES; - self.lightX = x; - self.lightY = y; - self.lightZ = z; - - if (_metalEnvironment != nullptr) { - _metalEnvironment->_lightDirection = simd_make_float3(_lightX, _lightY, _lightZ); - } - -} - - --(void)loadModels { - - // This goes through the model array and loads whatever hasn't been loaded already - for (GLTFModelMetadata *m in self.models) { - [self addModel:m]; - } - - /* - @{@"modelURL":@"al_awwal_v02.glb",@"lat":@(24.729326775575686),@"lon":@(46.623841518553355),@"rot":@(0)}, - @{@"modelURL":@"alawwalpark-03.glb",@"lat":@(24.729326775575686),@"lon":@(46.623841518553355),@"rot":@(0)}, - @{@"modelURL":@"Al_faisaliyah_005.glb",@"lat":@(24.69052042910012),@"lon":@(46.6856124145449),@"rot":@(0)}, - @{@"modelURL":@"Al_faisaliyah_007.glb",@"lat":@(24.69052042910012),@"lon":@(46.6856124145449),@"rot":@(0)}, - @{@"modelURL":@"alnajdoul_004.glb",@"lat":@(24.739367517042293),@"lon":@(46.65956858776968),@"rot":@(0)}, - @{@"modelURL":@"masmak_010-bl.glb",@"lat":@(24.63125410132941),@"lon":@(46.713372982335976),@"rot":@(0)}, - @{@"modelURL":@"turaif-03-bl.glb",@"lat":@(24.733690223733547),@"lon":@(46.57492745287205),@"rot":@(0)}, - @{@"modelURL":@"tvtower_009.glb",@"lat":@(24.643391710253425),@"lon":@(46.69595652756665),@"rot":@(0)}, -*/ - - //[self loadModel:@"alawwalpark-03.glb" lat:24.729326775575686 lon:46.623841518553355 rotationDeg:90]; - /* - [self loadModel:@"Al_faisaliyah_007.glb" lat:24.69052042910012 lon:46.6856124145449 rotationDeg:-65]; - [self loadModel:@"alnajdoul_004.glb" lat:24.739367517042293 lon:46.65956858776968 rotationDeg:25]; - [self loadModel:@"masmak_010-bl.glb" lat:24.63125410132941 lon:46.713372982335976 rotationDeg:0]; - [self loadModel:@"turaif-03-bl.glb" lat:24.733690223733547 lon:46.57492745287205 rotationDeg:0]; - [self loadModel:@"tvtower_009.glb" lat:24.643391710253425 lon:46.69595652756665 rotationDeg:0]; - - - [self loadModel:@"KAFD_Building01_v01.glb" lat:24.76592011755998 lon:46.64337787824368 rotationDeg:0]; - [self loadModel:@"KAFD_Building02_v01.glb" lat:24.76592011755998 lon:46.64337787824368 rotationDeg:0]; - [self loadModel:@"KAFD_Building06_v02.glb" lat:24.76592011755998 lon:46.64337787824368 rotationDeg:0]; - [self loadModel:@"KAFD_Building07_v01.glb" lat:24.76592011755998 lon:46.64337787824368 rotationDeg:0]; - [self loadModel:@"KAFD_Building09_v01.glb" lat:24.76592011755998 lon:46.64337787824368 rotationDeg:0]; -*/ - -} - --(void)loadModelFromJSON:(NSString *)modelMetadataFilename { - - NSError *error = nil; - NSData *dat = [NSData dataWithContentsOfFile:modelMetadataFilename]; - NSDictionary *d = [NSJSONSerialization JSONObjectWithData:dat - options:0 - error:&error]; - NSArray *models = [d objectForKey:@"models"]; - for (NSDictionary *model in models) { - - NSString *modelFilename = [model objectForKey:@"name"]; - double lat = [[model objectForKey:@"lat"] doubleValue]; - double lon = [[model objectForKey:@"lon"] doubleValue]; - double rot = [[model objectForKey:@"rot"] doubleValue]; - double scale = [[model objectForKey:@"scale_factor"] doubleValue]; - double brightnessCoefficient = [[model objectForKey:@"brightness"] doubleValue]; - if (brightnessCoefficient == 0) { - brightnessCoefficient = 1.0; - } - //NSString *bundleFilename = [[NSBundle mainBundle] pathForResource:modelFilename ofType:nil]; - [self loadModel:modelFilename - lat:lat - lon:lon - rotationDeg:rot - scaleFactor:scale - brightness:brightnessCoefficient]; - } - -} - - --(void)loadModel:(NSString *)appResourceFilename - lat:(double)lat - lon:(double)lon - rotationDeg:(double)rotationDeg - scaleFactor:(float)scaleFactor - brightness:(float)brightness { - - if (brightness == 0) { - brightness = 1.0; - } - - GLTFModelMetadata *modelMetadata = [[GLTFModelMetadata alloc] init]; - modelMetadata.modelPath = appResourceFilename; - modelMetadata.modelCoordinate = CLLocationCoordinate2DMake(lat, lon); - modelMetadata.modelRotation = -rotationDeg; - modelMetadata.modelScale = scaleFactor; - modelMetadata.brightness = brightness; - - [self.models addObject:modelMetadata]; - - if (self.managerCreated) { - [self addModel:modelMetadata]; - } - -} - - - --(void)addModel:(GLTFModelMetadata *)modelMetadata { - - if (modelMetadata.modelLoaded) { - return; - } - - NSURL *fileURL = [[NSBundle mainBundle] URLForResource:modelMetadata.modelPath withExtension:nil]; - - std::string modelURL = [[fileURL absoluteString] UTF8String]; - - std::shared_ptr model = std::make_shared(); - model->_referenceLat = modelMetadata.modelCoordinate.latitude; - model->_referenceLon = modelMetadata.modelCoordinate.longitude; - model->_modelURL = modelURL; - model->_rotationDeg = modelMetadata.modelRotation; - model->_brightness = modelMetadata.brightness; - model->_scaleFactor = modelMetadata.modelScale; -// model->_scaleFactor = 1.0; // Models are in meters - - _manager->addModel(model); - - modelMetadata.modelLoaded = YES; - -} - - -- (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingContext)context { - - MLNBackendResource* resource = [mapView backendResource]; - - bool loadModels = false; - - if (_manager == nullptr) { - - // Setup the metal environment for the model rendering - _metalEnvironment = std::make_shared(); - - if (self.lightSet) { - _metalEnvironment->_lightDirection = simd_make_float3(_lightX, _lightY, _lightZ); - } - - // Create the GLTF Manager - _manager = std::make_shared(RenderingEnvironmentMetal); - _manager->setRenderingEnvironmentVariables(_metalEnvironment); - - _manager->setProjectionCallback(^Cartesian3D(const Coordinate2D & coordinate){ - Cartesian3D tempResult; - - tempResult._x = 5198170.102753558; - tempResult._y = 2832006.4886368043; - tempResult._z = 0; - - tempResult._x = coordinate._lon * DEG_RAD; - double lat = coordinate._lat * DEG_RAD; - tempResult._y = log((1.0f+sin(lat))/cos(lat)); - - double metersScale = 20037508.34; - tempResult._x = tempResult._x * metersScale / M_PI; - tempResult._y = tempResult._y * metersScale / M_PI; - return tempResult; - }); - - loadModels = true; - } - - _metalEnvironment->_currentFOVDEG = context.fieldOfView * RAD_DEG; - _metalEnvironment->_currentProjectionMatrix = toSimdMatrix4D(context.nearClippedProjMatrix); - _metalEnvironment->_currentZoomLevel = context.zoomLevel; - _metalEnvironment->_currentCommandEncoder = self.renderEncoder; - _metalEnvironment->_currentCommandBuffer = resource.commandBuffer; - _metalEnvironment->_metalDevice = resource.mtkView.device; - _metalEnvironment->_currentDrawable = resource.mtkView.currentDrawable; - _metalEnvironment->_currentRenderPassDescriptor = resource.mtkView.currentRenderPassDescriptor; - _metalEnvironment->_depthStencilTexture = resource.mtkView.currentRenderPassDescriptor.depthAttachment.texture; - _metalEnvironment->_colorTexture = resource.mtkView.currentRenderPassDescriptor.colorAttachments[0].texture; - - if (self.lightSet) { - _metalEnvironment->_lightDirection = simd_make_float3(_lightX, _lightY, _lightZ); - } - - // TODO: Remove this.. This is legacy - _manager->setRenderingEnvironmentVariables(_metalEnvironment); - - if (loadModels) { - [self loadModels]; - } - - vector_uint2 _viewportSize; - _viewportSize.x = resource.mtkView.drawableSize.width; - _viewportSize.y = resource.mtkView.drawableSize.height; - _manager->setDrawableSize(_viewportSize.x, _viewportSize.y); - - float timestep = (1 / 60.0f); - _manager->updateScene(timestep); - - // Render the image - _manager->render(); -} - -- (void)willMoveFromMapView:(MLNMapView *)mapView { - // Clean up -} - -@end diff --git a/platform/darwin/src/gltf/GLTFModelLoader.h b/platform/darwin/src/gltf/GLTFModelLoader.h deleted file mode 100644 index d1e3ab9d7874..000000000000 --- a/platform/darwin/src/gltf/GLTFModelLoader.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// GLTFModelLoader.h -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#import -#import "gltfkit/GLTFAsset.h" - -NS_ASSUME_NONNULL_BEGIN - -typedef void (^GLTFModelLoaderCompletionHandler)(GLTFAsset *asset); - -@interface GLTFModelLoader : NSObject - -- (void)loadURL:(NSURL *)assetURL - withCompletionHandler:(GLTFModelLoaderCompletionHandler)completionHandler - bufferAllocator:(id)bufferAllocator; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/GLTFModelLoader.mm b/platform/darwin/src/gltf/GLTFModelLoader.mm deleted file mode 100644 index 66aeba4ec862..000000000000 --- a/platform/darwin/src/gltf/GLTFModelLoader.mm +++ /dev/null @@ -1,74 +0,0 @@ -// -// GLTFModelLoader.m -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#import "GLTFModelLoader.h" -#import "gltfkit/GLTFAsset.h" -#import "gltfkit/GLTFMTLBufferAllocator.h" - -@interface GLTFModelLoader () { - -} - -@property GLTFModelLoaderCompletionHandler completionHandler; - -@end - -@implementation GLTFModelLoader - --(void)loadURL:(NSURL *)assetURL -withCompletionHandler:(GLTFModelLoaderCompletionHandler)completionHandler -bufferAllocator:(id)bufferAllocator { - - self.completionHandler = completionHandler; - [GLTFAsset loadAssetWithURL:assetURL - bufferAllocator:bufferAllocator - delegate:self]; - -} - - -- (void)assetWithURL:(nonnull NSURL *)assetURL didFailToLoadWithError:(nonnull NSError *)error { - NSLog(@"Asset load failed with error: %@", error); -} - -- (void)assetWithURL:(nonnull NSURL *)assetURL - didFinishLoading:(nonnull GLTFAsset *)asset { - dispatch_async(dispatch_get_main_queue(), ^{ - - if (self.completionHandler) { - self.completionHandler(asset); - } - self.completionHandler = nil; - - NSLog(@"INFO: Total live buffer allocation size after document load is %0.2f MB", ([GLTFMTLBufferAllocator liveAllocationSize] / (float)1e6)); - }); -} - -- (void)assetWithURL:(nonnull NSURL *)assetURL -requiresContentsOfURL:(nonnull NSURL *)url - completionHandler:(void (^)(NSData *_Nullable, NSError *_Nullable))completionHandler { - NSURLSessionDataTask *task = [GLTFModelLoader.urlSession dataTaskWithURL:url - completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) - { - completionHandler(data, error); - }]; - [task resume]; -} - -+ (NSURLSession *)urlSession { - static NSURLSession *_urlSession = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; - _urlSession = [NSURLSession sessionWithConfiguration:configuration]; - }); - return _urlSession; -} - - - -@end diff --git a/platform/darwin/src/gltf/GLTFRenderer.cpp b/platform/darwin/src/gltf/GLTFRenderer.cpp deleted file mode 100644 index c308e566f32d..000000000000 --- a/platform/darwin/src/gltf/GLTFRenderer.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// -// GLTFRenderer.cpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#include "GLTFRenderer.hpp" - -using namespace maplibre::gltf; - -GLTFRenderer::GLTFRenderer() { - _camera = std::make_unique(); -} - -// Destructor -GLTFRenderer::~GLTFRenderer() { - // Base class does nothing -} - -// Update any animations -void GLTFRenderer::update(float timeSinceLastDraw) { - // Base class does nothing -} - -// Render -void GLTFRenderer::render() { - // Base class does nothing -} - -// Set the drawable size -void GLTFRenderer::setDrawableSize(int width, int height) { - // Base class does nothing -} - -// Protected items -void GLTFRenderer::loadBloomPipelines() {} - -void GLTFRenderer::loadTonemapPipeline() {} - -void GLTFRenderer::updateFramebufferSize() {} - -// Load a model -void GLTFRenderer::loadGLTFModel(std::shared_ptr model) { - // Base class does nothing -} - -// Set the meters per pixel scale -void GLTFRenderer::setMetersPerPixel(double metersPerPixel) { - _metersPerPixel = metersPerPixel; -} - -// Set tilt -void GLTFRenderer::setTiltDeg(double tiltDeg) { - _tiltDeg = tiltDeg; -} - -// Set the rotation deg -void GLTFRenderer::setRotationDeg(double rotationDeg) { - _rotationDeg = rotationDeg; -} - -// Use bloom pass -void GLTFRenderer::setUseBloomPass(bool useBloomPass) { - _useBloomPass = useBloomPass; -} - -// Set the rendering environemnt variables -void GLTFRenderer::setRenderingEnvironemnt(std::shared_ptr renderingEnvironment) { - _renderingEnvironment = renderingEnvironment; -} diff --git a/platform/darwin/src/gltf/GLTFRenderer.hpp b/platform/darwin/src/gltf/GLTFRenderer.hpp deleted file mode 100644 index dba305678e60..000000000000 --- a/platform/darwin/src/gltf/GLTFRenderer.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// -// GLTFRenderer.hpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#ifndef GLTFRenderer_hpp -#define GLTFRenderer_hpp - -#include -#include "Camera.hpp" -#include "GLTFModel.hpp" -#include "GLTFManagerRenderingEnvironment.hpp" -#include - -namespace maplibre { -namespace gltf { - -class GLTFRenderer { -public: - // Constructor - GLTFRenderer(); - - // Destructor - virtual ~GLTFRenderer(); - - // Update any animations - virtual void update(float timeSinceLastDraw); - - // Render - virtual void render(); - - // Set the drawable size - virtual void setDrawableSize(int width, int height); - - // Load a model - virtual void loadGLTFModel(std::shared_ptr model); - - // Set the meters per pixel scale - void setMetersPerPixel(double metersPerPixel); - - // Set tilt - void setTiltDeg(double tiltDeg); - - // Set the rotation deg - void setRotationDeg(double rotationDeg); - - // Use bloom pass - void setUseBloomPass(bool useBloomPass); - - // Set the rendering environemnt variables - virtual void setRenderingEnvironemnt(std::shared_ptr renderingEnvironment); - -protected: - std::unique_ptr _camera = nullptr; - double _metersPerPixel = 1; - std::shared_ptr _renderingEnvironment = nullptr; - double _tiltDeg = 0; - double _rotationDeg = 0; - bool _useBloomPass = true; - virtual void loadBloomPipelines(); - virtual void loadTonemapPipeline(); - virtual void updateFramebufferSize(); -}; - -} // namespace gltf -} // namespace maplibre - -#endif /* GLTFRenderer_hpp */ diff --git a/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm b/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm deleted file mode 100644 index 89d169ef21a1..000000000000 --- a/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm +++ /dev/null @@ -1,561 +0,0 @@ -// -// Untitled.h -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#include "MetalRenderer.hpp" - - -#import "GLTFMath.hpp" -#import "gltfkit/GLTFScene.h" -#import "gltfkit/GLTFMesh.h" -#import "gltfkit/GLTFMaterial.h" -#import "gltfkit/GLTFKHRLight.h" -#import "gltfkit/GLTFMTLUtilities.h" -#import "gltfkit/GLTFSkin.h" -#import "gltfkit/GLTFMTLBufferAllocator.h" -#import "gltfkit/GLTFAccessor.h" -#import "gltfkit/GLTFBufferView.h" -#import "gltfkit/GLTFVertexDescriptor.h" - - - -using namespace maplibre::gltf; - -// Encapsulated in GLTFRenderer+GLTFAsset -void MetalRenderer::setGLTFAsset(GLTFAsset *asset, std::shared_ptr model) { - - _models.clear(); - addGLTFAsset(asset, model); - -// _asset = asset; -// if (_asset != nullptr) { -// computeRegularizationMatrix(); -// computeTransforms(); -// addDefaultLights(); -// } - - -} - -// -void MetalRenderer::addGLTFAsset(GLTFAsset *asset, std::shared_ptr model) { - - auto m = createRenderModel(asset, model); - _models.push_back(m); - -} - -std::shared_ptr MetalRenderer::createRenderModel(GLTFAsset *asset, std::shared_ptr model) { - - std::shared_ptr tempResult = std::make_shared(); - tempResult->_asset = asset; - tempResult->_gltfModel = model; - tempResult->_scaling = model->_scaleFactor; - tempResult->_brightness = model->_brightness; - - computeRegularizationMatrix(tempResult); - computeTransforms(tempResult); - addDefaultLights(tempResult); - - return tempResult; - -} - - - -void MetalRenderer::addDefaultLights(std::shared_ptr model) { -// GLTFNode *lightNode = [[GLTFNode alloc] init]; -// lightNode.translation = (simd_float3){ 0, 0, 1 }; -// lightNode.rotationQuaternion = simd_quaternion(1.0f, 0, 0, 0); -// GLTFKHRLight *light = [[GLTFKHRLight alloc] init]; -// lightNode.light = light; -// [self.asset.defaultScene addNode:lightNode]; -// [self.asset addLight:light]; -// -// GLTFKHRLight *ambientLight = [[GLTFKHRLight alloc] init]; -// ambientLight.type = GLTFKHRLightTypeAmbient; -// ambientLight.intensity = 0.1; -// [self.asset addLight:ambientLight]; -// self.asset.defaultScene.ambientLight = ambientLight; -} - -void MetalRenderer::computeRegularizationMatrix(std::shared_ptr model) { - GLTFBoundingSphere bounds = GLTFBoundingSphereFromBox(model->_asset.defaultScene.approximateBounds); - model->_boundingSphere = bounds; - float scale = (bounds.radius > 0) ? (1 / (bounds.radius)) : 1; - simd_double4x4 centerScale = GLTFMatrixFromUniformScaleD(scale); - simd_double4x4 centerTranslation = GLTFMatrixFromTranslationD(-bounds.center); - - // This regularization matrix centers the model - model->_regularizationMatrix = matrix_multiply(centerScale, centerTranslation); - - - // The regularization matrix just scales it to show in the viewport - model->_regularizationMatrix = centerScale; - -} - -void MetalRenderer::computeTransforms(std::shared_ptr model) { - // New stuff - auto mdlMatrix = matrix_identity_double4x4; - - // Rotation - auto modelRotation = GLTFRotationMatrixFromAxisAngleD(GLTFAxisYD, (model->_gltfModel->_rotationDeg) * DEG_RAD); - auto modelRotated = matrix_multiply(modelRotation, mdlMatrix); - - // Tilt - auto modelTilted = GLTFRotationMatrixFromAxisAngleD(GLTFAxisXD, 90 * DEG_RAD); - modelTilted = matrix_multiply(modelTilted, modelRotated); - - simd_double3 xlateVector = simd_make_double3(model->_gltfModel->_xLateX, - model->_gltfModel->_xLateY, - model->_gltfModel->_xLateZ); - - auto xLateMatrix = GLTFMatrixFromTranslationD(xlateVector); - - auto modelTranslated = matrix_multiply(xLateMatrix, modelTilted); - - model->_modelMatrix = modelTranslated; - - model->_modelViewMatrix = modelTranslated; - - return; -} - -void MetalRenderer::renderScene(std::shared_ptr model, - GLTFScene *scene, - id commandBuffer, - id renderEncoder) { - - if (scene == nil) { - return; - } -/* - long timedOut = dispatch_semaphore_wait(_frameBoundarySemaphore, dispatch_time(0, 1 * NSEC_PER_SEC)); - if (timedOut) { - NSLog(@"Failed to receive frame boundary signal before timing out; calling signalFrameCompletion manually. " - "Remember to call signalFrameCompletion on GLTFMTLRenderer from the completion handler of the command buffer " - "into which you encode the work for drawing assets"); - signalFrameCompletion(); - } - */ - //self.ambientLight = scene.ambientLight; - - for (GLTFNode *rootNode in scene.nodes) { - buildLightListRecursive(rootNode); - } - - for (GLTFNode *rootNode in scene.nodes) { - buildRenderListRecursive(model, - rootNode, matrix_identity_float4x4, scene.ambientLight); - } - - NSMutableArray *renderList = [NSMutableArray arrayWithArray:_opaqueRenderItems]; - [renderList addObjectsFromArray:_transparentRenderItems]; - - drawRenderList(renderList, renderEncoder); - - NSArray *copiedDeferredReusableBuffers = [_deferredReusableBuffers copy]; - [commandBuffer addCompletedHandler:^(id commandBuffer) { - dispatch_async(dispatch_get_main_queue(), ^{ - for (id buffer in copiedDeferredReusableBuffers) { - enqueueReusableBuffer(buffer); - } - }); - }]; - - [_opaqueRenderItems removeAllObjects]; - [_transparentRenderItems removeAllObjects]; - [_currentLightNodes removeAllObjects]; - [_deferredReusableBuffers removeAllObjects]; -} - -void MetalRenderer::buildLightListRecursive(GLTFNode *node) { - if (node.light != nil) { - [_currentLightNodes addObject:node]; - } - - for (GLTFNode *childNode in node.children) { - buildLightListRecursive(childNode); - } -} - -simd_float4x4 matrix_double_to_float(simd_double4x4 input) { - simd_float4x4 tempResult; - tempResult.columns[0][0] = input.columns[0][0]; - tempResult.columns[0][1] = input.columns[0][1]; - tempResult.columns[0][2] = input.columns[0][2]; - tempResult.columns[0][3] = input.columns[0][3]; - - tempResult.columns[1][0] = input.columns[1][0]; - tempResult.columns[1][1] = input.columns[1][1]; - tempResult.columns[1][2] = input.columns[1][2]; - tempResult.columns[1][3] = input.columns[1][3]; - - tempResult.columns[2][0] = input.columns[2][0]; - tempResult.columns[2][1] = input.columns[2][1]; - tempResult.columns[2][2] = input.columns[2][2]; - tempResult.columns[2][3] = input.columns[2][3]; - - tempResult.columns[3][0] = input.columns[3][0]; - tempResult.columns[3][1] = input.columns[3][1]; - tempResult.columns[3][2] = input.columns[3][2]; - tempResult.columns[3][3] = input.columns[3][3]; - - return tempResult; -} - -simd_float3 double3_to_float3(simd_double3 input) { - simd_float3 tempResult; - tempResult.x = input.x; - tempResult.y = input.y; - tempResult.z = input.z; - return tempResult; - -} - -void MetalRenderer::buildRenderListRecursive(std::shared_ptr model, - GLTFNode *node, - simd_float4x4 modelMatrix, - GLTFKHRLight *defaultAmbientLight) { - modelMatrix = matrix_multiply(modelMatrix, node.localTransform); - - GLTFMesh *mesh = node.mesh; - if (mesh) { - for (GLTFSubmesh *submesh in mesh.submeshes) { - GLTFMaterial *material = submesh.material; - - simd_double3x3 viewAffine = simd_inverse(GLTFMatrixUpperLeft3x3D(model->_modelViewMatrix)); - simd_double3 cameraPos = model->_modelViewMatrix.columns[3].xyz; - simd_double3 cameraWorldPos = matrix_multiply(viewAffine, -cameraPos); - simd_float3 cameraWorldPosF = double3_to_float3(cameraWorldPos); - - VertexUniforms vertexUniforms; - vertexUniforms.modelMatrix = modelMatrix; - - // TODO: MT: Review this.. - auto mvp = matrix_multiply(_projectionMatrix, model->_modelMatrix); - auto mvpF = matrix_double_to_float(mvp); - vertexUniforms.modelViewProjectionMatrix = mvpF; - auto normalMatrix = GLTFNormalMatrixFromModelMatrixD(model->_modelMatrix); - vertexUniforms.normalMatrix = matrix_double_to_float(normalMatrix); - - vertexUniforms.scaleFactor = model->_scaling; - vertexUniforms.brightness = model->_brightness; - vertexUniforms.lightDirection = _renderingEnvironment->_lightDirection; - - FragmentUniforms fragmentUniforms; - fragmentUniforms.normalScale = material.normalTextureScale; - fragmentUniforms.emissiveFactor = material.emissiveFactor; - fragmentUniforms.occlusionStrength = material.occlusionStrength; - fragmentUniforms.metallicRoughnessValues = (simd_float2){ material.metalnessFactor, material.roughnessFactor }; - fragmentUniforms.baseColorFactor = material.baseColorFactor; - fragmentUniforms.camera = cameraWorldPosF; - fragmentUniforms.alphaCutoff = material.alphaCutoff; - fragmentUniforms.envIntensity = 2; // self.lightingEnvironment.intensity; - - if (material.baseColorTexture != nil) { - fragmentUniforms.textureMatrices[GLTFTextureBindIndexBaseColor] = GLTFTextureMatrixFromTransform(material.baseColorTexture.transform); - } - if (material.normalTexture != nil) { - fragmentUniforms.textureMatrices[GLTFTextureBindIndexNormal] = GLTFTextureMatrixFromTransform(material.normalTexture.transform); - } - if (material.metallicRoughnessTexture != nil) { - fragmentUniforms.textureMatrices[GLTFTextureBindIndexMetallicRoughness] = GLTFTextureMatrixFromTransform(material.metallicRoughnessTexture.transform); - } - if (material.occlusionTexture != nil) { - fragmentUniforms.textureMatrices[GLTFTextureBindIndexOcclusion] = GLTFTextureMatrixFromTransform(material.occlusionTexture.transform); - } - if (material.emissiveTexture != nil) { - fragmentUniforms.textureMatrices[GLTFTextureBindIndexEmissive] = GLTFTextureMatrixFromTransform(material.emissiveTexture.transform); - } - - if (defaultAmbientLight != nil) { - fragmentUniforms.ambientLight.color = defaultAmbientLight.color; // self.ambientLight.color; - fragmentUniforms.ambientLight.intensity = defaultAmbientLight.intensity; //self.ambientLight.intensity; - } - - // TODO: Make this more efficient. Iterating the light list for every submesh is pretty silly. - for (unsigned int lightIndex = 0; lightIndex < _currentLightNodes.count; ++lightIndex) { - GLTFNode *lightNode = _currentLightNodes[lightIndex]; - GLTFKHRLight *light = lightNode.light; - if (light.type == GLTFKHRLightTypeDirectional) { - fragmentUniforms.lights[lightIndex].position = lightNode.globalTransform.columns[2]; - } else { - fragmentUniforms.lights[lightIndex].position = lightNode.globalTransform.columns[3]; - } - fragmentUniforms.lights[lightIndex].color = light.color; - fragmentUniforms.lights[lightIndex].intensity = light.intensity; - fragmentUniforms.lights[lightIndex].range = light.range; - if (light.type == GLTFKHRLightTypeSpot) { - fragmentUniforms.lights[lightIndex].innerConeAngle = light.innerConeAngle; - fragmentUniforms.lights[lightIndex].outerConeAngle = light.outerConeAngle; - } else { - fragmentUniforms.lights[lightIndex].innerConeAngle = 0; - fragmentUniforms.lights[lightIndex].outerConeAngle = M_PI; - } - fragmentUniforms.lights[lightIndex].spotDirection = lightNode.globalTransform.columns[2]; - } - - GLTFMTLRenderItem *item = [GLTFMTLRenderItem new]; - item.label = [NSString stringWithFormat:@"%@ - %@", node.name ?: @"Unnamed node", submesh.name ?: @"Unnamed primitive"]; - item.node = node; - item.submesh = submesh; - item.vertexUniforms = vertexUniforms; - item.fragmentUniforms = fragmentUniforms; - - if (submesh.material.alphaMode == GLTFAlphaModeBlend) { - [_transparentRenderItems addObject:item]; - } else { - [_opaqueRenderItems addObject:item]; - } - } - } - - for (GLTFNode *childNode in node.children) { - buildRenderListRecursive(model, - childNode, modelMatrix, defaultAmbientLight); - // [self buildRenderListRecursive:childNode modelMatrix:modelMatrix]; - } -} - -void MetalRenderer::drawRenderList(NSArray *renderList, - id renderEncoder) { - for (GLTFMTLRenderItem *item in renderList) { - GLTFNode *node = item.node; - GLTFSubmesh *submesh = item.submesh; - GLTFMaterial *material = submesh.material; - - [renderEncoder pushDebugGroup:[NSString stringWithFormat:@"%@", item.label]]; - - id renderPipelineState = renderPipelineStateForSubmesh(submesh); - - [renderEncoder setRenderPipelineState:renderPipelineState]; - - [renderEncoder setFrontFacingWinding:MTLWindingCounterClockwise]; - - NSDictionary *accessorsForAttributes = submesh.accessorsForAttributes; - - GLTFAccessor *indexAccessor = submesh.indexAccessor; - BOOL useIndexBuffer = (indexAccessor != nil); - - // TODO: Check primitive type for unsupported types (tri fan, line loop), and modify draw calls as appropriate - MTLPrimitiveType primitiveType = GLTFMTLPrimitiveTypeForPrimitiveType(submesh.primitiveType); - - bindTexturesForMaterial(material, renderEncoder); - - VertexUniforms vertexUniforms = item.vertexUniforms; - [renderEncoder setVertexBytes:&vertexUniforms length:sizeof(vertexUniforms) atIndex:GLTFVertexDescriptorMaxAttributeCount + 0]; - - if (node.skin != nil && node.skin.jointNodes != nil && node.skin.jointNodes.count > 0) { - id jointBuffer = dequeueReusableBufferOfLength(node.skin.jointNodes.count * sizeof(simd_float4x4)); - computeJointsForSubmesh(submesh, node, jointBuffer); - [renderEncoder setVertexBuffer:jointBuffer offset:0 atIndex:GLTFVertexDescriptorMaxAttributeCount + 1]; - [_deferredReusableBuffers addObject:jointBuffer]; - } - - FragmentUniforms fragmentUniforms = item.fragmentUniforms; - [renderEncoder setFragmentBytes:&fragmentUniforms length: sizeof(fragmentUniforms) atIndex: 0]; - - GLTFVertexDescriptor *vertexDescriptor = submesh.vertexDescriptor; - for (int i = 0; i < GLTFVertexDescriptorMaxAttributeCount; ++i) { - NSString *semantic = vertexDescriptor.attributes[i].semantic; - if (semantic == nil) { continue; } - GLTFAccessor *accessor = submesh.accessorsForAttributes[semantic]; - - [renderEncoder setVertexBuffer:((GLTFMTLBuffer *)accessor.bufferView.buffer).buffer - offset:accessor.offset + accessor.bufferView.offset - atIndex:i]; - } - - if (material.alphaMode == GLTFAlphaModeBlend){ - id depthStencilState = depthStencilStateForDepthWriteEnabled(YES, YES, MTLCompareFunctionLess); - [renderEncoder setDepthStencilState:depthStencilState]; - } else { - id depthStencilState = depthStencilStateForDepthWriteEnabled(YES,YES,MTLCompareFunctionLess); - [renderEncoder setDepthStencilState:depthStencilState]; - } - - if (material.isDoubleSided) { - [renderEncoder setCullMode:MTLCullModeNone]; - } else { - [renderEncoder setCullMode:MTLCullModeBack]; - } - - if (useIndexBuffer) { - GLTFMTLBuffer *indexBuffer = (GLTFMTLBuffer *)indexAccessor.bufferView.buffer; - - MTLIndexType indexType = (indexAccessor.componentType == GLTFDataTypeUShort) ? MTLIndexTypeUInt16 : MTLIndexTypeUInt32; - - [renderEncoder drawIndexedPrimitives:primitiveType - indexCount:indexAccessor.count - indexType:indexType - indexBuffer:[indexBuffer buffer] - indexBufferOffset:indexAccessor.offset + indexAccessor.bufferView.offset]; - } else { - GLTFAccessor *positionAccessor = accessorsForAttributes[GLTFAttributeSemanticPosition]; - [renderEncoder drawPrimitives:primitiveType vertexStart:0 vertexCount:positionAccessor.count]; - } - - [renderEncoder popDebugGroup]; - } -} - - -void MetalRenderer::bindTexturesForMaterial(GLTFMaterial *material, - id renderEncoder) { - if (material.baseColorTexture != nil) { - id texture = textureForImage(material.baseColorTexture.texture.image, true); - id sampler = samplerStateForSampler(material.baseColorTexture.texture.sampler); - [renderEncoder setFragmentTexture:texture atIndex:GLTFTextureBindIndexBaseColor]; - [renderEncoder setFragmentSamplerState:sampler atIndex:GLTFTextureBindIndexBaseColor]; - } - - if (material.normalTexture != nil) { - id texture = textureForImage(material.normalTexture.texture.image, false); - id sampler = samplerStateForSampler(material.normalTexture.texture.sampler); - [renderEncoder setFragmentTexture:texture atIndex:GLTFTextureBindIndexNormal]; - [renderEncoder setFragmentSamplerState:sampler atIndex:GLTFTextureBindIndexNormal]; - } - - if (material.metallicRoughnessTexture != nil) { - id texture = textureForImage(material.metallicRoughnessTexture.texture.image, false); - id sampler = samplerStateForSampler(material.metallicRoughnessTexture.texture.sampler); - [renderEncoder setFragmentTexture:texture atIndex:GLTFTextureBindIndexMetallicRoughness]; - [renderEncoder setFragmentSamplerState:sampler atIndex:GLTFTextureBindIndexMetallicRoughness]; - } - - if (material.emissiveTexture != nil) { - id texture = textureForImage(material.emissiveTexture.texture.image, true); - id sampler = samplerStateForSampler(material.emissiveTexture.texture.sampler); - [renderEncoder setFragmentTexture:texture atIndex:GLTFTextureBindIndexEmissive]; - [renderEncoder setFragmentSamplerState:sampler atIndex:GLTFTextureBindIndexEmissive]; - } - - if (material.occlusionTexture != nil) { - id texture = textureForImage(material.occlusionTexture.texture.image, false); - id sampler = samplerStateForSampler(material.occlusionTexture.texture.sampler); - [renderEncoder setFragmentTexture:texture atIndex:GLTFTextureBindIndexOcclusion]; - [renderEncoder setFragmentSamplerState:sampler atIndex:GLTFTextureBindIndexOcclusion]; - } -} - -id MetalRenderer::dequeueReusableBufferOfLength(size_t length) { - int indexToReuse = -1; - for (unsigned int i = 0; i < _bufferPool.count; ++i) { - if (_bufferPool[i].length >= length) { - indexToReuse = i; - } - } - - if (indexToReuse >= 0) { - id buffer = _bufferPool[indexToReuse]; - [_bufferPool removeObjectAtIndex:indexToReuse]; - return buffer; - } else { - return [_metalDevice newBufferWithLength:length options:MTLResourceStorageModeShared]; - } -} - -void MetalRenderer::computeJointsForSubmesh(GLTFSubmesh *submesh, - GLTFNode *node, - id jointBuffer) { - GLTFAccessor *jointsAccessor = submesh.accessorsForAttributes[GLTFAttributeSemanticJoints0]; - GLTFSkin *skin = node.skin; - GLTFAccessor *inverseBindingAccessor = node.skin.inverseBindMatricesAccessor; - - if (jointsAccessor != nil && inverseBindingAccessor != nil) { - NSInteger jointCount = skin.jointNodes.count; - simd_float4x4 *jointMatrices = (simd_float4x4 *)jointBuffer.contents; - simd_float4x4 *inverseBindMatrices = (simd_float4x4 *)((char *)inverseBindingAccessor.bufferView.buffer.contents + inverseBindingAccessor.bufferView.offset + inverseBindingAccessor.offset); - for (NSInteger i = 0; i < jointCount; ++i) { - GLTFNode *joint = skin.jointNodes[i]; - simd_float4x4 inverseBindMatrix = inverseBindMatrices[i]; - jointMatrices[i] = matrix_multiply(matrix_invert(node.globalTransform), matrix_multiply(joint.globalTransform, inverseBindMatrix)); - } - } -} - -id MetalRenderer::depthStencilStateForDepthWriteEnabled(bool depthWriteEnabled, - bool depthTestEnabled, - MTLCompareFunction compareFunction) { - - NSInteger depthWriteBit = depthWriteEnabled ? 1 : 0; - NSInteger depthTestBit = depthTestEnabled ? 1 : 0; - - NSInteger hash = (compareFunction << 2) | (depthWriteBit << 1) | depthTestBit; - - id depthStencilState = _depthStencilStateMap[@(hash)]; - if (depthStencilState) { - return depthStencilState; - } - - MTLDepthStencilDescriptor *depthDescriptor = [MTLDepthStencilDescriptor new]; - depthDescriptor.depthCompareFunction = depthTestEnabled ? compareFunction : MTLCompareFunctionAlways; - depthDescriptor.depthWriteEnabled = depthWriteEnabled; - depthStencilState = [_metalDevice newDepthStencilStateWithDescriptor:depthDescriptor]; - - _depthStencilStateMap[@(hash)] = depthStencilState; - - return depthStencilState; -} - - -id MetalRenderer::textureForImage(GLTFImage *image, - bool sRGB) { -// NSParameterAssert(image != nil); - - id texture = _texturesForImageIdentifiers[image.identifier]; - - if (texture) { - return texture; - } - - NSDictionary *options = @{ GLTFMTLTextureLoaderOptionGenerateMipmaps : @YES, - GLTFMTLTextureLoaderOptionSRGB : @(sRGB) - }; - - NSError *error = nil; - if (image.imageData != nil) { - texture = [_textureLoader newTextureWithData:image.imageData options:options error:&error]; - texture.label = image.name; - } else if (image.url != nil) { - texture = [_textureLoader newTextureWithContentsOfURL:image.url options:options error:&error]; - texture.label = image.name ?: image.url.lastPathComponent; - } else if (image.bufferView != nil) { - GLTFBufferView *bufferView = image.bufferView; - NSData *data = [NSData dataWithBytesNoCopy:(char *)bufferView.buffer.contents + bufferView.offset length:bufferView.length freeWhenDone:NO]; - texture = [_textureLoader newTextureWithData:data options:options error:&error]; - texture.label = image.name; - } - - if (!texture) { - NSLog(@"Error occurred while loading texture: %@", error); - } else { - _texturesForImageIdentifiers[image.identifier] = texture; - } - - return texture; -} - -id MetalRenderer::samplerStateForSampler(GLTFTextureSampler *sampler) { -// NSParameterAssert(sampler != nil); - - id samplerState = _samplerStatesForSamplers[sampler]; - if (samplerState == nil) { - MTLSamplerDescriptor *descriptor = [MTLSamplerDescriptor new]; - descriptor.magFilter = GLTFMTLSamplerMinMagFilterForSamplingFilter(sampler.magFilter); - descriptor.minFilter = GLTFMTLSamplerMinMagFilterForSamplingFilter(sampler.minFilter); - descriptor.mipFilter = GLTFMTLSamplerMipFilterForSamplingFilter(sampler.minFilter); - descriptor.sAddressMode = GLTFMTLSamplerAddressModeForSamplerAddressMode(sampler.sAddressMode); - descriptor.tAddressMode = GLTFMTLSamplerAddressModeForSamplerAddressMode(sampler.tAddressMode); - descriptor.normalizedCoordinates = YES; - samplerState = [_metalDevice newSamplerStateWithDescriptor:descriptor]; - _samplerStatesForSamplers[sampler] = samplerState; - } - return samplerState; -} - diff --git a/platform/darwin/src/gltf/MetalRenderer.hpp b/platform/darwin/src/gltf/MetalRenderer.hpp deleted file mode 100644 index 4dae0c37c19e..000000000000 --- a/platform/darwin/src/gltf/MetalRenderer.hpp +++ /dev/null @@ -1,228 +0,0 @@ -// -// GLTFRenderer.hpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#ifndef MetalRenderer_hpp -#define MetalRenderer_hpp - -#include -#include -#include "GLTFRenderer.hpp" -#import "gltfkit/GLTFAsset.h" -#import "gltfkit//GLTFNode.h" -#import "gltfkit/GLTFImage.h" -#import "gltfkit/GLTFTextureSampler.h" -#include "GLTFMTLRenderItem.h" -#import "gltfkit/GLTFMTLTextureLoader.h" -#include "GLTFManagerRenderingEnvironmentMetal.hpp" -#include -#include -#include - -namespace maplibre { -namespace gltf { - -class GLTFRenderModel { -public: - // The model metadata - std::shared_ptr _gltfModel = nullptr; - - // The loaded model - GLTFAsset *_asset = nil; - - // Rendering variables - // Translation Vector is the translation of the model from the - simd_float3 _translationVector; // This might need to be a doubles vector - double _rotationDeg = 0; // Rotation around the zAxis (if applicable) - double _scaling = 1; // Scaling from - float _brightness = 1.0; // Brightness - - // This is the model matrix (rotation, scaling and transformation applied) - simd_double4x4 _modelMatrix; - - // This is the model matrix combined with the camera's view matrix - simd_double4x4 _modelViewMatrix; - - // We probably won't need this in the final thing. Used to normalize the model to the - // viewport size - simd_double4x4 _regularizationMatrix; - - // - GLTFBoundingSphere _boundingSphere; -}; - -// -class MetalRenderer : public GLTFRenderer { -public: - // Constructor - MetalRenderer(); - ~MetalRenderer(); - - void setMetalDevice(id device); - - // Set the drawable size - void setDrawableSize(int width, int height) override; - - // Set the current drawable (used for a metal view) - // void setCurrentDrawable(id drawable); - - // Set the output render pass descriptor (this is for outputting to a metal view) - // void setCurrentOutputRenderPassDescriptor(MTLRenderPassDescriptor *renderPassDescriptor); - - // Update any animations - void update(float timeSinceLastDraw) override; - - // Render - void render() override; - - // Load a model - void loadGLTFModel(std::shared_ptr model) override; - - // Set the rendering environemnt variables - void setRenderingEnvironemnt(std::shared_ptr renderingEnvironment) override; - -private: - // Rendering environment variables - simd_double4x4 _projectionMatrix; - int _sampleCount = 1; - MTLPixelFormat _colorPixelFormat; - MTLPixelFormat _depthStencilPixelFormat; - simd_int2 _drawableSize; - double _globalTime = 0; - int _maxInflightFrames = 3; - - // Current external environment variables - std::shared_ptr _metalRenderingEnvironment = nullptr; - - // id _currentDrawable = nullptr; - // MTLRenderPassDescriptor *_currentOutputRenderPassDescriptor = nullptr; - - dispatch_semaphore_t _frameBoundarySemaphore; - - void encodeMainPass(id commandBuffer); - void encodeBloomPasses(id commandBuffer); - void encodeTonemappingPass(id commandBuffer); - void drawFullscreenPassWithPipeline(id renderPipelineState, - id renderCommandEncoder, - id sourceTexture); - void signalFrameCompletion(); - MTLRenderPassDescriptor *newRenderPassDescriptor(); - -private: - // Per-frame - void computeTransforms(std::shared_ptr model); - -protected: - void loadBloomPipelines() override; - void loadTonemapPipeline() override; - void updateFramebufferSize() override; // Updates the framebuffers based on size - -private: - // Set by the environment - id _metalDevice = nullptr; - - // Created for rendering the model - id _internalMetalCommandQueue = nullptr; - id _metalLibrary = nullptr; - - // Setup the rendering environment. Called after device is set - void setupMetal(); - - // Bloom - id _bloomThresholdPipelineState = nullptr; - id _blurHorizontalPipelineState = nullptr; - id _blurVerticalPipelineState = nullptr; - id _additiveBlendPipelineState = nullptr; - - // Tonemap - id _tonemapPipelineState = nullptr; - - // Render targets - id _multisampleColorTexture = nullptr; - id _colorTexture = nullptr; - id _depthStencilTexture = nullptr; - id _bloomTextureA = nullptr; - id _bloomTextureB = nullptr; - - // Depth Clear - id _depthStencilClearState = nullptr; - id _pipelineDepthClearState = nullptr; - - void loadDepthClearPipeline(); - void clearDepth(id); - -public: - // Encapsulated in GLTFRenderer+GLTFAsset - void setGLTFAsset(GLTFAsset *asset, std::shared_ptr model); - - // - void addGLTFAsset(GLTFAsset *asset, std::shared_ptr model); - - // - id _bufferAllocator; - -private: - std::shared_ptr createRenderModel(GLTFAsset *asset, std::shared_ptr model); - - std::vector> _models; - // GLTFAsset *_asset = nil; - // NSMutableArray *_assets = nil; - - // - void computeRegularizationMatrix(std::shared_ptr model); - void addDefaultLights(std::shared_ptr model); - - void renderScene(std::shared_ptr model, - GLTFScene *scene, - id commandBuffer, - id renderEncoder); - - void buildLightListRecursive(GLTFNode *node); - - void buildRenderListRecursive(std::shared_ptr model, - GLTFNode *node, - simd_float4x4 modelMatrix, - GLTFKHRLight *defaultAmbientLight); - - void drawRenderList(NSArray *renderList, id renderEncoder); - - id renderPipelineStateForSubmesh(GLTFSubmesh *submesh); - - void bindTexturesForMaterial(GLTFMaterial *material, id renderEncoder); - - id dequeueReusableBufferOfLength(size_t length); - - void computeJointsForSubmesh(GLTFSubmesh *submesh, GLTFNode *node, id jointBuffer); - - id depthStencilStateForDepthWriteEnabled(bool depthWriteEnabled, - bool depthTestEnabled, - MTLCompareFunction compareFunction); - - id textureForImage(GLTFImage *image, bool sRGB); - id samplerStateForSampler(GLTFTextureSampler *sampler); - - NSMutableArray *_opaqueRenderItems; - NSMutableArray *_transparentRenderItems; - NSMutableArray *_currentLightNodes; - NSMutableArray> *_deferredReusableBuffers; - NSMutableArray> *_bufferPool; - NSMutableDictionary> *_depthStencilStateMap; - - NSMutableDictionary> *_pipelineStatesForSubmeshes; - NSMutableDictionary> *_texturesForImageIdentifiers; - GLTFMTLTextureLoader *_textureLoader; - NSMutableDictionary> *_samplerStatesForSamplers; - - void enqueueReusableBuffer(id buffer); - - // This is the depth stencil descriptor for overlaying the - id _fullscreenTransfterDepthStencilState = nullptr; -}; - -} // namespace gltf -} // namespace maplibre - -#endif /* MetalRenderer_hpp */ diff --git a/platform/darwin/src/gltf/MetalRenderer.mm b/platform/darwin/src/gltf/MetalRenderer.mm deleted file mode 100644 index 1a21692ea38e..000000000000 --- a/platform/darwin/src/gltf/MetalRenderer.mm +++ /dev/null @@ -1,540 +0,0 @@ -// -// GLTFRenderer.cpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#include "MetalRenderer.hpp" -#include -#include - -#import "GLTFModelLoader.h" -#import "gltfkit/GLTFAnimation.h" -#import "gltfkit/GLTFMTLShaderBuilder.h" -#import "gltfkit/GLTFMTLBufferAllocator.h" - - -using namespace maplibre::gltf; - -MetalRenderer::MetalRenderer() { - GLTFRenderer(); -} - -MetalRenderer::~MetalRenderer() { - std::cout << "Destructor\n"; -} - - -void MetalRenderer::setMetalDevice(id device) { - if (_metalDevice == device) { - return; - } - - _metalDevice = device; - setupMetal(); -} - -// Set the drawable size -void MetalRenderer::setDrawableSize(int width, int height) { - if ((_drawableSize.x == width) && (_drawableSize.y == height)) { - return; - } - _drawableSize = {width, height}; - // updateFramebufferSize(); -} - -// Set the current drawable -//void MetalRenderer::setCurrentDrawable(id drawable) { -// _currentDrawable = drawable; -//} - -// Set the output render pass descriptor (this is for outputting to a metal view) -//void MetalRenderer::setCurrentOutputRenderPassDescriptor(MTLRenderPassDescriptor *renderPassDescriptor) { -// _currentOutputRenderPassDescriptor = renderPassDescriptor; -//} - - - -// Update any animations -void MetalRenderer::update(float timeSinceLastDraw) { - - // Update the global time - _globalTime += timeSinceLastDraw; - - // If we don't have an asset, then bail - if (_models.size() == 0) { - return; - } - - double maxAnimDuration = 0; - for (auto m: _models) { - for (GLTFAnimation *animation in m->_asset.animations) { - for (GLTFAnimationChannel *channel in animation.channels) { - if (channel.duration > maxAnimDuration) { - maxAnimDuration = channel.duration; - } - } - } - } - - double animTime = fmod(_globalTime, maxAnimDuration); - for (auto m: _models) { - for (GLTFAnimation *animation in m->_asset.animations) { - [animation runAtTime:animTime]; - } - } - - _camera->updateWithTimestep(timeSinceLastDraw); - for (auto m: _models) { - computeTransforms(m); - } - -} - -// Render -void MetalRenderer::render() { - - auto environmentMVP = _metalRenderingEnvironment->_currentProjectionMatrix; - double tileSize = 256.0; - double zoom = _metalRenderingEnvironment->_currentZoomLevel; - double scaleFactor = (20037508.34); // M_PI - double worldSize = (tileSize / scaleFactor) * pow(2.0, zoom); - simd_double4x4 scaleMatrix = GLTFMatrixFromScaleD(simd_make_double3(worldSize, -worldSize, 1.0)); - simd_double4x4 xlateMatrix = GLTFMatrixFromTranslationD(simd_make_double3(20037508.34,-20037508.34,0.0)); - - auto m1 = matrix_multiply(scaleMatrix, xlateMatrix); - auto m2 = matrix_multiply(environmentMVP, m1); - _projectionMatrix = m2; - - // id internalCommandBuffer = [_internalMetalCommandQueue commandBuffer]; -// -// if (_existingCommandBuffer) { -// commandBuffer = _metalRenderingEnvironment->_currentCommandBuffer; -// } else { -// // Create a command buffer and we're going to be expected to draw to the output -// commandBuffer = [_internalMetalCommandQueue commandBuffer]; -// currentDrawable = _metalRenderingEnvironment->_currentDrawable; -// } -// - encodeMainPass(_metalRenderingEnvironment->_currentCommandBuffer); - // if (_useBloomPass) { - // encodeBloomPasses(internalCommandBuffer); - // } - -// [internalCommandBuffer addCompletedHandler:^(id buffer) { -// dispatch_async(dispatch_get_main_queue(), ^{ -// signalFrameCompletion(); -// }); -// }]; - - - // This will write out the tone mapping - //id externalBuffer = _metalRenderingEnvironment->_currentCommandBuffer; - //encodeTonemappingPass(externalBuffer); -} - -// Load a model -void MetalRenderer::loadGLTFModel(std::shared_ptr model) { - - GLTFModelLoader *modelLoader = [[GLTFModelLoader alloc] init]; - NSURL *u = [NSURL URLWithString:[NSString stringWithCString:model->_modelURL.c_str()]]; - [modelLoader loadURL:u - withCompletionHandler:^(GLTFAsset * _Nonnull asset) { - addGLTFAsset(asset, model); - } - bufferAllocator:_bufferAllocator]; - -} - -// Set the rendering environemnt variables -void MetalRenderer::setRenderingEnvironemnt(std::shared_ptr renderingEnvironment) { - GLTFRenderer::setRenderingEnvironemnt(renderingEnvironment); - - _metalRenderingEnvironment = std::static_pointer_cast(renderingEnvironment); - -} - - -// RENDERING -void MetalRenderer::encodeMainPass(id commandBuffer) { - - id renderEncoder = _metalRenderingEnvironment->_currentCommandEncoder; - - for (auto m: _models) { - [renderEncoder pushDebugGroup:@"Draw glTF Scene"]; - renderScene(m, m->_asset.defaultScene, commandBuffer, renderEncoder); - [renderEncoder popDebugGroup]; - } - - -} - -void MetalRenderer::encodeBloomPasses(id commandBuffer) { - - MTLRenderPassDescriptor *pass = [MTLRenderPassDescriptor renderPassDescriptor]; - pass.colorAttachments[0].texture = _bloomTextureA; - pass.colorAttachments[0].loadAction = MTLLoadActionDontCare; - pass.colorAttachments[0].storeAction = MTLStoreActionStore; - - id renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:pass]; - [renderEncoder pushDebugGroup:@"Post-process (Bloom threshold)"]; - drawFullscreenPassWithPipeline(_bloomThresholdPipelineState,renderEncoder,_colorTexture); - [renderEncoder popDebugGroup]; - [renderEncoder endEncoding]; - - pass = [MTLRenderPassDescriptor renderPassDescriptor]; - pass.colorAttachments[0].texture = _bloomTextureB; - pass.colorAttachments[0].loadAction = MTLLoadActionDontCare; - pass.colorAttachments[0].storeAction = MTLStoreActionStore; - renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:pass]; - [renderEncoder pushDebugGroup:@"Post-process (Bloom blur - horizontal)"]; - drawFullscreenPassWithPipeline(_blurHorizontalPipelineState,renderEncoder,_bloomTextureA); - [renderEncoder popDebugGroup]; - [renderEncoder endEncoding]; - - pass = [MTLRenderPassDescriptor renderPassDescriptor]; - pass.colorAttachments[0].texture = _bloomTextureA; - pass.colorAttachments[0].loadAction = MTLLoadActionDontCare; - pass.colorAttachments[0].storeAction = MTLStoreActionStore; - renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:pass]; - [renderEncoder pushDebugGroup:@"Post-process (Bloom blur - vertical)"]; - drawFullscreenPassWithPipeline(_blurVerticalPipelineState,renderEncoder,_bloomTextureB); - [renderEncoder popDebugGroup]; - [renderEncoder endEncoding]; - - pass = [MTLRenderPassDescriptor renderPassDescriptor]; - pass.colorAttachments[0].texture = _colorTexture; - pass.colorAttachments[0].loadAction = MTLLoadActionLoad; - pass.colorAttachments[0].storeAction = MTLStoreActionStore; - - renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:pass]; - [renderEncoder pushDebugGroup:@"Post-process (Bloom combine)"]; - drawFullscreenPassWithPipeline(_additiveBlendPipelineState,renderEncoder,_bloomTextureA); - [renderEncoder popDebugGroup]; - [renderEncoder endEncoding]; -} - -void MetalRenderer::encodeTonemappingPass(id commandBuffer) { - - if (_metalRenderingEnvironment->_currentRenderPassDescriptor == nil) { - return; - } - - id renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:_metalRenderingEnvironment->_currentRenderPassDescriptor]; - [renderEncoder pushDebugGroup:@"Post-process (Tonemapping)"]; - drawFullscreenPassWithPipeline(_tonemapPipelineState,renderEncoder,_colorTexture); - [renderEncoder popDebugGroup]; - [renderEncoder endEncoding]; - - - -} - -void MetalRenderer::drawFullscreenPassWithPipeline(id renderPipelineState, - id renderCommandEncoder, - id sourceTexture) { - float triangleData[] = { - -1, 3, 0, -1, - -1, -1, 0, 1, - 3, -1, 2, 1 - }; - [renderCommandEncoder setRenderPipelineState:renderPipelineState]; - [renderCommandEncoder setFrontFacingWinding:MTLWindingCounterClockwise]; - [renderCommandEncoder setCullMode:MTLCullModeNone]; - [renderCommandEncoder setVertexBytes:triangleData length:sizeof(float) * 12 atIndex:0]; - [renderCommandEncoder setFragmentTexture:sourceTexture atIndex:0]; - [renderCommandEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:3]; -} - -void MetalRenderer::signalFrameCompletion() { - dispatch_semaphore_signal(_frameBoundarySemaphore); -} - - -MTLRenderPassDescriptor* MetalRenderer::newRenderPassDescriptor() { - MTLRenderPassDescriptor *pass = [MTLRenderPassDescriptor renderPassDescriptor]; - if (_sampleCount > 1) { - pass.colorAttachments[0].texture = _multisampleColorTexture; - pass.colorAttachments[0].resolveTexture = _metalRenderingEnvironment->_colorTexture; - pass.colorAttachments[0].loadAction = MTLLoadActionLoad; - pass.colorAttachments[0].storeAction = MTLStoreActionMultisampleResolve; - pass.colorAttachments[0].clearColor = MTLClearColorMake(1, 0, 0, 0); - } else { - pass.colorAttachments[0].texture = _metalRenderingEnvironment->_colorTexture; - pass.colorAttachments[0].loadAction = MTLLoadActionLoad; - pass.colorAttachments[0].storeAction = MTLStoreActionStore; - pass.colorAttachments[0].clearColor = MTLClearColorMake(1, 0, 0, 0); - - } - pass.depthAttachment.texture = _metalRenderingEnvironment->_depthStencilTexture; - pass.depthAttachment.loadAction = MTLLoadActionLoad; - pass.depthAttachment.storeAction = MTLStoreActionStore; - - return pass; -} - -/* - ------- ------- ----- ----------------------------------------------- - PRIVATE METHODS BELOW - ------- ------- ----- ----------------------------------------------- -*/ - - -void MetalRenderer::setupMetal() { - - _internalMetalCommandQueue = [_metalDevice newCommandQueue]; - _metalLibrary = [_metalDevice newDefaultLibrary]; - - _projectionMatrix = matrix_identity_double4x4; - _colorPixelFormat = MTLPixelFormatBGRA8Unorm; - _depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8; - _sampleCount = 1; - _drawableSize = {1, 1}; - - _frameBoundarySemaphore = dispatch_semaphore_create(_maxInflightFrames); - - loadBloomPipelines(); - loadTonemapPipeline(); - loadDepthClearPipeline(); - - _opaqueRenderItems = [NSMutableArray array]; - _transparentRenderItems = [NSMutableArray array]; - _currentLightNodes = [NSMutableArray array]; - _deferredReusableBuffers = [NSMutableArray array]; - _bufferPool = [NSMutableArray array]; - - _pipelineStatesForSubmeshes = [NSMutableDictionary dictionary]; - _depthStencilStateMap = [NSMutableDictionary dictionary]; - _texturesForImageIdentifiers = [NSMutableDictionary dictionary]; - _samplerStatesForSamplers = [NSMutableDictionary dictionary]; - - _textureLoader = [[GLTFMTLTextureLoader alloc] initWithDevice:_metalDevice]; - _bufferAllocator = [[GLTFMTLBufferAllocator alloc] initWithDevice:_metalDevice]; - //_assets = [NSMutableArray array]; - - - - - MTLDepthStencilDescriptor *fullscreenTransfterDepthStencilDescriptor = [[MTLDepthStencilDescriptor alloc] init]; - fullscreenTransfterDepthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways; // Or another value as needed - fullscreenTransfterDepthStencilDescriptor.depthWriteEnabled = NO; - _fullscreenTransfterDepthStencilState = [_metalDevice newDepthStencilStateWithDescriptor:fullscreenTransfterDepthStencilDescriptor]; - - - -} - -void MetalRenderer::updateFramebufferSize() { - - MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor new]; - textureDescriptor.width = _drawableSize.x; - textureDescriptor.height = _drawableSize.y; - textureDescriptor.depth = 1; - - textureDescriptor.textureType = _sampleCount > 1 ? MTLTextureType2DMultisample : MTLTextureType2D; - textureDescriptor.pixelFormat = _colorPixelFormat; - textureDescriptor.sampleCount = _sampleCount; - textureDescriptor.storageMode = MTLStorageModePrivate; - textureDescriptor.usage = MTLTextureUsageRenderTarget; - _multisampleColorTexture = [_metalDevice newTextureWithDescriptor:textureDescriptor]; - - textureDescriptor.textureType = MTLTextureType2D; - textureDescriptor.pixelFormat = _colorPixelFormat; - textureDescriptor.sampleCount = 1; - textureDescriptor.storageMode = MTLStorageModePrivate; - textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; - _colorTexture = [_metalDevice newTextureWithDescriptor:textureDescriptor]; - - textureDescriptor.textureType = _sampleCount > 1 ? MTLTextureType2DMultisample : MTLTextureType2D; - textureDescriptor.pixelFormat = _depthStencilPixelFormat; - textureDescriptor.sampleCount = _sampleCount; - textureDescriptor.storageMode = MTLStorageModePrivate; - textureDescriptor.usage = MTLTextureUsageRenderTarget; - _depthStencilTexture = [_metalDevice newTextureWithDescriptor:textureDescriptor]; - - textureDescriptor.width = _drawableSize.x / 2; - textureDescriptor.height = _drawableSize.y / 2; - textureDescriptor.textureType = MTLTextureType2D; - textureDescriptor.pixelFormat = _colorPixelFormat; - textureDescriptor.sampleCount = 1; - textureDescriptor.storageMode = MTLStorageModePrivate; - textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; - _bloomTextureA = [_metalDevice newTextureWithDescriptor:textureDescriptor]; - - textureDescriptor.width = _drawableSize.x / 2; - textureDescriptor.height = _drawableSize.y / 2; - textureDescriptor.textureType = MTLTextureType2D; - textureDescriptor.pixelFormat = _colorPixelFormat; - textureDescriptor.sampleCount = 1; - textureDescriptor.storageMode = MTLStorageModePrivate; - textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; - _bloomTextureB = [_metalDevice newTextureWithDescriptor:textureDescriptor]; - - //self.renderer.sampleCount = self.sampleCount; - - -} - - - - - - -void MetalRenderer::loadBloomPipelines() { - - NSError *error = nil; - MTLRenderPipelineDescriptor *descriptor = [MTLRenderPipelineDescriptor new]; - descriptor.vertexFunction = [_metalLibrary newFunctionWithName:@"quad_vertex_main"]; - descriptor.colorAttachments[0].pixelFormat = _colorPixelFormat; - descriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"bloom_threshold_fragment_main"]; - _bloomThresholdPipelineState = [_metalDevice newRenderPipelineStateWithDescriptor:descriptor error:&error]; - if (_bloomThresholdPipelineState == nil) { - NSLog(@"Error occurred when creating render pipeline state: %@", error); - } - - descriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"blur_horizontal7_fragment_main"]; - _blurHorizontalPipelineState = [_metalDevice newRenderPipelineStateWithDescriptor:descriptor error:&error]; - if (_blurHorizontalPipelineState == nil) { - NSLog(@"Error occurred when creating render pipeline state: %@", error); - } - - descriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"blur_vertical7_fragment_main"]; - _blurVerticalPipelineState = [_metalDevice newRenderPipelineStateWithDescriptor:descriptor error:&error]; - if (_blurVerticalPipelineState == nil) { - NSLog(@"Error occurred when creating render pipeline state: %@", error); - } - - descriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"additive_blend_fragment_main"]; - - // Original Values - descriptor.colorAttachments[0].blendingEnabled = YES; - descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; - descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd; - descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne; - descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne; - descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOne; - descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorZero; - - descriptor.colorAttachments[0].blendingEnabled = YES; - descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; - descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationMin; - descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne; - descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha; - descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOne; - descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorDestinationAlpha; - - - _additiveBlendPipelineState = [_metalDevice newRenderPipelineStateWithDescriptor:descriptor error:&error]; - if (_additiveBlendPipelineState == nil) { - NSLog(@"Error occurred when creating render pipeline state: %@", error); - } -} - -void MetalRenderer::loadTonemapPipeline() { - - NSError *error = nil; - MTLRenderPipelineDescriptor *descriptor = [MTLRenderPipelineDescriptor new]; - - - // MT: Added blending - descriptor.colorAttachments[0].blendingEnabled = YES; - descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; - descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd; - descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha; - descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha; - descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha; - descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha; - - - id vertexFunction = [_metalLibrary newFunctionWithName:@"quad_vertex_main"]; - - descriptor.vertexFunction = vertexFunction; - descriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"tonemap_fragment_main"]; - descriptor.sampleCount = _sampleCount; - descriptor.colorAttachments[0].pixelFormat = _colorPixelFormat; - - // TODO: This was hard coded to fix an issue whe moving to ML. Need to sort out - // how these params are set in ML and pass them into here - descriptor.stencilAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; - descriptor.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; - - - _tonemapPipelineState = [_metalDevice newRenderPipelineStateWithDescriptor:descriptor error:&error]; - if (_tonemapPipelineState == nil) { - NSLog(@"Error occurred when creating render pipeline state: %@", error); - } -} - -void MetalRenderer::loadDepthClearPipeline() { - MTLDepthStencilDescriptor *depthStencilDescriptor = [[MTLDepthStencilDescriptor alloc] init]; - - depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways; - depthStencilDescriptor.depthWriteEnabled = YES; - depthStencilDescriptor.label = @"depthStencilClear"; - _depthStencilClearState = [_metalDevice newDepthStencilStateWithDescriptor:depthStencilDescriptor]; - - MTLRenderPipelineDescriptor *renderPipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; - - renderPipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; - renderPipelineDescriptor.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; - renderPipelineDescriptor.stencilAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; - renderPipelineDescriptor.rasterSampleCount = _sampleCount; - - renderPipelineDescriptor.vertexFunction = [_metalLibrary newFunctionWithName:@"vertex_depth_clear"]; - renderPipelineDescriptor.vertexFunction.label = @"vertexDepthClear"; - - renderPipelineDescriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"fragment_depth_clear"]; - renderPipelineDescriptor.fragmentFunction.label = @"fragmentDepthClear"; - - MTLVertexDescriptor *vertexDescriptor = [[MTLVertexDescriptor alloc] init]; - vertexDescriptor.attributes[0].format = MTLVertexFormatFloat2; - vertexDescriptor.attributes[0].offset = 0; - vertexDescriptor.attributes[0].bufferIndex = 0; - vertexDescriptor.layouts[0].stepRate = 1; - vertexDescriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex; - vertexDescriptor.layouts[0].stride = 8; - - renderPipelineDescriptor.vertexDescriptor = vertexDescriptor; - - NSError* error = NULL; - renderPipelineDescriptor.label = @"pipelineDepthClear"; - _pipelineDepthClearState = [_metalDevice newRenderPipelineStateWithDescriptor:renderPipelineDescriptor error:&error]; -} - -void MetalRenderer::clearDepth(id renderEncoder) { - [renderEncoder setDepthStencilState:_depthStencilClearState]; - [renderEncoder setRenderPipelineState:_pipelineDepthClearState]; - - const float clearCoords[8] = { - -1, -1, - 1, -1, - -1, 1, - 1, 1 - }; - - [renderEncoder setVertexBytes:clearCoords length:sizeof(float) * 8 atIndex:0]; - [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4]; - -} - -void MetalRenderer::enqueueReusableBuffer(id buffer) { - [_bufferPool addObject:buffer]; -} - -id MetalRenderer::renderPipelineStateForSubmesh(GLTFSubmesh *submesh) { - - id pipeline = _pipelineStatesForSubmeshes[submesh.identifier]; - - if (pipeline == nil) { - GLTFMTLShaderBuilder *shaderBuilder = [[GLTFMTLShaderBuilder alloc] init]; - pipeline = [shaderBuilder renderPipelineStateForSubmesh: submesh - colorPixelFormat:_colorPixelFormat - depthStencilPixelFormat:_depthStencilPixelFormat - sampleCount:_sampleCount - device:_metalDevice]; - _pipelineStatesForSubmeshes[submesh.identifier] = pipeline; - } - - return pipeline; -} diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAccessor.h b/platform/darwin/src/gltf/gltfkit/GLTFAccessor.h deleted file mode 100644 index e5bdf0d2f77c..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFAccessor.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFEnums.h" -#import "GLTFObject.h" - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFBufferView; - -typedef struct { - float minValue[16]; - float maxValue[16]; -} GLTFValueRange; - -@interface GLTFAccessor : GLTFObject -@property (nonatomic, weak) GLTFBufferView *bufferView; -@property (nonatomic, assign) GLTFDataType componentType; -@property (nonatomic, assign) GLTFDataDimension dimension; -@property (nonatomic, assign) NSInteger offset; -@property (nonatomic, assign) NSInteger count; -@property (nonatomic, assign) GLTFValueRange valueRange; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAccessor.mm b/platform/darwin/src/gltf/gltfkit/GLTFAccessor.mm deleted file mode 100644 index fdcc77e6c85c..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFAccessor.mm +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFAccessor.h" - -@implementation GLTFAccessor - -- (NSString *)description { - return [NSString stringWithFormat:@"GLTFAccessor: count: %d, component type: %d, dimension: %d, offset: %d, view: %@", - (int)self.count, (int)self.componentType, (int)self.dimension, (int)self.offset, self.bufferView]; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAnimation.h b/platform/darwin/src/gltf/gltfkit/GLTFAnimation.h deleted file mode 100644 index e00693e578f3..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFAnimation.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFEnums.h" -#import "GLTFObject.h" - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFNode, GLTFAccessor; - -@interface GLTFAnimation : GLTFObject -@property (nonatomic, copy) NSArray *channels; -@property (nonatomic, copy) NSDictionary *samplers; - -- (void)runAtTime:(NSTimeInterval)time; -@end - -@interface GLTFAnimationSampler : GLTFObject -@property (nonatomic, weak) GLTFAccessor *inputAccessor; -@property (nonatomic, weak) GLTFAccessor *outputAccessor; -@property (nonatomic, assign) GLTFInterpolationMode interpolationMode; -@end - -@interface GLTFAnimationChannel : NSObject -@property (nonatomic, weak) GLTFNode *targetNode; -@property (nonatomic, weak) NSString *targetPath; -@property (nonatomic, weak) GLTFAnimationSampler *sampler; -@property (nonatomic, readonly, assign) NSTimeInterval duration; -@property (nonatomic, readonly, assign) NSTimeInterval startTime; -@property (nonatomic, readonly, assign) NSTimeInterval endTime; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAnimation.mm b/platform/darwin/src/gltf/gltfkit/GLTFAnimation.mm deleted file mode 100644 index e716fc0113f5..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFAnimation.mm +++ /dev/null @@ -1,173 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFAnimation.h" -#include "GLTFUtilities.h" -#import "GLTFAccessor.h" -#import "GLTFBufferView.h" -#import "GLTFBuffer.h" -#import "GLTFNode.h" - -@implementation GLTFAnimationSampler - -- (NSString *)description { - return [NSString stringWithFormat:@"%@ interpolation: %d", super.description, (int)self.interpolationMode]; -} - -- (const void *)inputValues { - return (uint8_t*)[self.inputAccessor.bufferView.buffer contents] + self.inputAccessor.bufferView.offset + self.inputAccessor.offset; -} - -- (const void *)outputValues { - return (uint8_t*)[self.outputAccessor.bufferView.buffer contents] + self.outputAccessor.bufferView.offset + self.outputAccessor.offset; -} - -- (int)keyFrameCount { - return (int)self.inputAccessor.count; -} - -@end - -@implementation GLTFAnimationChannel - -- (NSString *)description { - return [NSString stringWithFormat:@"%@ target: %@; path: %@; sampler: %@", super.description, self.targetNode, self.targetPath, self.sampler]; -} - -- (NSTimeInterval)startTime { - GLTFAnimationSampler *sampler = self.sampler; - const float *timeValues = (const float*)sampler.inputValues; - float startTime = timeValues[0]; - return startTime; -} - -- (NSTimeInterval)endTime { - GLTFAnimationSampler *sampler = self.sampler; - const float *timeValues = (const float*)sampler.inputValues; - int keyFrameCount = sampler.keyFrameCount; - float endTime = timeValues[keyFrameCount - 1]; - return endTime; -} - -- (NSTimeInterval)duration { - return self.endTime - self.startTime; -} - -@end - -@implementation GLTFAnimation - -- (NSString *)description { - return [NSString stringWithFormat:@"%@ channels: %@", super.description, self.channels]; -} - -- (void)runAtTime:(NSTimeInterval)time { - for (GLTFAnimationChannel *channel in self.channels) { - GLTFNode *target = channel.targetNode; - NSString *path = channel.targetPath; - GLTFAnimationSampler *sampler = channel.sampler; - - int keyFrameCount = sampler.keyFrameCount; - - const float *timeValues = (const float*)sampler.inputValues; - - float minTime = timeValues[0]; - float maxTime = timeValues[keyFrameCount - 1]; - - if (time < minTime || time > maxTime) { - continue; - } - - int previousKeyFrame = 0, nextKeyFrame = 1; - while (timeValues[nextKeyFrame] < time) { - ++previousKeyFrame; - ++nextKeyFrame; - } - - if (previousKeyFrame >= keyFrameCount) { - previousKeyFrame = 0; - } - - if (nextKeyFrame >= keyFrameCount) { - nextKeyFrame = 0; - } - - float frameTimeDelta = timeValues[nextKeyFrame] - timeValues[previousKeyFrame]; - float timeWithinFrame = time - timeValues[previousKeyFrame]; - float frameProgress = timeWithinFrame / frameTimeDelta; - - if ([path isEqualToString:@"rotation"]) { - if(sampler.outputAccessor.componentType != GLTFDataTypeFloat) { - static dispatch_once_t floatRotationsNonce; - dispatch_once(&floatRotationsNonce, ^{ - NSLog(@"WARNING: Only float accessors are supported for rotation animations. This will only be reported once."); - }); - } - const GLTFQuaternion *rotationValues = (const GLTFQuaternion*)sampler.outputValues; - - GLTFQuaternion previousRotation = rotationValues[previousKeyFrame]; - GLTFQuaternion nextRotation = rotationValues[nextKeyFrame]; - GLTFQuaternion interpRotation = simd_slerp(previousRotation, nextRotation, frameProgress); - - target.rotationQuaternion = interpRotation; - } else if ([path isEqualToString:@"translation"]) { - const GLTFVector3 *translationValues = (const GLTFVector3*)sampler.outputValues; - - GLTFVector3 previousTranslation = translationValues[previousKeyFrame]; - GLTFVector3 nextTranslation = translationValues[nextKeyFrame]; - - GLTFVector3 interpTranslation = (GLTFVector3) { - ((1 - frameProgress) * previousTranslation.x) + (frameProgress * nextTranslation.x), - ((1 - frameProgress) * previousTranslation.y) + (frameProgress * nextTranslation.y), - ((1 - frameProgress) * previousTranslation.z) + (frameProgress * nextTranslation.z) - }; - - target.translation = (simd_float3){ interpTranslation.x, interpTranslation.y, interpTranslation.z }; - } else if ([path isEqualToString:@"scale"]) { - const float *scaleValues = (const float*)sampler.outputValues; - - float previousScale = scaleValues[previousKeyFrame]; - float nextScale = scaleValues[nextKeyFrame]; - - float interpScale = ((1 - frameProgress) * previousScale) + (frameProgress * nextScale); - - target.scale = (simd_float3)interpScale; - } else if ([path isEqualToString:@"weights"]) { - if(sampler.outputAccessor.componentType != GLTFDataTypeFloat) { - static dispatch_once_t floatWeightsNonce; - dispatch_once(&floatWeightsNonce, ^{ - NSLog(@"WARNING: Only scalar float accessors are supported for weight animations. This will only be reported once."); - }); - } - const float *weightValues = (const float*)sampler.outputValues; - - long weightCount = sampler.outputAccessor.count / keyFrameCount; - - const float *previousWeights = weightValues + (previousKeyFrame * weightCount); - const float *nextWeights = weightValues + (nextKeyFrame * weightCount); - - NSMutableArray *interpWeights = [NSMutableArray array]; - for (int i = 0; i < weightCount; ++i) { - float interpWeight = ((1 - frameProgress) * previousWeights[i]) + (frameProgress * nextWeights[i]); - [interpWeights addObject:@(interpWeight)]; - } - - target.morphTargetWeights = [interpWeights copy]; - } - } -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAsset.h b/platform/darwin/src/gltf/gltfkit/GLTFAsset.h deleted file mode 100644 index bbd795d35a70..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFAsset.h +++ /dev/null @@ -1,70 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import - -#import "GLTFEnums.h" -#import "GLTFObject.h" - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFAsset; -@class GLTFScene, GLTFCamera, GLTFAnimation; -@class GLTFKHRLight; -@protocol GLTFBufferAllocator; - -@protocol GLTFAssetLoadingDelegate -- (void)assetWithURL:(NSURL *)assetURL - requiresContentsOfURL:(NSURL *)url - completionHandler:(void (^)(NSData *_Nullable, NSError *_Nullable))completionHandler; -- (void)assetWithURL:(NSURL *)assetURL didFinishLoading:(GLTFAsset *)asset; -- (void)assetWithURL:(NSURL *)assetURL didFailToLoadWithError:(NSError *)error; -@end - -@interface GLTFAsset : NSObject - -@property (nonatomic, readonly, strong) NSArray *scenes; -@property (nonatomic, readonly) GLTFScene *_Nullable defaultScene; - -@property (nonatomic, readonly, strong) NSArray *animations; - -@property (nonatomic, readonly, strong) NSArray *lights; - -@property (nonatomic, readonly, strong) NSArray *cameras; - -@property (nonatomic, copy) NSString *_Nullable generator; -@property (nonatomic, copy) NSString *_Nullable copyright; -@property (nonatomic, copy) NSString *_Nullable formatVersion; - -@property (nonatomic, copy) NSArray *extensionsUsed; - -/// Load an asset asynchronously. The asset may either be a local asset or a remote asset; the -/// provided delegate will receive callbacks requesting the contents of remote URLs referenced by -/// the asset. These callbacks will occur on an arbitrary internal queue. -+ (void)loadAssetWithURL:(NSURL *)url - bufferAllocator:(id)bufferAllocator - delegate:(id)delegate; - -/// Load a local asset. The provided URL must be a file URL, or else loading will fail. -- (instancetype)initWithURL:(NSURL *)url bufferAllocator:(id)bufferAllocator; - -- (void)addLight:(GLTFKHRLight *)light; - -- (void)addCamera:(GLTFCamera *)camera; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAsset.mm b/platform/darwin/src/gltf/gltfkit/GLTFAsset.mm deleted file mode 100644 index ccda5f5ed2d7..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFAsset.mm +++ /dev/null @@ -1,1274 +0,0 @@ - -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFAsset.h" -#include "GLTFEnums.h" -#import "GLTFAnimation.h" -#import "GLTFAccessor.h" -#import "GLTFBinaryChunk.h" -#import "GLTFBuffer.h" -#import "GLTFBufferAllocator.h" -#import "GLTFBufferView.h" -#import "GLTFCamera.h" -#import "GLTFExtensionNames.h" -#import "GLTFImage.h" -#import "GLTFKHRLight.h" -#import "GLTFMaterial.h" -#import "GLTFMesh.h" -#import "GLTFNode.h" -#import "GLTFTexture.h" -#import "GLTFTextureSampler.h" -#import "GLTFScene.h" -#import "GLTFSkin.h" -#import "GLTFUtilities.h" - -#import - -#define USE_AGGRESSIVE_ALIGNMENT 0 - -@interface GLTFAsset () -@property (nonatomic, strong) NSURL *url; -@property (nonatomic, strong) id bufferAllocator; -@property (nonatomic, weak) id delegate; -@property (nonatomic, copy) NSArray *accessors; -@property (nonatomic, copy) NSArray> *buffers; -@property (nonatomic, copy) NSArray *bufferViews; -@property (nonatomic, copy) NSArray *images; -@property (nonatomic, copy) NSArray *samplers; -@property (nonatomic, copy) NSArray *textures; -@property (nonatomic, copy) NSArray *meshes; -@property (nonatomic, copy) NSArray *materials; -@property (nonatomic, strong) NSMutableArray *lights; -@property (nonatomic, strong) NSMutableArray *cameras; -@property (nonatomic, copy) NSArray *nodes; -@property (nonatomic, strong) NSArray *animations; -@property (nonatomic, copy) NSArray *skins; -@property (nonatomic, copy) NSArray *chunks; -@property (nonatomic, strong) GLTFMaterial *defaultMaterial; -@property (nonatomic, strong) GLTFTextureSampler *defaultSampler; -@property (nonatomic, assign) BOOL usesPBRSpecularGlossiness; -@property (nonatomic, assign) BOOL usesEXTPBRAttributes; -@property (nonatomic, assign) BOOL usesKHRLights; -@property (nonatomic, assign) BOOL usesKHRTextureTransform; -@property (nonatomic, assign) BOOL usesKHRMaterialsUnlit; -@end - -@implementation GLTFAsset - -+ (dispatch_queue_t)assetLoaderQueue { - static dispatch_once_t onceToken; - static dispatch_queue_t _assetLoaderQueue; - dispatch_once(&onceToken, ^{ - _assetLoaderQueue = dispatch_queue_create("net.warrenmoore.gltfkit.asset-loader-queue", DISPATCH_QUEUE_CONCURRENT); - }); - return _assetLoaderQueue; -} - -+ (void)loadAssetWithURL:(NSURL *)url bufferAllocator:(id)bufferAllocator delegate:(id)delegate { - dispatch_async(GLTFAsset.assetLoaderQueue, ^{ - (void)[[GLTFAsset alloc] _initWithURL:url bufferAllocator:bufferAllocator delegate:delegate]; - }); -} - -- (instancetype)initWithURL:(NSURL *)url bufferAllocator:(id)bufferAllocator { - return [self _initWithURL:url bufferAllocator:bufferAllocator delegate:nil]; -} - -- (instancetype)_initWithURL:(NSURL *)url bufferAllocator:(id)bufferAllocator delegate:(id)delegate { - if ((self = [super init])) { - _url = url; - _bufferAllocator = bufferAllocator; - _delegate = delegate; - NSError *error = nil; - if (![self loadWithError:&error]) { - [_delegate assetWithURL:_url didFailToLoadWithError:error]; - return nil; - } - } - - [_delegate assetWithURL:_url didFinishLoading:self]; - - return self; -} - -- (void)addLight:(GLTFKHRLight *)light { - [_lights addObject:light]; -} - -- (void)addCamera:(GLTFCamera *)camera { - [_cameras addObject:camera]; -} - -- (NSData *)imageDataForDataURI:(NSString *)uriData { - NSString *prefix = @"data:"; - if ([uriData hasPrefix:prefix]) { - NSInteger prefixEnd = prefix.length; - NSInteger firstComma = [uriData rangeOfString:@","].location; - if (firstComma != NSNotFound) { - NSString *mediaTypeAndTokenString = [uriData substringWithRange:NSMakeRange(prefixEnd, firstComma - prefixEnd)]; - NSArray *mediaTypeAndToken = [mediaTypeAndTokenString componentsSeparatedByString:@";"]; - if (mediaTypeAndToken.count > 0) { - NSString *encodedImageData = [uriData substringFromIndex:firstComma + 1]; - NSData *imageData = [[NSData alloc] initWithBase64EncodedString:encodedImageData - options:NSDataBase64DecodingIgnoreUnknownCharacters]; - return imageData; - } - } - } - return nil; -} - -- (NSData *_Nullable)_contentsOfURL:(NSURL *)url error:(NSError **)error { - __block NSData *urlData = nil; - __block NSError *internalError = nil; - if (![_url isFileURL]) { - dispatch_semaphore_t loadingSemaphore = dispatch_semaphore_create(0); - [_delegate assetWithURL:_url requiresContentsOfURL:url completionHandler:^(NSData *_Nullable data, NSError *_Nullable responseError) { - urlData = data; - internalError = responseError; - dispatch_semaphore_signal(loadingSemaphore); - }]; - dispatch_semaphore_wait(loadingSemaphore, DISPATCH_TIME_FOREVER); - } else { - urlData = [NSData dataWithContentsOfURL:url]; - } - - if (internalError != nil && error != nil) { - *error = internalError; - } - - return urlData; -} - -- (BOOL)loadWithError:(NSError **)errorOrNil { - NSError *error = nil; - NSDictionary *rootObject = nil; - - NSData *assetData = [self _contentsOfURL:_url error:&error]; - if (assetData == nil) { - return NO; - } - - if ([self assetIsGLB:assetData]) { - [self readBinaryChunks:assetData]; - rootObject = [NSJSONSerialization JSONObjectWithData:_chunks.firstObject.data options:0 error:&error]; - } else { - rootObject = [NSJSONSerialization JSONObjectWithData:assetData options:0 error:&error]; - } - - if (!rootObject) { - if (errorOrNil) { *errorOrNil = error; } - return NO; - } - - _extensionsUsed = [rootObject[@"extensionsUsed"] ?: @[] copy]; - - [self toggleExtensionFeatureFlags]; - - _defaultSampler = [GLTFTextureSampler new]; - - _defaultMaterial = [GLTFMaterial new]; - - _lights = [NSMutableArray array]; - - _cameras = [NSMutableArray array]; - - // Since we aren't streaming, we have the properties for all objects in memory - // and we can load in the order that makes the least work for us, i.e. by - // reducing the number of name resolutions we have to do after we deserialize - // everything into glTF objects. The only object subgraph that can't be - // resolved by careful ordering of loading is the subgraph of nodes itself, - // which is stored unordered and may contain arbitrary node-node relationships. - // Therefore, we run a post-load fix-up pass to resolve all node graph edges - // into real object references. Refer to `fixNodeRelationships` below. - - [self loadAssetProperties:rootObject[@"asset"]]; - [self loadBuffers:rootObject[@"buffers"]]; - [self loadBufferViews:rootObject[@"bufferViews"]]; - [self loadAccessors:rootObject[@"accessors"]]; - [self loadSamplers:rootObject[@"samplers"]]; - [self loadImages:rootObject[@"images"]]; - [self loadTextures:rootObject[@"textures"]]; - [self loadMaterials:rootObject[@"materials"]]; - if (_usesKHRLights) { - NSDictionary *extensionProperties = rootObject[@"extensions"][GLTFExtensionKHRLights]; - NSArray *lightsProperties = extensionProperties[@"lights"]; - [self loadLights:lightsProperties]; - } - [self loadCameras:rootObject[@"cameras"]]; - [self loadSkins:rootObject[@"skins"]]; - [self loadMeshes:rootObject[@"meshes"]]; - [self loadNodes:rootObject[@"nodes"]]; - [self loadAnimations:rootObject[@"animations"]]; - [self loadScenes:rootObject[@"scenes"]]; - [self loadDefaultScene:rootObject[@"scene"]]; - - return YES; -} - -- (void)toggleExtensionFeatureFlags { - for (NSString *extension in _extensionsUsed) { - if ([extension isEqualToString:GLTFExtensionKHRMaterialsPBRSpecularGlossiness]) { - NSLog(@"WARNING: Extension \"%@\" is not fully supported", extension); - _usesPBRSpecularGlossiness = YES; - } else if ([extension isEqualToString:GLTFExtensionEXTPBRAttributes]) { - _usesEXTPBRAttributes = YES; - } else if ([extension isEqualToString:GLTFExtensionKHRLights]) { - _usesKHRLights = YES; - } else if ([extension isEqualToString:GLTFExtensionKHRMaterialsUnlit]) { - _usesKHRMaterialsUnlit = YES; - } else if ([extension isEqualToString:GLTFExtensionKHRTextureTransform]) { - _usesKHRTextureTransform = YES; - } else { - NSLog(@"WARNING: Unsupported extension \"%@\" used", extension); - } - } -} - -- (BOOL)assetIsGLB:(NSData *)assetData { - if (assetData.length < sizeof(GLTFBinaryHeader)) { - return NO; - } else { - GLTFBinaryHeader header; - [assetData getBytes:&header length:sizeof(header)]; - return (header.magic == GLTFBinaryMagic); - } -} - -- (void)readBinaryChunks:(NSData *)assetData { - NSMutableArray *chunks = [NSMutableArray array]; - - GLTFBinaryHeader header; - [assetData getBytes:&header length:sizeof(GLTFBinaryHeader)]; - - NSUInteger offset = sizeof(GLTFBinaryHeader); - while (offset < header.length && offset < assetData.length) { - GLTFBinaryChunk *chunk = [GLTFBinaryChunk new]; - struct { - UInt32 length; - UInt32 type; - } chunkHeader; - - [assetData getBytes:&chunkHeader range:NSMakeRange(offset, sizeof(chunkHeader))]; - - NSData *chunkData = [NSData dataWithBytesNoCopy:(void *)((uint8_t*)assetData.bytes + offset + sizeof(chunkHeader)) - length:chunkHeader.length - freeWhenDone:NO]; - chunk.data = chunkData; - chunk.chunkType = (GLTFChunkType)chunkHeader.type; - - [chunks addObject:chunk]; - - offset += sizeof(chunkHeader) + chunkHeader.length; - } - - _chunks = [chunks copy]; - - NSAssert(_chunks.firstObject.chunkType == GLTFChunkTypeJSON, @"First chunk in GLB file had type %u rather than expected %u", - (unsigned int)_chunks.firstObject.chunkType, (unsigned int)GLTFChunkTypeJSON); -} - -- (BOOL)loadAssetProperties:(NSDictionary *)propertiesMap { - _generator = [propertiesMap[@"generator"] copy]; - _copyright = [propertiesMap[@"copyright"] copy]; - _formatVersion = propertiesMap[@"version"] ?: @"2.0"; - return YES; -} - -- (BOOL)loadAccessors:(NSArray *)accessorsMap { - if (accessorsMap.count == 0) { - _accessors = @[]; - return YES; - } - - NSMutableArray *accessors = [NSMutableArray arrayWithCapacity:accessorsMap.count]; - for (NSDictionary *properties in accessorsMap) { - GLTFAccessor *accessor = [[GLTFAccessor alloc] init]; - accessor.componentType = (GLTFDataType)[properties[@"componentType"] integerValue]; - accessor.dimension = GLTFDataDimensionForName(properties[@"type"]); - accessor.offset = [properties[@"byteOffset"] integerValue]; - accessor.count = [properties[@"count"] integerValue]; - NSUInteger bufferViewIndex = [properties[@"bufferView"] intValue]; - if (bufferViewIndex < _bufferViews.count) { - accessor.bufferView = _bufferViews[bufferViewIndex]; -#if USE_AGGRESSIVE_ALIGNMENT - size_t alignment = GLTFSizeOfComponentTypeWithDimension(accessor.componentType, accessor.dimension); -#else - size_t alignment = GLTFSizeOfDataType(accessor.componentType); -#endif - NSInteger dataOffset = accessor.offset + accessor.bufferView.offset; - if (dataOffset % alignment != 0) { - size_t elementSize = GLTFSizeOfComponentTypeWithDimension(accessor.componentType, accessor.dimension); - size_t length = accessor.count * elementSize; - NSLog(@"WARNING: Accessor had misaligned offset %d, which is not a multiple of %d. Building auxiliary buffer of length %d and continuing...", - (int)dataOffset, (int)alignment, (int)length); - id buffer = [_bufferAllocator newBufferWithLength:length]; - memcpy(buffer.contents, (uint8_t*)accessor.bufferView.buffer.contents + accessor.bufferView.offset + accessor.offset, buffer.length); - _buffers = [_buffers arrayByAddingObject:buffer]; - - GLTFBufferView *bufferView = [GLTFBufferView new]; - bufferView.buffer = buffer; - bufferView.offset = 0; - bufferView.stride = 0; - _bufferViews = [_bufferViews arrayByAddingObject:bufferView]; - - accessor.bufferView = bufferView; - accessor.offset = 0; - } - } - - __block GLTFValueRange valueRange = { {}, {} }; - NSArray *minValues = properties[@"min"]; - [minValues enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger index, BOOL *stop) { - valueRange.minValue[index] = num.floatValue; - }]; - NSArray *maxValues = properties[@"max"]; - [maxValues enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger index, BOOL *stop) { - valueRange.maxValue[index] = num.floatValue; - }]; - accessor.valueRange = valueRange; - - [accessors addObject:accessor]; - } - - _accessors = [accessors copy]; - - return YES; -} - -- (BOOL)loadBuffers:(NSArray *)buffersMap { - if (buffersMap.count == 0) { - _buffers = @[]; - } - - NSMutableArray *buffers = [NSMutableArray arrayWithCapacity:buffersMap.count]; - for (NSDictionary *properties in buffersMap) { - NSInteger byteLength = [properties[@"byteLength"] integerValue]; - - NSString *uri = properties[@"uri"]; - NSData *data = nil; - - if ([uri hasPrefix:@"data:"]) { - if ([uri hasPrefix:@"data:application/octet-stream;base64,"]) { - NSString *dataSubstring = [uri substringFromIndex:[@"data:application/octet-stream;base64," length]]; - data = [[NSData alloc] initWithBase64EncodedString:dataSubstring options:0]; - } else { - NSLog(@"WARNING: Encountered URL-encoded buffer that did not have the expected MIME type or encoding. Skipping..."); - continue; - } - } else if (uri.length > 0) { - NSURL *bufferURL = [[_url URLByDeletingLastPathComponent] URLByAppendingPathComponent:uri]; - NSError *error = nil; - data = [self _contentsOfURL:bufferURL error:&error]; - NSAssert(data != nil, @"Unable to load data at URL %@; error %@", bufferURL, error); - } else if (_chunks.count > 1) { - data = _chunks[1].data; - } else { - NSLog(@"WARNING: Encountered buffer which was not URL-encoded, nor a file reference, nor a GLB chunk reference. Skipping..."); - continue; - } - - id buffer = [_bufferAllocator newBufferWithData:data]; - - if (byteLength != [buffer length]) { - NSLog(@"WARNING: Expected to load buffer of length %lu bytes; got %lu bytes", (unsigned long)byteLength, (unsigned long)[buffer length]); - } - [buffers addObject: buffer]; - } - - _buffers = [buffers copy]; - return YES; -} - -- (BOOL)loadBufferViews:(NSArray *)bufferViewsMap { - if (bufferViewsMap.count == 0) { - _bufferViews = @[]; - } - - NSMutableArray *bufferViews = [NSMutableArray arrayWithCapacity:bufferViewsMap.count]; - [bufferViewsMap enumerateObjectsUsingBlock:^(NSDictionary *properties, NSUInteger index, BOOL *stop) { - - GLTFBufferView *bufferView = [[GLTFBufferView alloc] init]; - NSUInteger bufferIndex = [properties[@"buffer"] intValue]; - if (bufferIndex < _buffers.count) { - bufferView.buffer = _buffers[bufferIndex]; - } - bufferView.length = [properties[@"byteLength"] integerValue]; - bufferView.stride = [properties[@"byteStride"] integerValue]; - bufferView.offset = [properties[@"byteOffset"] integerValue]; - bufferView.target = (GLTFTarget)[properties[@"target"] integerValue]; - -// if ((bufferView.buffer != nil) && (bufferView.offset % 16 != 0)) { -// NSLog(@"WARNING: Buffer view %d had misaligned offset of %d. Creating auxilliary buffer of length %d and continuing...", -// (int)index, (int)bufferView.offset, (int)bufferView.length); -// id alignedBuffer = [_bufferAllocator newBufferWithLength:bufferView.length]; -// _buffers = [_buffers arrayByAddingObject:alignedBuffer]; -// memcpy([alignedBuffer contents], bufferView.buffer.contents + bufferView.offset, bufferView.length); -// bufferView.buffer = alignedBuffer; -// bufferView.offset = 0; -// } - - [bufferViews addObject: bufferView]; - }]; - - _bufferViews = [bufferViews copy]; - return YES; -} - -- (BOOL)loadSamplers:(NSArray *)samplersMap { - if (samplersMap.count == 0) { - _samplers = @[]; - } - - NSMutableArray *samplers = [NSMutableArray arrayWithCapacity:samplersMap.count]; - for (NSDictionary *properties in samplersMap) { - GLTFTextureSampler *sampler = [[GLTFTextureSampler alloc] init]; - sampler.minFilter = (GLTFSamplingFilter)([properties[@"minFilter"] integerValue] ?: sampler.minFilter); - sampler.magFilter = (GLTFSamplingFilter)([properties[@"magFilter"] integerValue] ?: sampler.magFilter); - sampler.sAddressMode = (GLTFAddressMode)([properties[@"wrapS"] integerValue] ?: sampler.sAddressMode); - sampler.tAddressMode = (GLTFAddressMode)([properties[@"wrapT"] integerValue] ?: sampler.tAddressMode); - sampler.name = properties[@"name"]; - sampler.extensions = properties[@"extensions"]; - sampler.extras = properties[@"extras"]; - - [samplers addObject:sampler]; - } - - _samplers = [samplers copy]; - return YES; -} - -- (BOOL)loadImages:(NSArray *)imagesMap { - if (imagesMap.count == 0) { - _images = @[]; - } - - NSMutableArray *images = [NSMutableArray arrayWithCapacity:imagesMap.count]; - for (NSDictionary *properties in imagesMap) { - GLTFImage *image = [[GLTFImage alloc] init]; - - NSString *uri = properties[@"uri"]; - - if ([uri hasPrefix:@"data:image/"]) { - image.imageData = [self imageDataForDataURI:uri]; - } else if (uri.length > 0) { - NSURL *resourceURL = [self.url URLByDeletingLastPathComponent]; - image.url = [resourceURL URLByAppendingPathComponent:uri]; - } - - image.mimeType = properties[@"mimeType"]; - - NSString *bufferViewIndexString = properties[@"bufferView"]; - if (bufferViewIndexString) { - NSUInteger bufferViewIndex = bufferViewIndexString.integerValue; - if (bufferViewIndex < _bufferViews.count) { - image.bufferView = _bufferViews[bufferViewIndex]; - } - } - - image.name = properties[@"name"]; - image.extensions = properties[@"extensions"]; - image.extras = properties[@"extras"]; - - [images addObject:image]; - } - - _images = [images copy]; - return YES; -} - -- (BOOL)loadTextures:(NSArray *)texturesMap { - if (texturesMap.count == 0) { - _textures = @[]; - } - - NSMutableArray *textures = [NSMutableArray arrayWithCapacity:texturesMap.count]; - for (NSDictionary *properties in texturesMap) { - GLTFTexture *texture = [[GLTFTexture alloc] init]; - - NSUInteger samplerIndex = [properties[@"sampler"] intValue]; - if (samplerIndex < _samplers.count) { - texture.sampler = _samplers[samplerIndex]; - } else { - texture.sampler = _defaultSampler; - } - - NSUInteger imageIndex = [properties[@"source"] intValue]; - if (imageIndex < _images.count) { - texture.image = _images[imageIndex]; - } - - texture.format = (GLTFTextureFormat)([properties[@"format"] integerValue] ?: texture.format); - texture.internalFormat = (GLTFTextureFormat)([properties[@"internalFormat"] integerValue] ?: texture.internalFormat); - texture.target = (GLTFTextureTarget)([properties[@"target"] integerValue] ?: texture.target); - texture.type = (GLTFTextureType)([properties[@"type"] integerValue] ?: texture.type); - texture.name = properties[@"name"]; - texture.extensions = properties[@"extensions"]; - texture.extras = properties[@"extras"]; - - [textures addObject: texture]; - } - - _textures = [textures copy]; - return YES; -} - - -- (BOOL)loadCameras:(NSArray *)camerasMap { - if (camerasMap.count == 0) { - _cameras = [NSMutableArray array]; - return YES; - } - - _cameras = [NSMutableArray arrayWithCapacity:camerasMap.count]; - for (NSDictionary *properties in camerasMap) { - GLTFCamera *camera = [[GLTFCamera alloc] init]; - - camera.cameraType = [properties[@"type"] isEqualToString:@"orthographic"] ? GLTFCameraTypeOrthographic : GLTFCameraTypePerspective; - - NSDictionary *params = properties[properties[@"type"]]; - - switch (camera.cameraType) { - case GLTFCameraTypeOrthographic: - camera.xmag = [params[@"xmag"] floatValue]; - camera.ymag = [params[@"ymag"] floatValue]; - break; - case GLTFCameraTypePerspective: - default: { - NSNumber *aspectRatioValue = params[@"aspectRatio"]; - camera.aspectRatio = (aspectRatioValue != nil) ? aspectRatioValue.floatValue : 1.0; - camera.yfov = [params[@"yfov"] floatValue]; - break; - } - } - - camera.znear = [params[@"znear"] floatValue]; - - if (camera.cameraType == GLTFCameraTypePerspective && (params[@"zfar"] == nil)) { - camera.zfar = FLT_MAX; - } else { - camera.zfar = [params[@"zfar"] floatValue]; - } - - camera.extensions = properties[@"extensions"]; - camera.extras = properties[@"extras"]; - - [_cameras addObject: camera]; - } - - return YES; -} - -- (BOOL)loadLights:(NSArray *)lightsMap { - if (lightsMap.count == 0) { - return YES; - } - - _lights = [NSMutableArray arrayWithCapacity:lightsMap.count]; - [lightsMap enumerateObjectsUsingBlock:^(NSDictionary *properties, NSUInteger index, BOOL *stop) { - GLTFKHRLight *light = [GLTFKHRLight new]; - NSString *lightTypeName = properties[@"type"]; - if ([lightTypeName isEqualToString:@"ambient"]) { - light.type = GLTFKHRLightTypeAmbient; - } else if ([lightTypeName isEqualToString:@"directional"]) { - light.type = GLTFKHRLightTypeDirectional; - } else if ([lightTypeName isEqualToString:@"point"]) { - light.type = GLTFKHRLightTypePoint; - } else if ([lightTypeName isEqualToString:@"spot"]) { - light.type = GLTFKHRLightTypeSpot; - } - - NSArray *colorArray = properties[@"color"]; - switch ([colorArray count]) { - case 3: // This is out of spec, but it happens in the wild, so be graceful. - light.color = GLTFVectorFloat4FromArray([colorArray arrayByAddingObject:@(1)]); - break; - case 4: - light.color = GLTFVectorFloat4FromArray(colorArray); - break; - } - - NSNumber *intensityValue = properties[@"intensity"]; - if (intensityValue != nil) { - light.intensity = [intensityValue floatValue]; - } - - if (light.type == GLTFKHRLightTypeSpot) { - NSDictionary *spotProperties = properties[@"spot"]; - NSNumber *innerConeAngleValue = spotProperties[@"innerConeAngle"]; - if (innerConeAngleValue != nil) { - light.innerConeAngle = [innerConeAngleValue floatValue]; - } - NSNumber *outerConeAngleValue = spotProperties[@"outerConeAngle"]; - if (outerConeAngleValue != nil) { - light.outerConeAngle = [outerConeAngleValue floatValue]; - } - } - - [_lights addObject:light]; - }]; - - return YES; -} - -- (BOOL)loadMeshes:(NSArray *)meshesMap { - if (meshesMap.count == 0) { - _meshes = @[]; - } - - NSMutableArray *meshes = [NSMutableArray arrayWithCapacity:meshesMap.count]; - for (NSDictionary *properties in meshesMap) { - GLTFMesh *mesh = [[GLTFMesh alloc] init]; - mesh.name = properties[@"name"]; - mesh.extensions = properties[@"extensions"]; - mesh.extras = properties[@"extras"]; - - mesh.defaultMorphTargetWeights = properties[@"weights"] ?: @[]; - - NSArray *submeshesProperties = properties[@"primitives"]; - NSMutableArray *submeshes = [NSMutableArray arrayWithCapacity:submeshesProperties.count]; - for (NSDictionary *submeshProperties in submeshesProperties) { - GLTFSubmesh *submesh = [[GLTFSubmesh alloc] init]; - - NSDictionary *submeshAttributes = submeshProperties[@"attributes"]; - - NSMutableDictionary *attributeAccessors = [NSMutableDictionary dictionaryWithCapacity:submeshAttributes.count]; - [submeshAttributes enumerateKeysAndObjectsUsingBlock:^(NSString *attributeName, NSNumber *accessorIndexValue, BOOL *stop) { - NSUInteger accessorIndex = accessorIndexValue.unsignedIntegerValue; - if (accessorIndex < _accessors.count) { - GLTFAccessor *accessor = _accessors[accessorIndex]; - attributeAccessors[attributeName] = accessor; - } - }]; - - submesh.accessorsForAttributes = attributeAccessors; - - NSUInteger materialIndex = [submeshProperties[@"material"] intValue]; - if (materialIndex < _materials.count) { - submesh.material = _materials[materialIndex]; - } else { - submesh.material = _defaultMaterial; - } - - NSUInteger indexAccessorIndex = [submeshProperties[@"indices"] intValue]; - if (indexAccessorIndex < _accessors.count) { - GLTFAccessor *indexAccessor = _accessors[indexAccessorIndex]; - if (indexAccessor.componentType == (GLTFDataType)GLTFTextureTypeUChar) { - // Fix up 8-bit indices, since they're unsupported in modern APIs - uint8_t *sourceIndices = (uint8_t*)indexAccessor.bufferView.buffer.contents + indexAccessor.offset + indexAccessor.bufferView.offset; - - id shortBuffer = [_bufferAllocator newBufferWithLength:indexAccessor.count * sizeof(uint16_t)]; - uint16_t *destIndices = (uint16_t*)shortBuffer.contents; - for (int i = 0; i < indexAccessor.count; ++i) { - destIndices[i] = (uint16_t)sourceIndices[i]; - } - _buffers = [_buffers arrayByAddingObject:shortBuffer]; - - GLTFBufferView *shortBufferView = [GLTFBufferView new]; - shortBufferView.buffer = shortBuffer; - shortBufferView.offset = 0; - shortBufferView.stride = 0; - _bufferViews = [_bufferViews arrayByAddingObject:shortBufferView]; - - GLTFAccessor *shortAccessor = [GLTFAccessor new]; - shortAccessor.bufferView = shortBufferView; - shortAccessor.componentType = GLTFDataTypeUShort; - shortAccessor.dimension = GLTFDataDimensionScalar; - shortAccessor.count = indexAccessor.count; - shortAccessor.offset = 0; - shortAccessor.valueRange = indexAccessor.valueRange; - _accessors = [_accessors arrayByAddingObject:shortAccessor]; - - indexAccessor = shortAccessor; - } - submesh.indexAccessor = indexAccessor; - } - - if (submeshProperties[@"mode"]) { - submesh.primitiveType = (GLTFPrimitiveType)[submeshProperties[@"mode"] intValue]; - } - - NSMutableArray *morphTargets = [NSMutableArray array]; - for (NSDictionary *targetProperties in submeshProperties[@"targets"]) { - GLTFMorphTarget *morphTarget = [GLTFMorphTarget new]; - NSMutableDictionary *attributeAccessors = [NSMutableDictionary dictionaryWithCapacity:submeshAttributes.count]; - [targetProperties enumerateKeysAndObjectsUsingBlock:^(NSString *attributeName, NSNumber *accessorIndexValue, BOOL *stop) { - NSUInteger accessorIndex = accessorIndexValue.unsignedIntegerValue; - if (accessorIndex < _accessors.count) { - GLTFAccessor *accessor = _accessors[accessorIndex]; - attributeAccessors[attributeName] = accessor; - } - }]; - morphTarget.accessorsForAttributes = [attributeAccessors copy]; - [morphTargets addObject:morphTarget]; - } - submesh.morphTargets = [morphTargets copy]; - - [submeshes addObject:submesh]; - } - - mesh.submeshes = [submeshes copy]; - - [meshes addObject:mesh]; - } - - _meshes = [meshes copy]; - return YES; -} - - -- (BOOL)loadMaterials:(NSArray *)materialsMap { - if (materialsMap.count == 0) { - _materials = @[]; - return YES; - } - - NSMutableArray *materials = [NSMutableArray arrayWithCapacity:materialsMap.count]; - for (NSDictionary *properties in materialsMap) { - GLTFMaterial *material = [[GLTFMaterial alloc] init]; - - NSDictionary *pbrValuesMap = properties[@"pbrMetallicRoughness"]; - if (pbrValuesMap) { - NSDictionary *baseColorTextureMap = pbrValuesMap[@"baseColorTexture"]; - NSNumber *baseColorTextureIndexValue = baseColorTextureMap[@"index"]; - if (baseColorTextureIndexValue != nil) { - material.baseColorTexture = [[GLTFTextureInfo alloc] init]; - NSUInteger baseColorTextureIndex = baseColorTextureIndexValue.integerValue; - if (baseColorTextureIndex < _textures.count) { - material.baseColorTexture.texture = _textures[baseColorTextureIndex]; - } - } - NSNumber *baseColorTexCoordValue = baseColorTextureMap[@"texCoord"]; - if (baseColorTexCoordValue != nil) { - material.baseColorTexture.texCoord = baseColorTexCoordValue.integerValue; - } - - material.baseColorTexture.extras = baseColorTextureMap[@"extras"]; - material.baseColorTexture.extensions = baseColorTextureMap[@"extensions"]; - - NSArray *baseColorFactorComponents = pbrValuesMap[@"baseColorFactor"]; - if (baseColorFactorComponents.count == 4) { - material.baseColorFactor = GLTFVectorFloat4FromArray(baseColorFactorComponents); - } - - NSNumber *metallicFactor = pbrValuesMap[@"metallicFactor"]; - if (metallicFactor != nil) { - material.metalnessFactor = metallicFactor.floatValue; - } - - NSNumber *roughnessFactor = pbrValuesMap[@"roughnessFactor"]; - if (roughnessFactor != nil) { - material.roughnessFactor = roughnessFactor.floatValue; - } - - NSDictionary *metallicRoughnessTextureMap = pbrValuesMap[@"metallicRoughnessTexture"]; - NSNumber *metallicRoughnessTextureIndexValue = metallicRoughnessTextureMap[@"index"]; - if (metallicRoughnessTextureIndexValue != nil) { - material.metallicRoughnessTexture = [[GLTFTextureInfo alloc] init]; - NSUInteger metallicRoughnessTextureIndex = metallicRoughnessTextureIndexValue.integerValue; - if (metallicRoughnessTextureIndex < _textures.count) { - material.metallicRoughnessTexture.texture = _textures[metallicRoughnessTextureIndex]; - } - } - - NSNumber *metallicRoughnessTexCoordValue = metallicRoughnessTextureMap[@"texCoord"]; - if (metallicRoughnessTexCoordValue != nil) { - material.metallicRoughnessTexture.texCoord = metallicRoughnessTexCoordValue.integerValue; - } - - material.metallicRoughnessTexture.extras = metallicRoughnessTextureMap[@"extras"]; - material.metallicRoughnessTexture.extensions = metallicRoughnessTextureMap[@"extensions"]; - } - - NSDictionary *normalTextureMap = properties[@"normalTexture"]; - if (normalTextureMap) { - material.normalTexture = [[GLTFTextureInfo alloc] init]; - NSNumber *normalTextureIndexValue = normalTextureMap[@"index"]; - NSUInteger normalTextureIndex = normalTextureIndexValue.integerValue; - if (normalTextureIndex < _textures.count) { - material.normalTexture.texture = _textures[normalTextureIndex]; - } - NSNumber *normalTextureScaleValue = normalTextureMap[@"scale"]; - material.normalTextureScale = (normalTextureScaleValue != nil) ? normalTextureScaleValue.floatValue : 1.0; - - NSNumber *normalTexCoordValue = normalTextureMap[@"texCoord"]; - if (normalTexCoordValue != nil) { - material.normalTexture.texCoord = normalTexCoordValue.integerValue; - } - - material.normalTexture.extras = normalTextureMap[@"extras"]; - material.normalTexture.extensions = normalTextureMap[@"extensions"]; - } - - NSDictionary *emissiveTextureMap = properties[@"emissiveTexture"]; - if (emissiveTextureMap) { - material.emissiveTexture = [[GLTFTextureInfo alloc] init]; - NSNumber *emissiveTextureIndexValue = emissiveTextureMap[@"index"]; - NSUInteger emissiveTextureIndex = emissiveTextureIndexValue.integerValue; - if (emissiveTextureIndex < _textures.count) { - material.emissiveTexture.texture = _textures[emissiveTextureIndex]; - } - NSNumber *emissiveTexCoordValue = emissiveTextureMap[@"texCoord"]; - if (emissiveTexCoordValue != nil) { - material.emissiveTexture.texCoord = emissiveTexCoordValue.integerValue; - } - - material.emissiveTexture.extras = emissiveTextureMap[@"extras"]; - material.emissiveTexture.extensions = emissiveTextureMap[@"extensions"]; - } - - NSArray *emissiveFactorArray = properties[@"emissiveFactor"]; - if (emissiveFactorArray.count == 3) { - material.emissiveFactor = GLTFVectorFloat3FromArray(emissiveFactorArray); - } - - NSDictionary *occlusionTextureMap = properties[@"occlusionTexture"]; - if (occlusionTextureMap) { - material.occlusionTexture = [[GLTFTextureInfo alloc] init]; - NSNumber *occlusionTextureIndexValue = occlusionTextureMap[@"index"]; - NSUInteger occlusionTextureIndex = occlusionTextureIndexValue.integerValue; - if (occlusionTextureIndex < _textures.count) { - material.occlusionTexture.texture = _textures[occlusionTextureIndex]; - } - NSNumber *occlusionTexCoordValue = occlusionTextureMap[@"texCoord"]; - if (occlusionTexCoordValue != nil) { - material.occlusionTexture.texCoord = occlusionTexCoordValue.integerValue; - } - NSNumber *occlusionStrengthValue = occlusionTextureMap[@"strength"]; - if (occlusionStrengthValue != nil) { - material.occlusionStrength = occlusionStrengthValue.floatValue; - } - - material.occlusionTexture.extras = occlusionTextureMap[@"extras"]; - material.occlusionTexture.extensions = occlusionTextureMap[@"extensions"]; - } - - NSNumber *doubleSidedValue = properties[@"doubleSided"]; - material.doubleSided = (doubleSidedValue == nil) || (doubleSidedValue != nil && doubleSidedValue.boolValue); - - NSString *alphaMode = properties[@"alphaMode"]; - if ([alphaMode isEqualToString:@"BLEND"]) { - material.alphaMode = GLTFAlphaModeBlend; - } else if ([alphaMode isEqualToString:@"MASK"]) { - material.alphaMode = GLTFAlphaModeMask; - } else { - material.alphaMode = GLTFAlphaModeOpaque; - } - - NSNumber *alphaCutoffValue = properties[@"alphaCutoff"]; - if (alphaCutoffValue != nil) { - material.alphaCutoff = alphaCutoffValue.floatValue; - } - - material.name = properties[@"name"]; - material.extensions = properties[@"extensions"]; - material.extras = properties[@"extras"]; - - if (_usesPBRSpecularGlossiness) { - NSDictionary *pbrSpecularGlossinessProperties = material.extensions[GLTFExtensionKHRMaterialsPBRSpecularGlossiness]; - if (pbrSpecularGlossinessProperties != nil) { - NSDictionary *diffuseTextureMap = pbrSpecularGlossinessProperties[@"diffuseTexture"]; - if (diffuseTextureMap != nil) { - material.baseColorTexture = [[GLTFTextureInfo alloc] init]; - - NSNumber *diffuseTextureIndexValue = diffuseTextureMap[@"index"]; - if (diffuseTextureIndexValue != nil) { - NSUInteger diffuseTextureIndex = diffuseTextureIndexValue.integerValue; - if (diffuseTextureIndex < _textures.count) { - material.baseColorTexture.texture = _textures[diffuseTextureIndex]; - } - } - NSNumber *diffuseTexCoordValue = diffuseTextureMap[@"texCoord"]; - if (diffuseTexCoordValue != nil) { - material.baseColorTexture.texCoord = diffuseTexCoordValue.integerValue; - } - } - - // TODO: Support specularGlossinessTexture - - // TODO: Support texture transform of specular-glossiness map - - NSArray *diffuseFactorComponents = pbrSpecularGlossinessProperties[@"diffuseFactor"]; - if (diffuseFactorComponents.count == 4) { - material.baseColorFactor = GLTFVectorFloat4FromArray(diffuseFactorComponents); - } - - NSNumber *glossinessFactorValue = pbrSpecularGlossinessProperties[@"glossinessFactor"]; - material.glossinessFactor = (glossinessFactorValue != nil) ? glossinessFactorValue.floatValue : 0.0; - - NSArray *specularFactorComponents = pbrSpecularGlossinessProperties[@"specularFactor"]; - if (specularFactorComponents.count == 3) { - material.specularFactor = GLTFVectorFloat3FromArray(specularFactorComponents); - } - } - } - - if (_usesKHRMaterialsUnlit) { - NSDictionary *unlitMap = material.extensions[GLTFExtensionKHRMaterialsUnlit]; - if (unlitMap != nil) { - material.unlit = YES; - } - } - - if (_usesKHRTextureTransform) { - [self _fixMaterialTextureTransforms:material]; - } - - [materials addObject: material]; - } - - _materials = [materials copy]; - - return YES; -} - -- (GLTFTextureTransform)_textureTransformWithProperties:(NSDictionary *)properties { - GLTFTextureTransform transform = GLTFTextureTransformMakeIdentity(); - NSArray *offsetArray = properties[@"offset"]; - if (offsetArray != nil && offsetArray.count == 2) { - transform.offset = GLTFVectorFloat2FromArray(offsetArray); - } - NSNumber *rotationValue = properties[@"rotation"]; - if (rotationValue != nil) { - transform.rotation = rotationValue.floatValue; - } - NSArray *scaleArray = properties[@"scale"]; - if (scaleArray != nil && scaleArray.count == 2) { - transform.scale = GLTFVectorFloat2FromArray(scaleArray); - } - return transform; -} - -- (void)_fixMaterialTextureTransforms:(GLTFMaterial *)material { - NSDictionary *baseColorTransformProperties = material.baseColorTexture.extensions[GLTFExtensionKHRTextureTransform]; - if (baseColorTransformProperties != nil) { - material.baseColorTexture.transform = [self _textureTransformWithProperties:baseColorTransformProperties]; - NSNumber *texCoordValue = baseColorTransformProperties[@"texCoord"]; - if (texCoordValue != nil) { - material.baseColorTexture.texCoord = texCoordValue.intValue; - } - } - NSDictionary *normalTransformProperties = material.normalTexture.extensions[GLTFExtensionKHRTextureTransform]; - if (normalTransformProperties != nil) { - material.normalTexture.transform = [self _textureTransformWithProperties:normalTransformProperties]; - NSNumber *texCoordValue = normalTransformProperties[@"texCoord"]; - if (texCoordValue != nil) { - material.normalTexture.texCoord = texCoordValue.intValue; - } - } - NSDictionary *metallicRoughnessTransformProperties = material.metallicRoughnessTexture.extensions[GLTFExtensionKHRTextureTransform]; - if (metallicRoughnessTransformProperties != nil) { - material.metallicRoughnessTexture.transform = [self _textureTransformWithProperties:metallicRoughnessTransformProperties]; - NSNumber *texCoordValue = metallicRoughnessTransformProperties[@"texCoord"]; - if (texCoordValue != nil) { - material.metallicRoughnessTexture.texCoord = texCoordValue.intValue; - } - } - NSDictionary *occlusionTransformProperties = material.occlusionTexture.extensions[GLTFExtensionKHRTextureTransform]; - if (occlusionTransformProperties != nil) { - material.occlusionTexture.transform = [self _textureTransformWithProperties:occlusionTransformProperties]; - NSNumber *texCoordValue = occlusionTransformProperties[@"texCoord"]; - if (texCoordValue != nil) { - material.occlusionTexture.texCoord = texCoordValue.intValue; - } - } - NSDictionary *emissiveTransformProperties = material.emissiveTexture.extensions[GLTFExtensionKHRTextureTransform]; - if (emissiveTransformProperties != nil) { - material.emissiveTexture.transform = [self _textureTransformWithProperties:emissiveTransformProperties]; - NSNumber *texCoordValue = emissiveTransformProperties[@"texCoord"]; - if (texCoordValue != nil) { - material.emissiveTexture.texCoord = texCoordValue.intValue; - } - } - - material.hasTextureTransforms = YES; -} - -- (BOOL)loadNodes:(NSArray *)nodesMap { - if (nodesMap.count == 0) { - _nodes = @[]; - return YES; - } - - NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:nodesMap.count]; - for (NSDictionary *properties in nodesMap) { - GLTFNode *node = [[GLTFNode alloc] init]; - - NSString *cameraIdentifierString = properties[@"camera"]; - if (cameraIdentifierString) { - NSUInteger cameraIndex = cameraIdentifierString.integerValue; - if (cameraIndex < _cameras.count) { - GLTFCamera *camera = _cameras[cameraIndex]; - node.camera = camera; - camera.referencingNodes = [camera.referencingNodes arrayByAddingObject:node]; - } - } - - // Copy array of indices for now; we fix this up later in another pass once all nodes are in memory. - node.children = [properties[@"children"] copy]; - - NSNumber *skinIndexValue = properties[@"skin"]; - if (skinIndexValue != nil) { - NSUInteger skinIndex = skinIndexValue.integerValue; - if (skinIndex < _skins.count) { - node.skin = _skins[skinIndex]; - } - } - - node.jointName = properties[@"jointName"]; - - NSNumber *meshIndexValue = properties[@"mesh"]; - if (meshIndexValue != nil) { - NSUInteger meshIndex = meshIndexValue.integerValue; - if (meshIndex < _meshes.count) { - node.mesh = _meshes[meshIndex]; - } - } - - NSArray *matrixArray = properties[@"matrix"]; - if (matrixArray) { - node.localTransform = GLTFMatrixFloat4x4FromArray(matrixArray); - } - - NSArray *rotationArray = properties[@"rotation"]; - if (rotationArray) { - node.rotationQuaternion = GLTFQuaternionFromArray(rotationArray); - } - - NSArray *scaleArray = properties[@"scale"]; - if (scaleArray) { - node.scale = GLTFVectorFloat3FromArray(scaleArray); - } - - NSArray *translationArray = properties[@"translation"]; - if (translationArray) { - node.translation = GLTFVectorFloat3FromArray(translationArray); - } - - node.name = properties[@"name"]; - node.extensions = properties[@"extensions"]; - node.extras = properties[@"extras"]; - - if (_usesKHRLights) { - NSDictionary *lightProperties = node.extensions[GLTFExtensionKHRLights]; - NSNumber *lightIdentifierValue = lightProperties[@"light"]; - if (lightIdentifierValue && lightIdentifierValue.unsignedIntValue < _lights.count) { - node.light = _lights[lightIdentifierValue.integerValue]; - } - } - - [nodes addObject: node]; - } - - _nodes = [nodes copy]; - - return [self fixNodeRelationships]; -} - -- (BOOL)fixNodeRelationships { - for (GLTFNode *node in _nodes) { - NSArray *childIdentifiers = node.children; - NSMutableArray *children = [NSMutableArray arrayWithCapacity:childIdentifiers.count]; - for (NSNumber *childIndexValue in childIdentifiers) { - NSUInteger childIndex = childIndexValue.integerValue; - if (childIndex < _nodes.count) { - GLTFNode *child = _nodes[childIndex]; - child.parent = node; - [children addObject:child]; - } - } - node.children = children; - } - - for (GLTFSkin *skin in _skins) { - NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:skin.jointNodes.count]; - for (NSUInteger i = 0; i < skin.jointNodes.count; ++i) { - NSNumber *jointIndexValue = (NSNumber *)skin.jointNodes[i]; - if (jointIndexValue != nil && jointIndexValue.unsignedIntegerValue < _nodes.count) { - [nodes addObject:_nodes[jointIndexValue.intValue]]; - } - } - skin.jointNodes = [nodes copy]; - - NSNumber *skeletonIndexValue = (NSNumber *)skin.skeletonRootNode; - if (skeletonIndexValue != nil && skeletonIndexValue.unsignedIntegerValue < _nodes.count) { - skin.skeletonRootNode = _nodes[skeletonIndexValue.intValue]; - } - } - - return YES; -} - -- (BOOL)loadAnimations:(NSArray *)animationsMap { - if (animationsMap.count == 0) { - _animations = @[]; - return YES; - } - - NSArray *interpolationModes = @[ @"STEP", @"LINEAR", @"CUBICSPLINE" ]; - - NSMutableArray *animations = [NSMutableArray arrayWithCapacity:animationsMap.count]; - - for (NSDictionary *properties in animationsMap) { - GLTFAnimation *animation = [[GLTFAnimation alloc] init]; - - NSArray *samplersProperties = properties[@"samplers"]; - NSMutableArray *samplers = [NSMutableArray arrayWithCapacity:samplersProperties.count]; - [samplersProperties enumerateObjectsUsingBlock:^(NSDictionary *samplerProperties, NSUInteger index, BOOL *stop) { - GLTFAnimationSampler *sampler = [[GLTFAnimationSampler alloc] init]; - NSNumber *inputIndexValue = samplerProperties[@"input"]; - if (inputIndexValue && inputIndexValue.unsignedIntegerValue < _accessors.count) { - sampler.inputAccessor = _accessors[inputIndexValue.integerValue]; - } - NSNumber *outputIndexValue = samplerProperties[@"output"]; - if (outputIndexValue && outputIndexValue.unsignedIntegerValue < _accessors.count) { - sampler.outputAccessor = _accessors[outputIndexValue.integerValue]; - } - if (samplerProperties[@"interpolation"]) { - sampler.interpolationMode = (GLTFInterpolationMode)[interpolationModes indexOfObject:samplerProperties[@"interpolation"]]; - } - [samplers addObject:sampler]; - }]; - - animation.samplers = [samplers copy]; - - NSArray *channelsProperties = properties[@"channels"]; - NSMutableArray *channels = [NSMutableArray arrayWithCapacity:channelsProperties.count]; - [channelsProperties enumerateObjectsUsingBlock:^(NSDictionary *channelProperties, NSUInteger index, BOOL *stop) { - GLTFAnimationChannel *channel = [GLTFAnimationChannel new]; - NSNumber *samplerIndexValue = channelProperties[@"sampler"]; - if (samplerIndexValue && samplerIndexValue.unsignedIntegerValue < samplers.count) { - channel.sampler = samplers[samplerIndexValue.integerValue]; - } - NSDictionary *targetProperties = channelProperties[@"target"]; - NSNumber *targetNodeIndexValue = targetProperties[@"node"]; - if (targetNodeIndexValue && targetNodeIndexValue.unsignedIntegerValue < _nodes.count) { - channel.targetNode = _nodes[targetNodeIndexValue.integerValue]; - } - channel.targetPath = targetProperties[@"path"]; - [channels addObject:channel]; - }]; - - animation.channels = [channels copy]; - - animation.name = properties[@"name"]; - animation.extensions = properties[@"extensions"]; - animation.extras = properties[@"extras"]; - - [animations addObject: animation]; - } - - _animations = [animations copy]; - - return YES; -} - -- (BOOL)loadSkins:(NSArray *)skinsMap { - if (skinsMap.count == 0) { - _skins = @[]; - return YES; - } - - NSMutableArray *skins = [NSMutableArray arrayWithCapacity:skinsMap.count]; - for (NSDictionary *properties in skinsMap) { - GLTFSkin *skin = [[GLTFSkin alloc] init]; - - NSNumber *inverseBindMatricesAccessorIndexValue = properties[@"inverseBindMatrices"]; - if (inverseBindMatricesAccessorIndexValue != nil) { - NSUInteger inverseBindMatricesAccessorIndex = inverseBindMatricesAccessorIndexValue.unsignedIntegerValue; - if (inverseBindMatricesAccessorIndex < _accessors.count) { - skin.inverseBindMatricesAccessor = _accessors[inverseBindMatricesAccessorIndex]; - } - } - - NSArray *jointIndices = properties[@"joints"]; - if (jointIndices.count > 0) { - skin.jointNodes = [jointIndices copy]; - } - - NSNumber *skeletonIndexValue = properties[@"skeleton"]; - if (skeletonIndexValue != nil) { - skin.skeletonRootNode = (id)skeletonIndexValue; - } - - skin.name = properties[@"name"]; - skin.extensions = properties[@"extensions"]; - skin.extras = properties[@"extras"]; - - [skins addObject:skin]; - } - - _skins = [skins copy]; - - return YES; -} - -- (BOOL)loadScenes:(NSArray *)scenesMap { - if (scenesMap.count == 0) { - _scenes = @[]; - return YES; - } - - NSMutableArray *scenes = [NSMutableArray arrayWithCapacity:scenesMap.count]; - for (NSDictionary *properties in scenesMap) { - GLTFScene *scene = [[GLTFScene alloc] init]; - - NSArray *rootNodeIndices = properties[@"nodes"]; - NSMutableArray *rootNodes = [NSMutableArray arrayWithCapacity:rootNodeIndices.count]; - for (NSNumber *nodeIndexValue in rootNodeIndices) { - NSUInteger nodeIndex = nodeIndexValue.integerValue; - if (nodeIndex < _nodes.count) { - GLTFNode *node = _nodes[nodeIndex]; - [rootNodes addObject:node]; - } - } - scene.nodes = [rootNodes copy]; - - scene.name = properties[@"name"]; - scene.extensions = properties[@"extensions"]; - scene.extras = properties[@"extras"]; - - if (_usesKHRLights) { - NSDictionary *lightProperties = scene.extensions[GLTFExtensionKHRLights]; - NSNumber *lightIdentifierValue = lightProperties[@"light"]; - if (lightIdentifierValue != nil && lightIdentifierValue.unsignedIntegerValue < _lights.count) { - scene.ambientLight = _lights[lightIdentifierValue.integerValue]; - } - } - - [scenes addObject:scene]; - } - - _scenes = [scenes copy]; - - return YES; -} - -- (BOOL)loadDefaultScene:(NSNumber *)defaultSceneIndexValue -{ - if (defaultSceneIndexValue != nil) { - NSUInteger defaultSceneIndex = defaultSceneIndexValue.integerValue; - if (defaultSceneIndex < _scenes.count) { - _defaultScene = _scenes[defaultSceneIndex]; - } - } else { - _defaultScene = _scenes.firstObject; - } - - return YES; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.h b/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.h deleted file mode 100644 index cb4fd22591c4..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import - -extern const UInt32 GLTFBinaryMagic; - -typedef NS_ENUM(NSInteger, GLTFChunkType) { - GLTFChunkTypeJSON = 0x4E4F534A, - GLTFChunkTypeBinary = 0x004E4942 -}; - -typedef struct { - UInt32 magic; - UInt32 version; - UInt32 length; -} GLTFBinaryHeader; - -@interface GLTFBinaryChunk : NSObject -@property (nonatomic, assign) GLTFChunkType chunkType; -@property (nonatomic, strong) NSData *data; -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.mm b/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.mm deleted file mode 100644 index 415273fddf3c..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.mm +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFBinaryChunk.h" - -const UInt32 GLTFBinaryMagic = 0x46546C67; - -@implementation GLTFBinaryChunk -@end - diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBuffer.h b/platform/darwin/src/gltf/gltfkit/GLTFBuffer.h deleted file mode 100644 index a91cd8fda245..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFBuffer.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFObject.h" - -NS_ASSUME_NONNULL_BEGIN - -@protocol GLTFBuffer - -@property (nonatomic, readonly) NSInteger length; - -/// The actual data associated with this buffer. If uri is a data URI, this is populated when -/// loading; else it is nil -@property (nonatomic, readonly) void *contents; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBufferAllocator.h b/platform/darwin/src/gltf/gltfkit/GLTFBufferAllocator.h deleted file mode 100644 index 126168d7032b..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFBufferAllocator.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFBuffer.h" - -#import - -NS_ASSUME_NONNULL_BEGIN - -@protocol GLTFBufferAllocator -+ (uint64_t)liveAllocationSize; -- (id)newBufferWithLength:(NSInteger)length; -- (id)newBufferWithData:(NSData *)data; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBufferView.h b/platform/darwin/src/gltf/gltfkit/GLTFBufferView.h deleted file mode 100644 index 3f83f265f350..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFBufferView.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFEnums.h" -#import "GLTFObject.h" - -NS_ASSUME_NONNULL_BEGIN - -@protocol GLTFBuffer; - -@interface GLTFBufferView : GLTFObject -@property (nonatomic, weak) id buffer; -@property (nonatomic, assign) GLTFTarget target; -@property (nonatomic, assign) NSInteger length; -@property (nonatomic, assign) NSInteger offset; -@property (nonatomic, assign) NSInteger stride; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBufferView.mm b/platform/darwin/src/gltf/gltfkit/GLTFBufferView.mm deleted file mode 100644 index 3d4ba74ec15a..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFBufferView.mm +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFBufferView.h" - -@implementation GLTFBufferView - -- (NSString *)description { - return [NSString stringWithFormat:@"GLTFBufferView: length: %d, offset: %d, stride: %d, target: %d, buffer: %@", - (int)self.length, (int)self.offset, (int)self.stride, (int)self.target, self.buffer]; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFCamera.h b/platform/darwin/src/gltf/gltfkit/GLTFCamera.h deleted file mode 100644 index 67d729b85c95..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFCamera.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFEnums.h" -#import "GLTFObject.h" - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFNode; - -@interface GLTFCamera : GLTFObject -@property (nonatomic, assign) GLTFCameraType cameraType; - -@property (nonatomic, assign) float aspectRatio; // Only applicable when type is perspective -@property (nonatomic, assign) float yfov; // Only applicable when type is perspective -@property (nonatomic, assign) float xmag; // Only applicable when type is orthographic -@property (nonatomic, assign) float ymag; // Only applicable when type is orthographic -@property (nonatomic, assign) float znear; -@property (nonatomic, assign) float zfar; - -@property (nonatomic, assign) simd_float4x4 projectionMatrix; - -@property (nonatomic, copy) NSArray *referencingNodes; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFCamera.mm b/platform/darwin/src/gltf/gltfkit/GLTFCamera.mm deleted file mode 100644 index fd2d9c27a169..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFCamera.mm +++ /dev/null @@ -1,115 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFCamera.h" - -@interface GLTFCamera () -@property (nonatomic, assign, getter=projectionMatrixIsDirty) BOOL projectionMatrixDirty; -@end - -@implementation GLTFCamera - -@synthesize projectionMatrix=_projectionMatrix; - -- (instancetype)init { - if ((self = [super init])) { - _referencingNodes = @[]; - } - return self; -} - -- (void)setCameraType:(GLTFCameraType)cameraType { - _cameraType = cameraType; - _projectionMatrixDirty = YES; -} - -- (void)setAspectRatio:(float)aspectRatio { - _aspectRatio = aspectRatio; - _projectionMatrixDirty = YES; -} - -- (void)setYfov:(float)yfov { - _yfov = yfov; - _projectionMatrixDirty = YES; -} - -- (void)setXmag:(float)xmag { - _xmag = xmag; - _projectionMatrixDirty = YES; -} - -- (void)setYmag:(float)ymag { - _ymag = ymag; - _projectionMatrixDirty = YES; -} - -- (void)setZnear:(float)znear { - _znear = znear; - _projectionMatrixDirty = YES; -} - -- (void)setZfar:(float)zfar { - _zfar = zfar; - _projectionMatrixDirty = YES; -} - -- (void)setProjectionMatrix:(simd_float4x4)projectionMatrix { - _projectionMatrix = projectionMatrix; - _projectionMatrixDirty = NO; -} - -- (simd_float4x4)projectionMatrix { - if (self.projectionMatrixIsDirty) { - [self _buildProjectionMatrix]; - } - return _projectionMatrix; -} - -- (void)_buildProjectionMatrix { - switch (_cameraType) { - case GLTFCameraTypeOrthographic: { - simd_float4 X = (simd_float4){ 1 / _xmag, 0, 0, 0 }; - simd_float4 Y = (simd_float4){ 0, 1 / _ymag, 0, 0 }; - simd_float4 Z = (simd_float4){ 0, 0, 2 / (_znear - _zfar), 0 }; - simd_float4 W = (simd_float4){ 0, 0, (_zfar + _znear) / (_znear - _zfar), 1 }; - _projectionMatrix = (simd_float4x4){ { X, Y, Z, W } }; - break; - } - case GLTFCameraTypePerspective: - default: { - simd_float4 X = (simd_float4){ 1 / (_aspectRatio * tanf(0.5 * _yfov)), 0, 0, 0 }; - simd_float4 Y = (simd_float4){ 0, 1 / tanf(0.5 * _yfov), 0, 0 }; - simd_float4 Z = (simd_float4){ 0, 0, -1, -1 }; - simd_float4 W = (simd_float4){ 0, 0, -2 * _znear, 0 }; - if (_zfar != FLT_MAX) { - Z = (simd_float4){ 0, 0, (_zfar + _znear) / (_znear - _zfar), -1 }; - W = (simd_float4){ 0, 0, (2 * _zfar * _znear) / (_znear - _zfar), 0 }; - } - _projectionMatrix = (simd_float4x4){ { X, Y, Z, W } }; - break; - } - } - simd_float4x4 glToMetal = (simd_float4x4){{ - { 1, 0, 0, 0 }, - { 0, 1, 0, 0 }, - { 0, 0, 0.5, 0 }, - { 0, 0, 0.5, 1 }, - }}; - _projectionMatrix = simd_mul(glToMetal, _projectionMatrix); - _projectionMatrixDirty = NO; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.h b/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.h deleted file mode 100644 index 8382ba773a9f..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import - -#import "GLTFBufferAllocator.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface GLTFDefaultBufferAllocator : NSObject - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.mm b/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.mm deleted file mode 100644 index d27ceba2cbfb..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.mm +++ /dev/null @@ -1,93 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFDefaultBufferAllocator.h" - -static uint64_t _liveAllocationSize; - -@interface GLTFDefaultBufferAllocator () -+ (void)incrementLiveAllocationSizeByLength:(uint64_t)length; -+ (void)decrementLiveAllocationSizeByLength:(uint64_t)length; -@end - -@interface GLTFMemoryBuffer: NSObject -@property (nonatomic, assign) void *bytes; -@property (nonatomic, assign) NSInteger length; -- (instancetype)initWithLength:(NSInteger)length; -- (instancetype)initWithData:(NSData *)data; -@end - -@implementation GLTFMemoryBuffer - -@synthesize name; -@synthesize extras; -@synthesize extensions; - -- (instancetype)initWithLength:(NSInteger)length { - if ((self = [super init])) { - _bytes = malloc(length); - _length = length; - [GLTFDefaultBufferAllocator incrementLiveAllocationSizeByLength:_length]; - } - return self; -} - -- (instancetype)initWithData:(NSData *)data { - if ((self = [super init])) { - _length = data.length; - _bytes = malloc(_length); - memcpy(_bytes, data.bytes, _length); - [GLTFDefaultBufferAllocator incrementLiveAllocationSizeByLength:_length]; - } - return self; -} - -- (void)dealloc { - free(_bytes); - [GLTFDefaultBufferAllocator decrementLiveAllocationSizeByLength:_length]; -} - -- (void *)contents NS_RETURNS_INNER_POINTER { - return self.bytes; -} - -@end - -@implementation GLTFDefaultBufferAllocator - -+ (void)incrementLiveAllocationSizeByLength:(uint64_t)length { - _liveAllocationSize += length; -} - -+ (void)decrementLiveAllocationSizeByLength:(uint64_t)length { - _liveAllocationSize -= length; -} - -+ (uint64_t)liveAllocationSize { - return _liveAllocationSize; -} - -- (id)newBufferWithLength:(NSInteger)length { - GLTFMemoryBuffer *buffer = [[GLTFMemoryBuffer alloc] initWithLength:length]; - return buffer; -} - -- (id)newBufferWithData:(NSData *)data { - GLTFMemoryBuffer *buffer = [[GLTFMemoryBuffer alloc] initWithData:data]; - return buffer; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFEnums.h b/platform/darwin/src/gltf/gltfkit/GLTFEnums.h deleted file mode 100644 index 76bffbc8779a..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFEnums.h +++ /dev/null @@ -1,178 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import - -typedef NS_ENUM(NSInteger, GLTFDataType) { - GLTFBaseTypeUnknown, - GLTFDataTypeChar = 0x1400, - GLTFDataTypeUChar = 0x1401, - GLTFDataTypeShort = 0x1402, - GLTFDataTypeUShort = 0x1403, - GLTFDataTypeInt = 0x1404, - GLTFDataTypeUInt = 0x1405, - GLTFDataTypeFloat = 0x1406, - - GLTFDataTypeFloat2 = 0x8B50, - GLTFDataTypeFloat3 = 0x8B51, - GLTFDataTypeFloat4 = 0x8B52, - GLTFDataTypeInt2 = 0x8B53, - GLTFDataTypeInt3 = 0x8B54, - GLTFDataTypeInt4 = 0x8B55, - GLTFDataTypeBool = 0x8B56, - GLTFDataTypeBool2 = 0x8B57, - GLTFDataTypeBool3 = 0x8B58, - GLTFDataTypeBool4 = 0x8B59, - GLTFDataTypeFloat2x2 = 0x8B5A, - GLTFDataTypeFloat3x3 = 0x8B5B, - GLTFDataTypeFloat4x4 = 0x8B5C, - GLTFDataTypeSampler2D = 0x8B5E, -}; - -typedef NS_ENUM(NSInteger, GLTFDataDimension) { - GLTFDataDimensionUnknown, - GLTFDataDimensionScalar, - GLTFDataDimensionVector2, - GLTFDataDimensionVector3, - GLTFDataDimensionVector4, - GLTFDataDimensionMatrix2x2, - GLTFDataDimensionMatrix3x3, - GLTFDataDimensionMatrix4x4, -}; - -typedef NS_ENUM(NSInteger, GLTFTarget) { - GLTFTargetUnknown, - GLTFTargetArrayBuffer = 0x8892, - GLTFTargetElementArrayBuffer = 0x8893, -}; - -typedef NS_ENUM(NSInteger, GLTFPrimitiveType) { - GLTFPrimitiveTypePoints, - GLTFPrimitiveTypeLines, - GLTFPrimitiveTypeLineLoop, - GLTFPrimitiveTypeLineStrip, - GLTFPrimitiveTypeTriangles, - GLTFPrimitiveTypeTriangleStrip, - GLTFPrimitiveTypeTriangleFan, -}; - -typedef NS_ENUM(NSInteger, GLTFCameraType) { - GLTFCameraTypePerspective, - GLTFCameraTypeOrthographic, -}; - -typedef NS_ENUM(NSInteger, GLTFTextureTarget) { - GLTFTextureTargetTexture2D = 0x0DE1, -}; - -typedef NS_ENUM(NSInteger, GLTFTextureFormat) { - GLTFTextureFormatUnknown, - GLTFTextureFormatAlpha = 0x1906, - GLTFTextureFormatRGB = 0x1907, - GLTFTextureFormatRGBA = 0x1908, - GLTFTextureFormatLuminance = 0x1909, - GLTFTextureFormatLuminanceAlpha = 0x190A, -}; - -typedef NS_ENUM(NSInteger, GLTFTextureType) { - GLTFTextureTypeUnknown, - GLTFTextureTypeUChar = 0x1401, - GLTFTextureTypeUShort565 = 0x8363, - GLTFTextureTypeUShort4444 = 0x8033, - GLTFTextureTypeUShort5551 = 0x8034, -}; - -typedef NS_ENUM(NSInteger, GLTFShaderType) { - GLTFShaderTypeVertex = 0x8B31, - GLTFShaderTypeFragment = 0x8B30, -}; - -typedef NS_ENUM(NSInteger, GLTFSamplingFilter) { - GLTFSamplingFilterUnknown, - GLTFSamplingFilterNearest = 0x2600, - GLTFSamplingFilterLinear = 0x2601, - GLTFSamplingFilterNearestMipNearest = 0x2700, - GLTFSamplingFilterLinearMipNearest = 0x2701, - GLTFSamplingFilterNearestMipLinear = 0x2702, - GLTFSamplingLinearMipLinear = 0x2703, -}; - -typedef NS_ENUM(NSInteger, GLTFAddressMode) { - GLTFAddressModeUnknown, - GLTFAddressModeClampToEdge = 0x812F, - GLTFAddressModeMirroredRepeat = 0x8370, - GLTFAddressModeRepeat = 0x2901, -}; - -typedef NS_ENUM(NSInteger, GLTFComparisonFunc) { - GLTFComparisonFuncLess = 0x0201, - GLTFComparisonFuncEqual = 0x0202, - GLTFComparisonFuncLessEqual = 0x0203, - GLTFComparisonFuncGreater = 0x0204, - GLTFComparisonFuncNotEqual = 0x0205, - GLTFComparisonFuncGreaterEqual = 0x0206, - GLTFComparisonFuncAlways = 0x0207, -}; - -typedef NS_ENUM(NSInteger, GLTFFace) { - GLTFFaceFront = 0x0404, - GLTFFaceBack = 0x405, - GLTFFaceFrontAndBack = 0x408, -}; - -typedef NS_ENUM(NSInteger, GLTFWinding) { - GLTFWindingClockwise = 0x900, - GLTFWindingCounterclockwise = 0x0901, -}; - -typedef NS_ENUM(NSInteger, GLTFState) { - GLTFStateBlendingEnabled = 0x0BE2, - GLTFStateCullFaceEnabled = 0x0B44, - GLTFStateDepthTestEnabled = 0x0B71, - GLTFStatePolygonOffsetFillEnabled = 0x8037, - GLTFStateAlphaToCoverageEnabled = 0x809E, - GLTFStateScissorTestEnabled = 0x0C11, -}; - -typedef NS_ENUM(NSInteger, GLTFBlendFunction) { - GLTFBlendFunctionAdd = 0x8006, - GLTFBlendFunctionSubtract = 0x800A, - GLTFBlendFunctionReverseSubtract = 0x800B, -}; - -typedef NS_ENUM(NSInteger, GLTFBlendEquation) { - GLTFBlendEquationZero = 0x0000, - GLTFBlendEquationOne = 0x0001, - GLTFBlendEquationSrcColor = 0x0300, - GLTFBlendEquationOneMinusSrcColor = 0x0301, - GLTFBlendEquationSrcAlpha = 0x0302, - GLTFBlendEquationOneMinusSrcAlpha = 0x0303, - GLTFBlendEquationDestAlpha = 0x0304, - GLTFBlendEquationOneMinusDestAlpha = 0x0305, - GLTFBlendEquationDestColor = 0x0306, - GLTFBlendEquationOneMinusDestColor = 0x0307, - GLTFBlendEquationSrcAlphaSaturate = 0x0308, - GLTFBlendEquationConstantColor = 0x8001, - GLTFBlendEquationOneMinusConstColor = 0x8002, - GLTFBlendEquationConstantAlpha = 0x8003, - GLTFBlendEquationOneMinusConstAlpha = 0x8004, -}; - -typedef NS_ENUM(NSInteger, GLTFInterpolationMode) { - GLTFInterpolationModeStep, - GLTFInterpolationModeLinear, - GLTFInterpolationModeCubic, -}; diff --git a/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.h b/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.h deleted file mode 100644 index b219b6c004dd..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import - -extern NSString *const GLTFExtensionKHRMaterialsPBRSpecularGlossiness; -extern NSString *const GLTFExtensionKHRLights; -extern NSString *const GLTFExtensionKHRMaterialsUnlit; -extern NSString *const GLTFExtensionKHRTextureTransform; -extern NSString *const GLTFExtensionEXTPBRAttributes; diff --git a/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.mm b/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.mm deleted file mode 100644 index a531b33a8987..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.mm +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFExtensionNames.h" - -NSString *const GLTFExtensionKHRMaterialsPBRSpecularGlossiness = @"KHR_materials_pbrSpecularGlossiness"; -NSString *const GLTFExtensionKHRLights = @"KHR_lights"; -NSString *const GLTFExtensionKHRMaterialsUnlit = @"KHR_materials_unlit"; -NSString *const GLTFExtensionKHRTextureTransform = @"KHR_texture_transform"; -NSString *const GLTFExtensionEXTPBRAttributes = @"EXT_pbr_attributes"; diff --git a/platform/darwin/src/gltf/gltfkit/GLTFImage.h b/platform/darwin/src/gltf/gltfkit/GLTFImage.h deleted file mode 100644 index fe621ff196b6..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFImage.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFBufferView.h" -#import "GLTFObject.h" - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface GLTFImage : GLTFObject - -/// A reference to a buffer view containing image data, if url is nil -@property (nonatomic, strong) GLTFBufferView *_Nullable bufferView; - -/// The MIME type of the data contained in this image's buffer view -@property (nonatomic, copy) NSString *_Nullable mimeType; - -/// A file URL, if the URI was not a decodable data-uri; otherwise nil -@property (nonatomic, copy) NSURL *_Nullable url; - -/// A data object containing the data encoded in the image's data-uri, if present; otherwise nil -@property (nonatomic, strong) NSData *imageData; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFImage.mm b/platform/darwin/src/gltf/gltfkit/GLTFImage.mm deleted file mode 100644 index b45f287d95e1..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFImage.mm +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFImage.h" - -#import - -@implementation GLTFImage - -+ (CGImageRef)newImageForData:(NSData *)data mimeType:(NSString *)mimeType { - CGImageRef image = NULL; - CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data); - if ([mimeType isEqualToString:@"image/jpeg"]) { - image = CGImageCreateWithJPEGDataProvider(provider, NULL, false, kCGRenderingIntentDefault); - } else if ([mimeType isEqualToString:@"image/png"]) { - image = CGImageCreateWithPNGDataProvider(provider, NULL, false, kCGRenderingIntentDefault); - } else { - NSLog(@"Unknown MIME type encountered when decoding image: %@", mimeType); - } - CGDataProviderRelease(provider); - return image; -} - -+ (CGImageRef)newImageForDataURI:(NSString *)uriData { - NSString *prefix = @"data:"; - if ([uriData hasPrefix:prefix]) { - NSInteger prefixEnd = prefix.length; - NSInteger firstComma = [uriData rangeOfString:@","].location; - if (firstComma != NSNotFound) { - NSString *mediaTypeAndTokenString = [uriData substringWithRange:NSMakeRange(prefixEnd, firstComma - prefixEnd)]; - NSArray *mediaTypeAndToken = [mediaTypeAndTokenString componentsSeparatedByString:@";"]; - if (mediaTypeAndToken.count > 0) { - NSString *mediaType = mediaTypeAndToken.firstObject; - NSString *encodedImageData = [uriData substringFromIndex:firstComma + 1]; - NSData *imageData = [[NSData alloc] initWithBase64EncodedString:encodedImageData - options:NSDataBase64DecodingIgnoreUnknownCharacters]; - return [self newImageForData:imageData mimeType:mediaType]; - } - } - } - return NULL; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.h b/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.h deleted file mode 100644 index 9139bacf582d..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.h +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFObject.h" - -#import - -typedef NS_ENUM(NSInteger, GLTFKHRLightType) { - GLTFKHRLightTypeAmbient, - GLTFKHRLightTypeDirectional, - GLTFKHRLightTypePoint, - GLTFKHRLightTypeSpot, -}; - -@interface GLTFKHRLight : GLTFObject - -@property (nonatomic, assign) GLTFKHRLightType type; - -/// Color of light in a linear RGB color space -@property (nonatomic, assign) simd_float4 color; - -/// Brightness of light. Point and spot lights use luminous intensity in candela (lm/sr), -/// while directional lights use illuminance in lux (lm/m^2). -@property (nonatomic, assign) float intensity; - -/// Distance threshold at which the light's intensity may be considered to have reached zero, -/// expressed in meters. Default is 0, signifying effectively infinite range. -@property (nonatomic, assign) float range; - -/// Angle, in radians, from the center of a spotlight to where falloff begins. -/// Must be greater than or equal to 0, less than or equal to `outerConeAngle`, -/// and less than pi / 2. Default value is 0. -@property (nonatomic, assign) float innerConeAngle; - -/// Angle, in radians, from the center of a spotlight to where falloff ends. -/// Must be greater than or equal to 0, greater than or equal to `innerConeAngle`, -/// and less than pi / 2. Default value is pi / 4. -@property (nonatomic, assign) float outerConeAngle; - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.mm b/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.mm deleted file mode 100644 index eff3be6aeff2..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.mm +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFKHRLight.h" - -@implementation GLTFKHRLight - -- (instancetype)init { - if ((self = [super init])) { - _type = GLTFKHRLightTypeDirectional; - _color = (simd_float4){ 1, 1, 1, 1 }; - _intensity = 1; - _range = 0; - _innerConeAngle = 0; - _outerConeAngle = M_PI_4; - } - return self; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.h b/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.h deleted file mode 100644 index 07abe678380d..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import -#import -#import "GLTFBuffer.h" -#import "GLTFBufferAllocator.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface GLTFMTLBuffer : NSObject - -@property (nonatomic, readonly) id buffer; - -@end - -@interface GLTFMTLBufferAllocator : NSObject - -- (instancetype)initWithDevice:(id)device; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.mm b/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.mm deleted file mode 100644 index c1bf44f1387d..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.mm +++ /dev/null @@ -1,101 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFMTLBufferAllocator.h" - -#import - -static uint64_t _liveAllocationSize; - -@interface GLTFMTLBufferAllocator () -+ (void)incrementLiveAllocationSizeByLength:(uint64_t)length; -+ (void)decrementLiveAllocationSizeByLength:(uint64_t)length; -@end - -@interface GLTFMTLBuffer () -@property (nonatomic, strong) id buffer; - -- (instancetype)initWithBuffer:(id)buffer; - -@end - -@implementation GLTFMTLBuffer - -@synthesize name; -@synthesize extras; -@synthesize extensions; - -- (instancetype)initWithBuffer:(id)buffer { - if ((self = [super init])) { - _buffer = buffer; - [GLTFMTLBufferAllocator incrementLiveAllocationSizeByLength:_buffer.length]; - } - return self; -} - -- (void)dealloc { - [GLTFMTLBufferAllocator decrementLiveAllocationSizeByLength:_buffer.length]; -} - -- (NSInteger)length { - return [self.buffer length]; -} - -- (void *)contents { - return [self.buffer contents]; -} - -@end - -@interface GLTFMTLBufferAllocator () -@property (nonatomic, strong) id device; -@end - -@implementation GLTFMTLBufferAllocator - -+ (void)incrementLiveAllocationSizeByLength:(uint64_t)length { - _liveAllocationSize += length; -} - -+ (void)decrementLiveAllocationSizeByLength:(uint64_t)length { - _liveAllocationSize -= length; -} - -+ (uint64_t)liveAllocationSize { - return _liveAllocationSize; -} - -- (instancetype)initWithDevice:(id)device { - if ((self = [super init])) { - _device = device; - } - return self; -} - -- (id)newBufferWithLength:(NSInteger)length { - MTLResourceOptions options = MTLResourceCPUCacheModeDefaultCache | MTLResourceStorageModeShared; - id underlying = [self.device newBufferWithLength:length options:options]; - return [[GLTFMTLBuffer alloc] initWithBuffer:underlying]; -} - - -- (id)newBufferWithData:(NSData *)data { - MTLResourceOptions options = MTLResourceCPUCacheModeDefaultCache | MTLResourceStorageModeShared; - id underlying = [self.device newBufferWithBytes:data.bytes length:data.length options:options]; - return [[GLTFMTLBuffer alloc] initWithBuffer:underlying]; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.h b/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.h deleted file mode 100644 index 4c664894ad71..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFMTLUtilities.h" -#import "GLTFMesh.h" - -#import - -// Maximum number of textures supplied by a material; excludes IBL textures, etc. - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFMTLLightingEnvironment; - -@interface GLTFMTLShaderBuilder : NSObject - -- (id) - renderPipelineStateForSubmesh:(GLTFSubmesh *)submesh - // lightingEnvironment:(GLTFMTLLightingEnvironment * _Nullable)lightingEnvironment - colorPixelFormat:(MTLPixelFormat)colorPixelFormat - depthStencilPixelFormat:(MTLPixelFormat)depthStencilPixelFormat - sampleCount:(int)sampleCount - device:(id)device; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.mm b/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.mm deleted file mode 100644 index 8045d13e9f1c..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.mm +++ /dev/null @@ -1,246 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - - -#import "GLTFMTLShaderBuilder.h" -#import "GLTFMesh.h" -#import "GLTFMaterial.h" -#import "GLTFVertexDescriptor.h" -#import "GLTFAccessor.h" -#import "../GLTFMath.hpp" - -@implementation GLTFMTLShaderBuilder - -- (id)renderPipelineStateForSubmesh:(GLTFSubmesh *)submesh - // lightingEnvironment:(GLTFMTLLightingEnvironment *)lightingEnvironment - colorPixelFormat:(MTLPixelFormat)colorPixelFormat - depthStencilPixelFormat:(MTLPixelFormat)depthStencilPixelFormat - sampleCount:(int)sampleCount - device:(id)device -{ - NSParameterAssert(submesh); - NSParameterAssert(submesh.material); - NSParameterAssert(submesh.vertexDescriptor); - - NSError *error = nil; - NSString *shaderSource = [self shaderSource]; - - shaderSource = [self rewriteSource:shaderSource forSubmesh:submesh]; - - id library = [device newLibraryWithSource:shaderSource options:nil error:&error]; - if (!library) { - NSLog(@"Error occurred while creating library for material : %@", error); - return nil; - } - - id vertexFunction = nil; - id fragmentFunction = nil; - - for (NSString *functionName in [library functionNames]) { - id function = [library newFunctionWithName:functionName]; - if ([function functionType] == MTLFunctionTypeVertex) { - vertexFunction = function; - } else if ([function functionType] == MTLFunctionTypeFragment) { - fragmentFunction = function; - } - } - - if (!vertexFunction || !fragmentFunction) { - NSLog(@"Failed to find a vertex and fragment function in library source"); - return nil; - } - - MTLVertexDescriptor *vertexDescriptor = [self vertexDescriptorForSubmesh: submesh]; - - MTLRenderPipelineDescriptor *pipelineDescriptor = [MTLRenderPipelineDescriptor new]; - pipelineDescriptor.vertexFunction = vertexFunction; - pipelineDescriptor.fragmentFunction = fragmentFunction; - pipelineDescriptor.vertexDescriptor = vertexDescriptor; - - pipelineDescriptor.colorAttachments[0].pixelFormat = colorPixelFormat; - pipelineDescriptor.sampleCount = sampleCount; - - if (submesh.material.alphaMode == GLTFAlphaModeBlend) { - pipelineDescriptor.colorAttachments[0].blendingEnabled = YES; - pipelineDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; - pipelineDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd; - pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne; - pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne; - pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha; - pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha; - } - - pipelineDescriptor.depthAttachmentPixelFormat = depthStencilPixelFormat; - pipelineDescriptor.stencilAttachmentPixelFormat = depthStencilPixelFormat; - - id pipeline = [device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:&error]; - if (!pipeline) { - NSLog(@"Error occurred when creating render pipeline state: %@", error); - } - - return pipeline; -} - -- (NSString *)shaderSource { - NSError *error = nil; - // TODO: Figure out why Bazel won't embed the .metal files - NSURL *shaderURL = [[NSBundle mainBundle] URLForResource:@"pbr" withExtension:@"txt"]; - if (shaderURL == nil) { - NSLog(@"ERROR: Shader source not found in main bundle; pipeline states cannot be generated"); - } - return [NSString stringWithContentsOfURL:shaderURL encoding:NSUTF8StringEncoding error:&error]; -} - -- (NSString *)rewriteSource:(NSString *)source - forSubmesh:(GLTFSubmesh *)submesh -{ - GLTFMaterial *material = submesh.material; - - BOOL usePBR = YES; - BOOL useIBL = NO; // lightingEnvironment != nil; - BOOL useDoubleSided = material.isDoubleSided; - BOOL hasTexCoord0 = submesh.accessorsForAttributes[GLTFAttributeSemanticTexCoord0] != nil; - BOOL hasTexCoord1 = submesh.accessorsForAttributes[GLTFAttributeSemanticTexCoord1] != nil; - BOOL hasNormals = submesh.accessorsForAttributes[GLTFAttributeSemanticNormal] != nil; - BOOL hasTangents = submesh.accessorsForAttributes[GLTFAttributeSemanticTangent] != nil; - BOOL hasBaseColorMap = material.baseColorTexture != nil; - BOOL hasOcclusionMap = material.occlusionTexture != nil; - BOOL hasEmissiveMap = material.emissiveTexture != nil; - BOOL hasNormalMap = material.normalTexture != nil; - BOOL hasMetallicRoughnessMap = material.metallicRoughnessTexture != nil; - BOOL hasTextureTransforms = material.hasTextureTransforms; - BOOL hasSkinningData = submesh.accessorsForAttributes[GLTFAttributeSemanticJoints0] != nil && - submesh.accessorsForAttributes[GLTFAttributeSemanticWeights0] != nil; - BOOL hasExtendedSkinning = submesh.accessorsForAttributes[GLTFAttributeSemanticJoints1] != nil && - submesh.accessorsForAttributes[GLTFAttributeSemanticWeights1] != nil; - BOOL hasVertexColor = submesh.accessorsForAttributes[GLTFAttributeSemanticColor0] != nil; - BOOL vertexColorIsRGB = submesh.accessorsForAttributes[GLTFAttributeSemanticColor0].dimension == GLTFDataDimensionVector3; - BOOL hasVertexRoughness = submesh.accessorsForAttributes[GLTFAttributeSemanticRoughness] != nil; - BOOL hasVertexMetallic = submesh.accessorsForAttributes[GLTFAttributeSemanticMetallic] != nil; - BOOL premultiplyBaseColor = material.alphaMode == GLTFAlphaModeBlend; - BOOL materialIsUnlit = material.isUnlit; - BOOL useAlphaTest = material.alphaMode == GLTFAlphaModeMask; - - NSMutableString *shaderFeatures = [NSMutableString string]; - [shaderFeatures appendFormat:@"#define USE_PBR %d\n", usePBR]; - [shaderFeatures appendFormat:@"#define USE_IBL %d\n", useIBL]; - [shaderFeatures appendFormat:@"#define USE_ALPHA_TEST %d\n", useAlphaTest]; - [shaderFeatures appendFormat:@"#define USE_VERTEX_SKINNING %d\n", hasSkinningData]; - [shaderFeatures appendFormat:@"#define USE_EXTENDED_VERTEX_SKINNING %d\n", hasExtendedSkinning]; - [shaderFeatures appendFormat:@"#define USE_DOUBLE_SIDED_MATERIAL %d\n", useDoubleSided]; - [shaderFeatures appendFormat:@"#define HAS_TEXCOORD_0 %d\n", hasTexCoord0]; - [shaderFeatures appendFormat:@"#define HAS_TEXCOORD_1 %d\n", hasTexCoord1]; - [shaderFeatures appendFormat:@"#define HAS_NORMALS %d\n", hasNormals]; - [shaderFeatures appendFormat:@"#define HAS_TANGENTS %d\n", hasTangents]; - [shaderFeatures appendFormat:@"#define HAS_VERTEX_COLOR %d\n", hasVertexColor]; - [shaderFeatures appendFormat:@"#define VERTEX_COLOR_IS_RGB %d\n", vertexColorIsRGB]; - [shaderFeatures appendFormat:@"#define HAS_BASE_COLOR_MAP %d\n", hasBaseColorMap]; - [shaderFeatures appendFormat:@"#define HAS_NORMAL_MAP %d\n", hasNormalMap]; - [shaderFeatures appendFormat:@"#define HAS_METALLIC_ROUGHNESS_MAP %d\n", hasMetallicRoughnessMap]; - [shaderFeatures appendFormat:@"#define HAS_OCCLUSION_MAP %d\n", hasOcclusionMap]; - [shaderFeatures appendFormat:@"#define HAS_EMISSIVE_MAP %d\n", hasEmissiveMap]; - [shaderFeatures appendFormat:@"#define HAS_VERTEX_ROUGHNESS %d\n", hasVertexRoughness]; - [shaderFeatures appendFormat:@"#define HAS_VERTEX_METALLIC %d\n", hasVertexMetallic]; - [shaderFeatures appendFormat:@"#define HAS_TEXTURE_TRANSFORM %d\n", hasTextureTransforms]; - [shaderFeatures appendFormat:@"#define PREMULTIPLY_BASE_COLOR %d\n", premultiplyBaseColor]; - [shaderFeatures appendFormat:@"#define MATERIAL_IS_UNLIT %d\n", materialIsUnlit]; - [shaderFeatures appendFormat:@"#define SPECULAR_ENV_MIP_LEVELS %d\n", 0]; // lightingEnvironment.specularMipLevelCount]; - [shaderFeatures appendFormat:@"#define MAX_LIGHTS %d\n", (int)GLTFMTLMaximumLightCount]; - [shaderFeatures appendFormat:@"#define MAX_MATERIAL_TEXTURES %d\n\n", (int)GLTFMTLMaximumTextureCount]; - - [shaderFeatures appendFormat:@"#define BaseColorTexCoord texCoord%d\n", (int)material.baseColorTexture.texCoord]; - [shaderFeatures appendFormat:@"#define NormalTexCoord texCoord%d\n", (int)material.normalTexture.texCoord]; - [shaderFeatures appendFormat:@"#define MetallicRoughnessTexCoord texCoord%d\n", (int)material.metallicRoughnessTexture.texCoord]; - [shaderFeatures appendFormat:@"#define EmissiveTexCoord texCoord%d\n", (int)material.emissiveTexture.texCoord]; - [shaderFeatures appendFormat:@"#define OcclusionTexCoord texCoord%d\n\n", (int)material.occlusionTexture.texCoord]; - - NSString *preamble = @"struct VertexIn {\n"; - NSString *epilogue = @"\n};"; - - NSMutableArray *attribs = [NSMutableArray array]; - int i = 0; - for (GLTFVertexAttribute *attribute in submesh.vertexDescriptor.attributes) { - if (attribute.componentType == GLTFBaseTypeUnknown) { continue; } - if ([attribute.semantic isEqualToString:GLTFAttributeSemanticPosition]) { - [attribs addObject:[NSString stringWithFormat:@" %@ position [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticNormal]) { - [attribs addObject:[NSString stringWithFormat:@" %@ normal [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticTangent]) { - [attribs addObject:[NSString stringWithFormat:@" %@ tangent [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticTexCoord0]) { - [attribs addObject:[NSString stringWithFormat:@" %@ texCoord0 [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticTexCoord1]) { - [attribs addObject:[NSString stringWithFormat:@" %@ texCoord1 [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticColor0]) { - [attribs addObject:[NSString stringWithFormat:@" %@ color [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticJoints0]) { - [attribs addObject:[NSString stringWithFormat:@" %@ joints0 [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticJoints1]) { - [attribs addObject:[NSString stringWithFormat:@" %@ joints1 [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticWeights0]) { - [attribs addObject:[NSString stringWithFormat:@" %@ weights0 [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticWeights1]) { - [attribs addObject:[NSString stringWithFormat:@" %@ weights1 [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticRoughness]) { - [attribs addObject:[NSString stringWithFormat:@" %@ roughness [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticMetallic]) { - [attribs addObject:[NSString stringWithFormat:@" %@ metalness [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } - - ++i; - } - - NSString *decls = [NSString stringWithFormat:@"%@%@%@%@", - shaderFeatures, preamble, [attribs componentsJoinedByString:@"\n"], epilogue]; - - NSRange startSigilRange = [source rangeOfString:@"/*%begin_replace_decls%*/"]; - NSRange endSigilRange = [source rangeOfString:@"/*%end_replace_decls%*/"]; - - NSRange declRange = NSUnionRange(startSigilRange, endSigilRange); - - source = [source stringByReplacingCharactersInRange:declRange withString:decls]; - - return source; -} - -- (MTLVertexDescriptor *)vertexDescriptorForSubmesh:(GLTFSubmesh *)submesh { - MTLVertexDescriptor *vertexDescriptor = [MTLVertexDescriptor new]; - - GLTFVertexDescriptor *descriptor = submesh.vertexDescriptor; - - for (NSInteger attributeIndex = 0; attributeIndex < GLTFVertexDescriptorMaxAttributeCount; ++attributeIndex) { - GLTFVertexAttribute *attribute = descriptor.attributes[attributeIndex]; - GLTFBufferLayout *layout = descriptor.bufferLayouts[attributeIndex]; - - if (attribute.componentType == 0) { - continue; - } - - MTLVertexFormat vertexFormat = GLTFMTLVertexFormatForComponentTypeAndDimension(attribute.componentType, attribute.dimension); - - vertexDescriptor.attributes[attributeIndex].offset = 0; - vertexDescriptor.attributes[attributeIndex].format = vertexFormat; - vertexDescriptor.attributes[attributeIndex].bufferIndex = attributeIndex; - - vertexDescriptor.layouts[attributeIndex].stride = layout.stride; - vertexDescriptor.layouts[attributeIndex].stepRate = 1; - vertexDescriptor.layouts[attributeIndex].stepFunction = MTLVertexStepFunctionPerVertex; // MTLStepFunctionPerVertex; - } - - return vertexDescriptor; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.h b/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.h deleted file mode 100644 index 286838dda5fa..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -extern NSString *const GLTFMTLTextureLoaderOptionGenerateMipmaps; -extern NSString *const GLTFMTLTextureLoaderOptionUsageFlags; -extern NSString *const GLTFMTLTextureLoaderOptionSRGB; - -@interface GLTFMTLTextureLoader : NSObject -- (instancetype)initWithDevice:(id)device; -- (id _Nullable)newTextureWithContentsOfURL:(NSURL *)url - options:(NSDictionary *_Nullable)options - error:(NSError **)error; -- (id _Nullable)newTextureWithData:(NSData *)data - options:(NSDictionary *_Nullable)options - error:(NSError **)error; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.mm b/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.mm deleted file mode 100644 index 95c113d17c1e..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.mm +++ /dev/null @@ -1,244 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFMTLTextureLoader.h" -#import -#import -#import - -NSString *const GLTFMTLTextureLoaderOptionGenerateMipmaps = @"GLTFMTLTextureLoaderOptionGenerateMipmaps"; -NSString *const GLTFMTLTextureLoaderOptionUsageFlags = @"GLTFMTLTextureLoaderOptionUsageFlags"; -NSString *const GLTFMTLTextureLoaderOptionSRGB = @"GLTFMTLTextureLoaderOptionSRGB"; - -__fp16 *GLTFMTLConvertImageToRGBA16F(CGImageRef image) -{ - size_t width = CGImageGetWidth(image); - size_t height = CGImageGetHeight(image); - - void *dstPixels = malloc(sizeof(__fp16) * 4 * width * height); - size_t dstBytesPerRow = sizeof(__fp16) * 4 * width; - vImage_Buffer dstBuffer = { - .data = dstPixels, - .height = height, - .width = width, - .rowBytes = dstBytesPerRow - }; - - vImage_CGImageFormat srcFormat = { - .bitsPerComponent = (uint32_t)CGImageGetBitsPerComponent(image), - .bitsPerPixel = (uint32_t)CGImageGetBitsPerPixel(image), - .colorSpace = CGImageGetColorSpace(image), - .bitmapInfo = CGImageGetBitmapInfo(image) - }; - - vImage_CGImageFormat dstFormat = { - .bitsPerComponent = sizeof(__fp16) * 8, - .bitsPerPixel = sizeof(__fp16) * 8 * 4, - .colorSpace = CGImageGetColorSpace(image), - .bitmapInfo = kCGBitmapByteOrder16Little | kCGBitmapFloatComponents | kCGImageAlphaLast - }; - - vImage_Error error = kvImageNoError; - CGFloat background[] = { 0, 0, 0, 1 }; - vImageConverterRef converter = vImageConverter_CreateWithCGImageFormat(&srcFormat, - &dstFormat, - background, - kvImageNoFlags, - &error); - - CGDataProviderRef dataProvider = CGImageGetDataProvider(image); - CFDataRef srcData = CGDataProviderCopyData(dataProvider); - - const void *srcPixels = CFDataGetBytePtr(srcData); - size_t srcBytesPerRow = CGImageGetBytesPerRow(image); - - vImage_Buffer srcBuffer = { - .data = (void *)srcPixels, - .height = height, - .width = width, - .rowBytes = srcBytesPerRow - }; - - error = vImageConvert_AnyToAny(converter, &srcBuffer, &dstBuffer, NULL, kvImageNoFlags); - - vImageConverter_Release(converter); - CFRelease(srcData); - - return (__fp16*)dstPixels; -} - -unsigned char *GLTFMTLConvertImageToRGBA8U(CGImageRef image) -{ - size_t width = CGImageGetWidth(image); - size_t height = CGImageGetHeight(image); - - CGColorSpaceRef srcColorSpace = CGImageGetColorSpace(image); - - vImage_CGImageFormat srcFormat = { - .bitsPerComponent = (uint32_t)CGImageGetBitsPerComponent(image), - .bitsPerPixel = (uint32_t)CGImageGetBitsPerPixel(image), - .colorSpace = srcColorSpace, - .bitmapInfo = CGImageGetBitmapInfo(image) - }; - - void *dstPixels = malloc(sizeof(unsigned char) * 4 * width * height); - vImage_Buffer dstBuffer = { - .data = dstPixels, - .height = height, - .width = width, - .rowBytes = sizeof(unsigned char) * 4 * width - }; - - CGColorSpaceRef dstColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); - - vImage_CGImageFormat dstFormat = { - .bitsPerComponent = sizeof(unsigned char) * 8, - .bitsPerPixel = sizeof(unsigned char) * 8 * 4, - .colorSpace = dstColorSpace, - .bitmapInfo = (CGBitmapInfo)kCGBitmapByteOrder32Big | (CGBitmapInfo)kCGImageAlphaLast - }; - - vImage_Error error = kvImageNoError; - CGFloat background[] = { 0, 0, 0, 1 }; - vImageConverterRef converter = vImageConverter_CreateWithCGImageFormat(&srcFormat, - &dstFormat, - background, - kvImageNoFlags, - &error); - - CGDataProviderRef dataProvider = CGImageGetDataProvider(image); - CFDataRef srcData = CGDataProviderCopyData(dataProvider); - - const void *srcPixels = CFDataGetBytePtr(srcData); - - size_t srcBytesPerPixel = CGImageGetBitsPerPixel(image) / 8; - - vImage_Buffer srcBuffer = { - .data = (void *)srcPixels, - .height = height, - .width = width, - .rowBytes = srcBytesPerPixel * width - }; - - vImageConvert_AnyToAny(converter, &srcBuffer, &dstBuffer, NULL, kvImageNoFlags); - - vImageConverter_Release(converter); - CFRelease(srcData); - - return (unsigned char*)dstPixels; -} - -@interface GLTFMTLTextureLoader () -@property (nonatomic, strong) id device; -@property (nonatomic, strong) id commandQueue; -@end - -@implementation GLTFMTLTextureLoader - -- (instancetype)initWithDevice:(id)device { - if ((self = [super init])) { - _device = device; - _commandQueue = [device newCommandQueue]; - } - return self; -} - -- (id)newTextureWithContentsOfURL:(NSURL *)url options:(NSDictionary *)options error:(NSError **)error { - if (url == nil) { - return nil; - } - - NSData *data = [NSData dataWithContentsOfURL:url]; - - return [self newTextureWithData:data options:options error:error]; -} - -- (id)newTextureWithData:(NSData *)data options:(NSDictionary *)options error:(NSError **)error { - if (data == nil) { - return nil; - } - - NSNumber *sRGBOption = options[GLTFMTLTextureLoaderOptionSRGB]; - BOOL sRGB = (sRGBOption != nil) ? sRGBOption.boolValue : NO; - - CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, nil); - CGImageRef image = CGImageSourceCreateImageAtIndex(imageSource, 0, nil); - size_t width = CGImageGetWidth(image); - size_t height = CGImageGetHeight(image); - size_t bitsPerComponent = CGImageGetBitsPerComponent(image); - - void *dstBytes = NULL; - MTLPixelFormat pixelFormat = MTLPixelFormatInvalid; - if (bitsPerComponent == 8) { - pixelFormat = sRGB ? MTLPixelFormatRGBA8Unorm_sRGB : MTLPixelFormatRGBA8Unorm; - dstBytes = GLTFMTLConvertImageToRGBA8U(image); - bitsPerComponent = 8; - } else if (bitsPerComponent == 16 || bitsPerComponent == 32) { - pixelFormat = MTLPixelFormatRGBA16Float; - dstBytes = GLTFMTLConvertImageToRGBA16F(image); - bitsPerComponent = 16; - } - - size_t bytesPerRow = (bitsPerComponent / 8) * 4 * width; - NSNumber *mipmapOption = options[GLTFMTLTextureLoaderOptionGenerateMipmaps]; - BOOL mipmapped = (mipmapOption != nil) ? mipmapOption.boolValue : NO; - - MTLTextureDescriptor *descriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pixelFormat - width:width - height:height - mipmapped:mipmapped]; - - id texture = [self newTextureWithBytes:(const unsigned char*)dstBytes - bytesPerRow:bytesPerRow - descriptor:descriptor - options:options - error:error]; - - free(dstBytes); - CGImageRelease(image); - CFRelease(imageSource); - - return texture; -} - -- (id _Nullable)newTextureWithBytes:(const unsigned char *)bytes - bytesPerRow:(size_t)bytesPerRow - descriptor:(MTLTextureDescriptor *)descriptor - options:(NSDictionary * _Nullable)options - error:(NSError **)error -{ - NSNumber *usageOption = options[GLTFMTLTextureLoaderOptionUsageFlags]; - descriptor.usage = (usageOption != nil) ? usageOption.integerValue : MTLTextureUsageShaderRead; - - id texture = [self.device newTextureWithDescriptor:descriptor]; - - [texture replaceRegion:MTLRegionMake2D(0, 0, texture.width, texture.height) - mipmapLevel:0 - withBytes:bytes - bytesPerRow:bytesPerRow]; - - if (texture != nil && (texture.mipmapLevelCount > 1)) { - id commandBuffer = [self.commandQueue commandBuffer]; - id commandEncoder = [commandBuffer blitCommandEncoder]; - [commandEncoder generateMipmapsForTexture:texture]; - [commandEncoder endEncoding]; - [commandBuffer commit]; - } - - return texture; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.h b/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.h deleted file mode 100644 index 774e113d4c51..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.h +++ /dev/null @@ -1,56 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFEnums.h" - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -#ifdef __cplusplus -extern "C" { -#endif - -extern MTLPrimitiveType GLTFMTLPrimitiveTypeForPrimitiveType(GLTFPrimitiveType gltfType); - -extern MTLBlendOperation GLTFMTLBlendOperationForBlendFunction(GLTFBlendFunction f); - -extern MTLBlendFactor GLTFBlendFactorForBlendEquation(GLTFBlendEquation e); - -extern MTLCompareFunction GLTFMTLCompareFunctionForComparisonFunc(GLTFComparisonFunc f); - -extern MTLWinding GLTFMTLWindingForWinding(GLTFWinding w); - -extern MTLCullMode GLTFMTLCullModeForCullFace(GLTFFace face); - -extern MTLSamplerMinMagFilter GLTFMTLSamplerMinMagFilterForSamplingFilter(GLTFSamplingFilter mode); - -extern MTLSamplerMipFilter GLTFMTLSamplerMipFilterForSamplingFilter(GLTFSamplingFilter mode); - -extern MTLSamplerAddressMode GLTFMTLSamplerAddressModeForSamplerAddressMode(GLTFAddressMode mode); - -extern NSString *GLTFMTLTypeNameForType(GLTFDataType baseType, GLTFDataDimension dimension, - BOOL packedIfPossible); - -extern MTLVertexFormat GLTFMTLVertexFormatForComponentTypeAndDimension(GLTFDataType baseType, - GLTFDataDimension dimension); - -#ifdef __cplusplus -} -#endif - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.mm b/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.mm deleted file mode 100644 index 1dc446902fb5..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.mm +++ /dev/null @@ -1,291 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFMTLUtilities.h" - -MTLPrimitiveType GLTFMTLPrimitiveTypeForPrimitiveType(GLTFPrimitiveType gltfType) { - switch (gltfType) { - case GLTFPrimitiveTypePoints: - return MTLPrimitiveTypePoint; - case GLTFPrimitiveTypeLines: - return MTLPrimitiveTypeLine; - case GLTFPrimitiveTypeLineStrip: - return MTLPrimitiveTypeLineStrip; - case GLTFPrimitiveTypeTriangles: - return MTLPrimitiveTypeTriangle; - case GLTFPrimitiveTypeTriangleStrip: - return MTLPrimitiveTypeTriangleStrip; - - // Not supported; need to duplicate first element and restitch into tri strip, respectively - case GLTFPrimitiveTypeLineLoop: - case GLTFPrimitiveTypeTriangleFan: - default: - NSLog(@"Unsupported primitive type function %d", (int)gltfType); - return MTLPrimitiveTypePoint; - } -} - -MTLBlendOperation GLTFMTLBlendOperationForBlendFunction(GLTFBlendFunction f) { - switch (f) { - case GLTFBlendFunctionAdd: - return MTLBlendOperationAdd; - case GLTFBlendFunctionSubtract: - return MTLBlendOperationSubtract; - case GLTFBlendFunctionReverseSubtract: - return MTLBlendOperationReverseSubtract; - } -} - -MTLBlendFactor GLTFBlendFactorForBlendEquation(GLTFBlendEquation e) { - switch (e) { - case GLTFBlendEquationOne: - return MTLBlendFactorOne; - case GLTFBlendEquationZero: - return MTLBlendFactorZero; - case GLTFBlendEquationSrcAlpha: - return MTLBlendFactorSourceAlpha; - case GLTFBlendEquationSrcColor: - return MTLBlendFactorSourceColor; - case GLTFBlendEquationDestAlpha: - return MTLBlendFactorDestinationAlpha; - case GLTFBlendEquationDestColor: - return MTLBlendFactorDestinationColor; - case GLTFBlendEquationOneMinusSrcAlpha: - return MTLBlendFactorOneMinusSourceAlpha; - case GLTFBlendEquationOneMinusSrcColor: - return MTLBlendFactorOneMinusSourceColor; - case GLTFBlendEquationSrcAlphaSaturate: - return MTLBlendFactorSourceAlphaSaturated; - case GLTFBlendEquationOneMinusDestAlpha: - return MTLBlendFactorOneMinusDestinationAlpha; - case GLTFBlendEquationOneMinusDestColor: - return MTLBlendFactorOneMinusDestinationColor; - case GLTFBlendEquationOneMinusConstAlpha: - return MTLBlendFactorOneMinusDestinationColor; - default: - NSLog(@"Unsupported blend equation %d", (int)e); - return MTLBlendFactorOne; - } -} - -MTLCompareFunction GLTFMTLCompareFunctionForComparisonFunc(GLTFComparisonFunc f) { - switch (f) { - case GLTFComparisonFuncLess: - return MTLCompareFunctionLess; - case GLTFComparisonFuncEqual: - return MTLCompareFunctionEqual; - case GLTFComparisonFuncAlways: - return MTLCompareFunctionAlways; - case GLTFComparisonFuncGreater: - return MTLCompareFunctionGreater; - case GLTFComparisonFuncNotEqual: - return MTLCompareFunctionNotEqual; - case GLTFComparisonFuncLessEqual: - return MTLCompareFunctionLessEqual; - case GLTFComparisonFuncGreaterEqual: - return MTLCompareFunctionGreaterEqual; - default: - NSLog(@"Unsupported comparison function %d", (int)f); - return MTLCompareFunctionLess; - } -} - -MTLWinding GLTFMTLWindingForWinding(GLTFWinding w) { - switch (w) { - case GLTFWindingCounterclockwise: - return MTLWindingCounterClockwise; - case GLTFWindingClockwise: - default: - return MTLWindingClockwise; - } -} - -MTLCullMode GLTFMTLCullModeForCullFace(GLTFFace face) { - switch (face) { - case GLTFFaceBack: - return MTLCullModeBack; - case GLTFFaceFront: - return MTLCullModeFront; - default: - return MTLCullModeBack; - } -} - -MTLSamplerMinMagFilter GLTFMTLSamplerMinMagFilterForSamplingFilter(GLTFSamplingFilter mode) { - switch (mode) { - case GLTFSamplingFilterNearest: - return MTLSamplerMinMagFilterNearest; - default: - return MTLSamplerMinMagFilterLinear; - } -} - -MTLSamplerMipFilter GLTFMTLSamplerMipFilterForSamplingFilter(GLTFSamplingFilter mode) { - switch (mode) { - case GLTFSamplingFilterNearest: - case GLTFSamplingFilterLinear: - return MTLSamplerMipFilterNotMipmapped; - case GLTFSamplingFilterNearestMipNearest: - case GLTFSamplingFilterLinearMipNearest: - return MTLSamplerMipFilterNearest; - default: - return MTLSamplerMipFilterLinear; - } -} - -MTLSamplerAddressMode GLTFMTLSamplerAddressModeForSamplerAddressMode(GLTFAddressMode mode) { - switch (mode) { - case GLTFAddressModeClampToEdge: - return MTLSamplerAddressModeClampToEdge; - case GLTFAddressModeMirroredRepeat: - return MTLSamplerAddressModeMirrorRepeat; - default: - return MTLSamplerAddressModeRepeat; - } -} - -NSString *GLTFMTLTypeNameForType(GLTFDataType baseType, GLTFDataDimension dimension, BOOL packed) { - NSString *typeName = @"float"; - NSString *packingPrefix = @""; - NSString *dimensionSuffix = @""; - - if (packed && (dimension != GLTFDataDimensionScalar)) { - packingPrefix = @"packed_"; - } - - switch (baseType) { - case GLTFDataTypeBool: typeName = @"bool"; break; - case GLTFDataTypeChar: typeName = @"char"; break; - case GLTFDataTypeUChar: typeName = @"uchar"; break; - case GLTFDataTypeShort: typeName = @"short"; break; - case GLTFDataTypeUShort: typeName = @"ushort"; break; - case GLTFDataTypeInt: typeName = @"int"; break; - case GLTFDataTypeUInt: typeName = @"uint"; break; - case GLTFDataTypeFloat: typeName = @"float"; break; - case GLTFDataTypeSampler2D: typeName = @"texture2d"; break; - default: - return @"__UNKNOWN_TYPE__"; - } - - switch (dimension) { - case GLTFDataDimensionScalar: dimensionSuffix = @""; break; - case GLTFDataDimensionVector2: dimensionSuffix = @"2"; break; - case GLTFDataDimensionVector3: dimensionSuffix = @"3"; break; - case GLTFDataDimensionVector4: dimensionSuffix = @"4"; break; - case GLTFDataDimensionMatrix2x2: dimensionSuffix = @"float2x2"; break; - case GLTFDataDimensionMatrix3x3: dimensionSuffix = @"float3x3"; break; - case GLTFDataDimensionMatrix4x4: dimensionSuffix = @"float4x4"; break; - default: - return @"__UNKNOWN_TYPE__"; - } - - return [NSString stringWithFormat:@"%@%@%@", packingPrefix, typeName, dimensionSuffix]; -} - -MTLVertexFormat GLTFMTLVertexFormatForComponentTypeAndDimension(GLTFDataType baseType, GLTFDataDimension dimension) -{ - switch (baseType) { - case GLTFDataTypeChar: - switch (dimension) { - case GLTFDataDimensionVector2: - return MTLVertexFormatChar2; - case GLTFDataDimensionVector3: - return MTLVertexFormatChar3; - case GLTFDataDimensionVector4: - return MTLVertexFormatChar4; - default: - break; - } - case GLTFDataTypeUChar: - switch (dimension) { - case GLTFDataDimensionVector2: - return MTLVertexFormatUChar2; - case GLTFDataDimensionVector3: - return MTLVertexFormatUChar3; - case GLTFDataDimensionVector4: - return MTLVertexFormatUChar4; - default: - break; - } - case GLTFDataTypeShort: - switch (dimension) { - case GLTFDataDimensionVector2: - return MTLVertexFormatShort2; - case GLTFDataDimensionVector3: - return MTLVertexFormatShort3; - case GLTFDataDimensionVector4: - return MTLVertexFormatShort4; - default: - break; - } - case GLTFDataTypeUShort: - switch (dimension) { - case GLTFDataDimensionVector2: - return MTLVertexFormatUShort2; - case GLTFDataDimensionVector3: - return MTLVertexFormatUShort3; - case GLTFDataDimensionVector4: - return MTLVertexFormatUShort4; - default: - break; - } - case GLTFDataTypeInt: - switch (dimension) { - case GLTFDataDimensionScalar: - return MTLVertexFormatInt; - case GLTFDataDimensionVector2: - return MTLVertexFormatInt2; - case GLTFDataDimensionVector3: - return MTLVertexFormatInt3; - case GLTFDataDimensionVector4: - return MTLVertexFormatInt4; - default: - break; - } - case GLTFDataTypeUInt: - switch (dimension) { - case GLTFDataDimensionScalar: - return MTLVertexFormatUInt; - case GLTFDataDimensionVector2: - return MTLVertexFormatUInt2; - case GLTFDataDimensionVector3: - return MTLVertexFormatUInt3; - case GLTFDataDimensionVector4: - return MTLVertexFormatUInt4; - default: - break; - } - case GLTFDataTypeFloat: - switch (dimension) { - case GLTFDataDimensionScalar: - return MTLVertexFormatFloat; - case GLTFDataDimensionVector2: - return MTLVertexFormatFloat2; - case GLTFDataDimensionVector3: - return MTLVertexFormatFloat3; - case GLTFDataDimensionVector4: - return MTLVertexFormatFloat4; - default: - break; - } - default: - break; - } - - return MTLVertexFormatInvalid; -} - - diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMaterial.h b/platform/darwin/src/gltf/gltfkit/GLTFMaterial.h deleted file mode 100644 index cc8a889ab828..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMaterial.h +++ /dev/null @@ -1,65 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFObject.h" -#import "GLTFTexture.h" - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFParameter; - -typedef NS_ENUM(NSInteger, GLTFAlphaMode) { - GLTFAlphaModeOpaque, - GLTFAlphaModeMask, - GLTFAlphaModeBlend, -}; - -@interface GLTFMaterial : GLTFObject - -@property (nonatomic, assign) simd_float4 baseColorFactor; -@property (nonatomic, assign) float metalnessFactor; -@property (nonatomic, assign) float roughnessFactor; -@property (nonatomic, assign) float normalTextureScale; -@property (nonatomic, assign) float occlusionStrength; -@property (nonatomic, assign) simd_float3 emissiveFactor; - -@property (nonatomic, assign) - float glossinessFactor; // Only used by KHR_materials_pbrSpecularGlossiness extension -@property (nonatomic, assign) - simd_float3 specularFactor; // Only used by KHR_materials_pbrSpecularGlossiness extension - -@property (nonatomic, strong) GLTFTextureInfo* _Nullable baseColorTexture; -@property (nonatomic, strong) GLTFTextureInfo* _Nullable metallicRoughnessTexture; -@property (nonatomic, strong) GLTFTextureInfo* _Nullable normalTexture; -@property (nonatomic, strong) GLTFTextureInfo* _Nullable emissiveTexture; -@property (nonatomic, strong) GLTFTextureInfo* _Nullable occlusionTexture; - -@property (nonatomic, assign) - BOOL hasTextureTransforms; // Only used when KHR_texture_transform extension is present - -@property (nonatomic, assign, getter=isDoubleSided) BOOL doubleSided; - -@property (nonatomic, assign) GLTFAlphaMode alphaMode; -@property (nonatomic, assign) float alphaCutoff; // Only used when `alphaMode` == GLTFAlphaModeMask - -@property (nonatomic, assign, getter=isUnlit) - BOOL unlit; // Only used when KHR_materials_unlit extension is present - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMaterial.mm b/platform/darwin/src/gltf/gltfkit/GLTFMaterial.mm deleted file mode 100644 index e8f78a4700ed..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMaterial.mm +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFMaterial.h" - -@implementation GLTFMaterial - -- (instancetype)init { - if ((self = [super init])) { - _baseColorFactor = (simd_float4){ 1, 1, 1, 1 }; - _metalnessFactor = 1.0; - _roughnessFactor = 1.0; - _occlusionStrength = 1.0; - _emissiveFactor = (simd_float3) { 0.0, 0.0, 0.0 }; - _normalTextureScale = 1.0; - _alphaMode = GLTFAlphaModeOpaque; - _alphaCutoff = 0.5; - } - return self; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMesh.h b/platform/darwin/src/gltf/gltfkit/GLTFMesh.h deleted file mode 100644 index 19d4ea6f9ee7..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMesh.h +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFEnums.h" -#import "GLTFObject.h" - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFAccessor, GLTFVertexDescriptor, GLTFSubmesh, GLTFMaterial; - -@interface GLTFMesh : GLTFObject -@property (nonatomic, copy) NSArray *submeshes; -@property (nonatomic, copy) NSArray *defaultMorphTargetWeights; -@end - -@interface GLTFMorphTarget : GLTFObject -@property (nonatomic, copy) NSDictionary *accessorsForAttributes; -@end - -@interface GLTFSubmesh : GLTFObject -@property (nonatomic, copy) NSDictionary *accessorsForAttributes; -@property (nonatomic, weak) GLTFAccessor *indexAccessor; -@property (nonatomic, weak) GLTFMaterial *material; -@property (nonatomic, assign) GLTFPrimitiveType primitiveType; -@property (nonatomic, copy) NSArray *morphTargets; - -@property (nonatomic, readonly) GLTFVertexDescriptor *vertexDescriptor; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMesh.mm b/platform/darwin/src/gltf/gltfkit/GLTFMesh.mm deleted file mode 100644 index bc6ae3a88407..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMesh.mm +++ /dev/null @@ -1,69 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFMesh.h" -#import "GLTFVertexDescriptor.h" -#import "GLTFAccessor.h" -#import "GLTFBufferView.h" -#import "GLTFUtilities.h" - -@implementation GLTFMesh -@end - -@implementation GLTFMorphTarget -@end - -@interface GLTFSubmesh () -@property (nonatomic, strong) GLTFVertexDescriptor *cachedVertexDescriptor; -@end - -@implementation GLTFSubmesh - -- (instancetype)init { - if ((self = [super init])) { - _primitiveType = GLTFPrimitiveTypeTriangles; - } - return self; -} - -- (void)setAccessorsForAttributes:(NSDictionary *)accessorsForAttributes { - _accessorsForAttributes = accessorsForAttributes; - _cachedVertexDescriptor = nil; -} - -- (GLTFVertexDescriptor *)vertexDescriptor { - if (self.cachedVertexDescriptor == nil) { - GLTFVertexDescriptor *descriptor = [GLTFVertexDescriptor new]; - __block NSUInteger index = 0; - [self.accessorsForAttributes enumerateKeysAndObjectsUsingBlock:^(NSString *name, GLTFAccessor *accessor, BOOL *stop) { - descriptor.attributes[index].componentType = accessor.componentType; - descriptor.attributes[index].dimension = accessor.dimension; - descriptor.attributes[index].offset = accessor.offset; - descriptor.attributes[index].semantic = name; - if (accessor.bufferView.stride > 0) { - descriptor.bufferLayouts[index].stride = accessor.bufferView.stride; - } else { - descriptor.bufferLayouts[index].stride = GLTFSizeOfComponentTypeWithDimension(accessor.componentType, accessor.dimension); - } - ++index; - }]; - self.cachedVertexDescriptor = descriptor; - } - - return self.cachedVertexDescriptor; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFNode.h b/platform/darwin/src/gltf/gltfkit/GLTFNode.h deleted file mode 100644 index f370d0299095..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFNode.h +++ /dev/null @@ -1,49 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import -#import "GLTFNodeVisitor.h" -#import "GLTFObject.h" -#import "GLTFUtilities.h" - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFCamera, GLTFSkin, GLTFMesh; -@class GLTFKHRLight; - -@interface GLTFNode : GLTFObject -@property (nonatomic, weak) GLTFCamera *_Nullable camera; -@property (nonatomic, weak) GLTFKHRLight *_Nullable light; -@property (nonatomic, weak) GLTFNode *_Nullable parent; -@property (nonatomic, copy) NSArray *children; -@property (nonatomic, weak) GLTFSkin *_Nullable skin; -@property (nonatomic, copy) NSString *_Nullable jointName; -@property (nonatomic, weak) GLTFMesh *_Nullable mesh; -@property (nonatomic, copy) NSArray *morphTargetWeights; -@property (nonatomic, assign) GLTFQuaternion rotationQuaternion; -@property (nonatomic, assign) simd_float3 scale; -@property (nonatomic, assign) simd_float3 translation; -@property (nonatomic, assign) simd_float4x4 localTransform; -@property (nonatomic, readonly, assign) simd_float4x4 globalTransform; -@property (nonatomic, readonly, assign) - GLTFBoundingBox approximateBounds; // axis-aligned; in local coordinates - -- (void)addChildNode:(GLTFNode *)node; -- (void)removeFromParent; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFNode.mm b/platform/darwin/src/gltf/gltfkit/GLTFNode.mm deleted file mode 100644 index 2630d49960c5..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFNode.mm +++ /dev/null @@ -1,171 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFNode.h" -#import "GLTFAccessor.h" -#import "GLTFMesh.h" -#import "GLTFVertexDescriptor.h" - -@interface GLTFNode () -@property (nonatomic, assign, getter=localTransformIsDirty) BOOL localTransformDirty; -@property (nonatomic, strong) NSMutableArray *mutableChildren; -@end - -@implementation GLTFNode - -@synthesize localTransform=_localTransform; - -- (instancetype)init { - if ((self = [super init])) { - _localTransform = matrix_identity_float4x4; - _rotationQuaternion = simd_quaternion(0.f, 0.f, 0.f, 1.f); - _scale = vector3(1.0f, 1.0f, 1.0f); - _translation = vector3(0.0f, 0.0f, 0.0f); - _morphTargetWeights = @[]; - } - return self; -} - -- (void)setChildren:(NSArray *)children { - _mutableChildren = [children mutableCopy]; -} - -- (NSArray *)children { - return [_mutableChildren copy]; -} - -- (void)addChildNode:(GLTFNode *)node { - if (node.parent) { - [node removeFromParent]; - } - node.parent = self; - [self.mutableChildren addObject:node]; -} - -- (void)removeFromParent { - [self.parent _removeChildNode:self]; -} - -- (void)_removeChildNode:(GLTFNode *)child { - [self.mutableChildren removeObject:child]; - child.parent = nil; -} - -- (void)setScale:(simd_float3)scale { - _scale = scale; - _localTransformDirty = YES; -} - -- (void)setRotationQuaternion:(GLTFQuaternion)rotationQuaternion { - _rotationQuaternion = rotationQuaternion; - _localTransformDirty = YES; -} - -- (void)setTranslation:(simd_float3)translation { - _translation = translation; - _localTransformDirty = YES; -} - -- (simd_float4x4)globalTransform { - simd_float4x4 localTransform = self.localTransform; - simd_float4x4 ancestorTransform = self.parent ? self.parent.globalTransform : matrix_identity_float4x4; - return matrix_multiply(ancestorTransform, localTransform); -} - -- (void)setLocalTransform:(simd_float4x4)localTransform { - _localTransform = localTransform; -} - -- (simd_float4x4)localTransform { - if (self.localTransformIsDirty) { - [self computeLocalTransform]; - } - - return _localTransform; -} - -- (void)computeLocalTransform { - simd_float4x4 translationMatrix = matrix_identity_float4x4; - translationMatrix.columns[3][0] = _translation[0]; - translationMatrix.columns[3][1] = _translation[1]; - translationMatrix.columns[3][2] = _translation[2]; - - simd_float4x4 rotationMatrix = simd_matrix4x4(_rotationQuaternion); - - simd_float4x4 scaleMatrix = matrix_identity_float4x4; - scaleMatrix.columns[0][0] = _scale[0]; - scaleMatrix.columns[1][1] = _scale[1]; - scaleMatrix.columns[2][2] = _scale[2]; - - _localTransform = matrix_multiply(matrix_multiply(translationMatrix, rotationMatrix), scaleMatrix); - _localTransformDirty = NO; -} - -- (GLTFBoundingBox)approximateBounds { - return [self _approximateBoundsRecursive:matrix_identity_float4x4]; -} - -- (GLTFBoundingBox)_approximateBoundsRecursive:(simd_float4x4)transform { - GLTFBoundingBox bounds = { 0, 0 }; - - if (self.mesh != nil) { - for (GLTFSubmesh *submesh in self.mesh.submeshes) { - GLTFBoundingBox submeshBounds = { 0, 0 }; - GLTFAccessor *positionAccessor = submesh.accessorsForAttributes[GLTFAttributeSemanticPosition]; - GLTFValueRange positionRange = positionAccessor.valueRange; - submeshBounds.minPoint.x = positionRange.minValue[0]; - submeshBounds.minPoint.y = positionRange.minValue[1]; - submeshBounds.minPoint.z = positionRange.minValue[2]; - submeshBounds.maxPoint.x = positionRange.maxValue[0]; - submeshBounds.maxPoint.y = positionRange.maxValue[1]; - submeshBounds.maxPoint.z = positionRange.maxValue[2]; - GLTFBoundingBoxUnion(&bounds, submeshBounds); - } - } - - simd_float4x4 globalTransform = matrix_multiply(transform, self.localTransform); - - GLTFBoundingBoxTransform(&bounds, globalTransform); - - for (GLTFNode *child in self.children) { - GLTFBoundingBox childBounds = [child _approximateBoundsRecursive:globalTransform]; - GLTFBoundingBoxUnion(&bounds, childBounds); - } - - return bounds; -} - -- (void)acceptVisitor:(GLTFNodeVisitor)visitor strategy:(GLTFVisitationStrategy)strategy { - [self _acceptVisitor:visitor depth:0 strategy:strategy]; -} - -- (void)_acceptVisitor:(GLTFNodeVisitor)visitor depth:(int)depth strategy:(GLTFVisitationStrategy)strategy { - switch (strategy) { - case GLTFVisitationStrategyDepthFirst: - default: - { - BOOL recurse = YES; - visitor(self, depth, &recurse); - if (recurse) { - for (GLTFNode *child in self.children) { - [child _acceptVisitor:visitor depth:(depth + 1) strategy:strategy]; - } - } - } - } -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFNodeVisitor.h b/platform/darwin/src/gltf/gltfkit/GLTFNodeVisitor.h deleted file mode 100644 index ee3ce2b5de46..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFNodeVisitor.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFNode; - -typedef NS_ENUM(NSInteger, GLTFVisitationStrategy) { GLTFVisitationStrategyDepthFirst }; - -typedef void (^GLTFNodeVisitor)(GLTFNode *node, int depth, BOOL *stop); - -@protocol GLTFNodeVisitable -- (void)acceptVisitor:(GLTFNodeVisitor)visitor strategy:(GLTFVisitationStrategy)strategy; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFObject.h b/platform/darwin/src/gltf/gltfkit/GLTFObject.h deleted file mode 100644 index 146d6c82a300..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFObject.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@protocol GLTFObject - -/// The user-defined name of this object. Need not be unique. -@property (nonatomic, copy) NSString *_Nullable name; -/// Data specific to any extensions used in this document -@property (nonatomic, copy) NSDictionary *extensions; -/// Contains application-specific information that is passed through but not parsed -@property (nonatomic, copy) NSDictionary *extras; - -@end - -@interface GLTFObject : NSObject - -/// A unique identifier for this object -@property (nonatomic, readonly) NSUUID *identifier; -/// The user-defined name of this object. Need not be unique. -@property (nonatomic, copy) NSString *_Nullable name; -/// Data specific to any extensions used in this document -@property (nonatomic, copy) NSDictionary *extensions; -/// Contains application-specific information that is passed through but not parsed -@property (nonatomic, copy) NSDictionary *extras; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFObject.mm b/platform/darwin/src/gltf/gltfkit/GLTFObject.mm deleted file mode 100644 index 42e9e79127aa..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFObject.mm +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFObject.h" - -@implementation GLTFObject - -- (instancetype)init { - if ((self = [super init])) { - _identifier = [NSUUID new]; - } - return self; -} - -- (NSString *)description { - return [NSString stringWithFormat:@"%@; name = %@", super.description, self.name]; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFScene.h b/platform/darwin/src/gltf/gltfkit/GLTFScene.h deleted file mode 100644 index 6abf39c6c92f..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFScene.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFNodeVisitor.h" -#import "GLTFObject.h" -#import "GLTFUtilities.h" - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFNode; -@class GLTFKHRLight; - -@interface GLTFScene : GLTFObject -@property (nonatomic, copy) NSArray *nodes; -@property (nonatomic, weak) GLTFKHRLight *_Nullable ambientLight; -@property (nonatomic, readonly, assign) GLTFBoundingBox approximateBounds; - -- (void)addNode:(GLTFNode *)node; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFScene.mm b/platform/darwin/src/gltf/gltfkit/GLTFScene.mm deleted file mode 100644 index b3f0a6901277..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFScene.mm +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFScene.h" -#import "GLTFNode.h" - -@interface GLTFScene () -@property (nonatomic, strong) NSMutableArray *mutableNodes; -@end - -@implementation GLTFScene - -- (void)setNodes:(NSArray *)nodes { - _mutableNodes = [nodes mutableCopy]; -} - -- (NSArray *)nodes { - return [_mutableNodes copy]; -} - -- (void)addNode:(GLTFNode *)node { - if (node.parent) { - [node removeFromParent]; - } - - [_mutableNodes addObject:node]; -} - -- (GLTFBoundingBox)approximateBounds { - GLTFBoundingBox sceneBounds = { 0, 0 }; - for (GLTFNode *node in self.nodes) { - GLTFBoundingBox nodeBounds = node.approximateBounds; - GLTFBoundingBoxUnion(&sceneBounds, nodeBounds); - } - return sceneBounds; -} - -- (void)acceptVisitor:(GLTFNodeVisitor)visitor strategy:(GLTFVisitationStrategy)strategy { - for (GLTFNode *node in self.nodes) { - [node acceptVisitor:visitor strategy:strategy]; - } -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFSkin.h b/platform/darwin/src/gltf/gltfkit/GLTFSkin.h deleted file mode 100644 index fa5a8aee553e..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFSkin.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import -#import "GLTFObject.h" - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFAccessor, GLTFNode; - -@interface GLTFSkin : GLTFObject -@property (nonatomic, strong) GLTFAccessor *inverseBindMatricesAccessor; -@property (nonatomic, copy) NSArray *jointNodes; -@property (nonatomic, assign) GLTFNode *skeletonRootNode; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFSkin.mm b/platform/darwin/src/gltf/gltfkit/GLTFSkin.mm deleted file mode 100644 index c6c5dfbfbdc2..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFSkin.mm +++ /dev/null @@ -1,20 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFSkin.h" - -@implementation GLTFSkin -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFTexture.h b/platform/darwin/src/gltf/gltfkit/GLTFTexture.h deleted file mode 100644 index 7b7a9f97bb0d..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFTexture.h +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import -#import "../GLTFMath.hpp" -#import "GLTFEnums.h" -#import "GLTFObject.h" - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFTextureSampler, GLTFImage; - -@interface GLTFTexture : GLTFObject - -@property (nonatomic, weak) GLTFTextureSampler *sampler; - -@property (nonatomic, weak) GLTFImage *image; - -// GLTFTextureFormatRGBA -@property (nonatomic, assign) GLTFTextureFormat format; - -// GLTFTextureFormatRGBA -@property (nonatomic, assign) GLTFTextureFormat internalFormat; - -// GLTFTextureTypeUChar -@property (nonatomic, assign) GLTFTextureType type; - -// GLTFTextureTargetTexture2D -@property (nonatomic, assign) GLTFTextureTarget target; - -@end - -@interface GLTFTextureInfo : NSObject - -@property (nonatomic, strong) GLTFTexture *texture; - -@property (nonatomic, assign) NSInteger texCoord; - -// The transform to apply to texture coordinates before sampling from this texture. -// Defaults to the identity transform. Only populated if KHR_texture_transform is included -// as an optional or required extension for the containing asset. -@property (nonatomic, assign) GLTFTextureTransform transform; - -@property (nonatomic, strong) NSDictionary *_Nullable extensions; - -@property (nonatomic, strong) NSDictionary *_Nullable extras; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFTexture.mm b/platform/darwin/src/gltf/gltfkit/GLTFTexture.mm deleted file mode 100644 index 0f5d77fdeb82..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFTexture.mm +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFTexture.h" -#import "GLTFUtilities.h" - - -@implementation GLTFTexture - -- (instancetype)init { - if ((self = [super init])) { - _format = GLTFTextureFormatRGBA; - _internalFormat = GLTFTextureFormatRGBA; - _type = GLTFTextureTypeUChar; - _target = GLTFTextureTargetTexture2D; - } - return self; -} - -@end - -@implementation GLTFTextureInfo - -- (instancetype)init { - if ((self = [super init])) { - _transform = GLTFTextureTransformMakeIdentity(); - } - return self; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.h b/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.h deleted file mode 100644 index fbe3b026f529..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFEnums.h" -#import "GLTFObject.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface GLTFTextureSampler : GLTFObject - -// GLTFSamplingFilterLinear -@property (nonatomic, assign) GLTFSamplingFilter magFilter; -// GLTFSamplingFilterNearestMipLinear -@property (nonatomic, assign) GLTFSamplingFilter minFilter; -// GLTFAddressModeRepeat -@property (nonatomic, assign) GLTFAddressMode sAddressMode; -// GLTFAddressModeRepeat -@property (nonatomic, assign) GLTFAddressMode tAddressMode; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.mm b/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.mm deleted file mode 100644 index 2078acb52ea4..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.mm +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFTextureSampler.h" - -@implementation GLTFTextureSampler - -- (instancetype)init { - if ((self = [super init])) { - _magFilter = GLTFSamplingFilterLinear; - _minFilter = GLTFSamplingFilterNearestMipLinear; - _sAddressMode = GLTFAddressModeRepeat; - _tAddressMode = GLTFAddressModeRepeat; - } - return self; -} - -- (BOOL)isEqual:(id)other { - if (![other isKindOfClass:[GLTFTextureSampler class]]) { - return NO; - } - - GLTFTextureSampler *otherSampler = (GLTFTextureSampler *)other; - BOOL areEqual = - (otherSampler.magFilter == self.magFilter) && - (otherSampler.minFilter == self.minFilter) && - (otherSampler.sAddressMode == self.sAddressMode) && - (otherSampler.tAddressMode == self.tAddressMode); - return areEqual; -} - -- (NSUInteger)hash { - NSUInteger hashValue = ((_sAddressMode << 16) | _tAddressMode) + ((_magFilter << 16) | _minFilter); - return hashValue; -} - -- (id)copyWithZone:(NSZone *)zone { - GLTFTextureSampler *copy = [[GLTFTextureSampler allocWithZone:zone] init]; - copy.magFilter = self.magFilter; - copy.minFilter = self.minFilter; - copy.sAddressMode = self.sAddressMode; - copy.tAddressMode = self.tAddressMode; - return copy; -} - -@end - diff --git a/platform/darwin/src/gltf/gltfkit/GLTFUtilities.h b/platform/darwin/src/gltf/gltfkit/GLTFUtilities.h deleted file mode 100644 index db7a39064ce5..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFUtilities.h +++ /dev/null @@ -1,72 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFEnums.h" - -#import -#import -#import "../GLTFMath.hpp" - -NS_ASSUME_NONNULL_BEGIN - -typedef struct __attribute__((packed)) { - float x, y, z; -} GLTFVector3; - -typedef struct __attribute__((packed)) { - float x, y, z, w; -} GLTFVector4; - -typedef struct __attribute__((packed)) { - GLTFVector4 columns[4]; -} GLTFMatrix4; - -typedef simd_quatf GLTFQuaternion; - -extern bool GLTFBoundingBoxIsEmpty(GLTFBoundingBox b); - -extern GLTFBoundingBox *GLTFBoundingBoxUnion(GLTFBoundingBox *a, GLTFBoundingBox b); - -extern void GLTFBoundingBoxTransform(GLTFBoundingBox *b, simd_float4x4 transform); - -extern GLTFQuaternion GLTFQuaternionFromEulerAngles(float pitch, float yaw, float roll); - -extern simd_float3x3 GLTFMatrixUpperLeft3x3(simd_float4x4); - -extern simd_float4x4 GLTFNormalMatrixFromModelMatrix(simd_float4x4); - -extern GLTFDataDimension GLTFDataDimensionForName(NSString *name); - -extern size_t GLTFSizeOfDataType(GLTFDataType type); - -extern size_t GLTFSizeOfComponentTypeWithDimension(GLTFDataType baseType, - GLTFDataDimension dimension); - -extern NSInteger GLTFComponentCountForDimension(GLTFDataDimension dimension); - -extern BOOL GLTFDataTypeComponentsAreFloats(GLTFDataType type); - -extern simd_float2 GLTFVectorFloat2FromArray(NSArray *array); - -extern simd_float3 GLTFVectorFloat3FromArray(NSArray *array); - -extern simd_float4 GLTFVectorFloat4FromArray(NSArray *array); - -extern GLTFQuaternion GLTFQuaternionFromArray(NSArray *array); - -extern simd_float4x4 GLTFMatrixFloat4x4FromArray(NSArray *array); - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFUtilities.mm b/platform/darwin/src/gltf/gltfkit/GLTFUtilities.mm deleted file mode 100644 index ecce6e6fc0bc..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFUtilities.mm +++ /dev/null @@ -1,262 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFUtilities.h" -#include "GLTFEnums.h" - -bool GLTFBoundingBoxIsEmpty(GLTFBoundingBox b) { - return (b.minPoint.x == b.maxPoint.x) && (b.minPoint.y == b.maxPoint.y) && (b.minPoint.z == b.maxPoint.z); -} - -GLTFBoundingBox *GLTFBoundingBoxUnion(GLTFBoundingBox *a, GLTFBoundingBox b) { - bool leftEmpty = GLTFBoundingBoxIsEmpty(*a); - bool rightEmpty = GLTFBoundingBoxIsEmpty(b); - - if (leftEmpty) { - if (!rightEmpty) { - *a = b; - } - } else if (!rightEmpty) { - if (b.minPoint.x < a->minPoint.x) { a->minPoint.x = b.minPoint.x; } - if (b.minPoint.y < a->minPoint.y) { a->minPoint.y = b.minPoint.y; } - if (b.minPoint.z < a->minPoint.z) { a->minPoint.z = b.minPoint.z; } - if (b.maxPoint.x > a->maxPoint.x) { a->maxPoint.x = b.maxPoint.x; } - if (b.maxPoint.y > a->maxPoint.y) { a->maxPoint.y = b.maxPoint.y; } - if (b.maxPoint.z > a->maxPoint.z) { a->maxPoint.z = b.maxPoint.z; } - } - - return a; -} - -void GLTFBoundingBoxTransform(GLTFBoundingBox *b, simd_float4x4 transform) { - simd_float4 ltf = (simd_float4) { b->minPoint.x, b->maxPoint.y, b->maxPoint.z, 1 }; - simd_float4 rtf = (simd_float4) { b->maxPoint.x, b->maxPoint.y, b->maxPoint.z, 1 }; - simd_float4 lbf = (simd_float4) { b->minPoint.x, b->minPoint.y, b->maxPoint.z, 1 }; - simd_float4 rbf = (simd_float4) { b->maxPoint.x, b->minPoint.y, b->maxPoint.z, 1 }; - simd_float4 ltb = (simd_float4) { b->minPoint.x, b->maxPoint.y, b->minPoint.z, 1 }; - simd_float4 rtb = (simd_float4) { b->maxPoint.x, b->maxPoint.y, b->minPoint.z, 1 }; - simd_float4 lbb = (simd_float4) { b->minPoint.x, b->minPoint.y, b->minPoint.z, 1 }; - simd_float4 rbb = (simd_float4) { b->maxPoint.x, b->minPoint.y, b->minPoint.z, 1 }; - - ltf = matrix_multiply(transform, ltf); - rtf = matrix_multiply(transform, rtf); - lbf = matrix_multiply(transform, lbf); - rbf = matrix_multiply(transform, rbf); - ltb = matrix_multiply(transform, ltb); - rtb = matrix_multiply(transform, rtb); - lbb = matrix_multiply(transform, lbb); - rbb = matrix_multiply(transform, rbb); - - b->minPoint.x = fmin(fmin(fmin(fmin(fmin(fmin(fmin(ltf.x, rtf.x), lbf.x), rbf.x), ltb.x), rtb.x), lbb.x), rbb.x); - b->minPoint.y = fmin(fmin(fmin(fmin(fmin(fmin(fmin(ltf.y, rtf.y), lbf.y), rbf.y), ltb.y), rtb.y), lbb.y), rbb.y); - b->minPoint.z = fmin(fmin(fmin(fmin(fmin(fmin(fmin(ltf.z, rtf.z), lbf.z), rbf.z), ltb.z), rtb.z), lbb.z), rbb.z); - b->maxPoint.x = fmax(fmax(fmax(fmax(fmax(fmax(fmax(ltf.x, rtf.x), lbf.x), rbf.x), ltb.x), rtb.x), lbb.x), rbb.x); - b->maxPoint.y = fmax(fmax(fmax(fmax(fmax(fmax(fmax(ltf.y, rtf.y), lbf.y), rbf.y), ltb.y), rtb.y), lbb.y), rbb.y); - b->maxPoint.z = fmax(fmax(fmax(fmax(fmax(fmax(fmax(ltf.z, rtf.z), lbf.z), rbf.z), ltb.z), rtb.z), lbb.z), rbb.z); -} - - - -GLTFQuaternion GLTFQuaternionFromEulerAngles(float pitch, float yaw, float roll) { - float cx = cos(pitch / 2); - float sx = sin(pitch / 2); - float cy = cos(yaw / 2); - float sy = sin(yaw / 2); - float cz = cos(roll / 2); - float sz = sin(roll / 2); - - GLTFQuaternion q = simd_quaternion( - sx*cy*cz + cx*sy*sz, - cx*sy*cz + sx*cy*sz, - cx*cy*sz - sx*sy*cz, - cx*cy*cz - sx*sy*sz - ); - return q; -} - - - - - - - - - - - -GLTFDataDimension GLTFDataDimensionForName(NSString *name) { - if ([name isEqualToString:@"SCALAR"]) { - return GLTFDataDimensionScalar; - } else if ([name isEqualToString:@"VEC2"]) { - return GLTFDataDimensionVector2; - } else if ([name isEqualToString:@"VEC2"]) { - return GLTFDataDimensionVector2; - } else if ([name isEqualToString:@"VEC3"]) { - return GLTFDataDimensionVector3; - } else if ([name isEqualToString:@"VEC4"]) { - return GLTFDataDimensionVector4; - } else if ([name isEqualToString:@"MAT2"]) { - return GLTFDataDimensionMatrix2x2; - } else if ([name isEqualToString:@"MAT3"]) { - return GLTFDataDimensionMatrix3x3; - } else if ([name isEqualToString:@"MAT4"]) { - return GLTFDataDimensionMatrix4x4; - } - - return GLTFDataDimensionUnknown; -} - -size_t GLTFSizeOfDataType(GLTFDataType type) { - - switch (type) { - case GLTFDataTypeChar: return sizeof(char); - case GLTFDataTypeUChar: return sizeof(unsigned char); - case GLTFDataTypeShort: return sizeof(short); - case GLTFDataTypeUShort: return sizeof(unsigned short); - case GLTFDataTypeInt: return sizeof(int); - case GLTFDataTypeUInt: return sizeof(unsigned int); - case GLTFDataTypeFloat: return sizeof(float); - case GLTFDataTypeFloat2: return sizeof(float) * 2; - case GLTFDataTypeFloat3: return sizeof(float) * 3; - case GLTFDataTypeFloat4: return sizeof(float) * 4; - case GLTFDataTypeInt2: return sizeof(int) * 2; - case GLTFDataTypeInt3: return sizeof(int) * 3; - case GLTFDataTypeInt4: return sizeof(int) * 4; - case GLTFDataTypeBool: return sizeof(bool); - case GLTFDataTypeBool2: return sizeof(bool) * 2; - case GLTFDataTypeBool3: return sizeof(bool) * 3; - case GLTFDataTypeBool4: return sizeof(bool) * 4; - case GLTFDataTypeFloat2x2: return sizeof(float) * 4; - case GLTFDataTypeFloat3x3: return sizeof(float) * 9; - case GLTFDataTypeFloat4x4: return sizeof(float) * 16; - case GLTFDataTypeSampler2D: return sizeof(size_t); - default: return 0; - } -} - -size_t GLTFSizeOfComponentTypeWithDimension(GLTFDataType baseType, GLTFDataDimension dimension) -{ - switch (baseType) { - case GLTFDataTypeChar: - case GLTFDataTypeUChar: - switch (dimension) { - case GLTFDataDimensionVector2: - return 2; - case GLTFDataDimensionVector3: - return 3; - case GLTFDataDimensionVector4: - return 4; - default: - break; - } - case GLTFDataTypeShort: - case GLTFDataTypeUShort: - switch (dimension) { - case GLTFDataDimensionVector2: - return 4; - case GLTFDataDimensionVector3: - return 6; - case GLTFDataDimensionVector4: - return 8; - default: - break; - } - case GLTFDataTypeInt: - case GLTFDataTypeUInt: - case GLTFDataTypeFloat: - switch (dimension) { - case GLTFDataDimensionScalar: - return 4; - case GLTFDataDimensionVector2: - return 8; - case GLTFDataDimensionVector3: - return 12; - case GLTFDataDimensionVector4: - case GLTFDataDimensionMatrix2x2: - return 16; - case GLTFDataDimensionMatrix3x3: - return 36; - case GLTFDataDimensionMatrix4x4: - return 64; - default: - break; - } - default: - break; - } - return 0; -} - -NSInteger GLTFComponentCountForDimension(GLTFDataDimension dimension) { - switch (dimension) { - case GLTFDataDimensionScalar: - return 1; - case GLTFDataDimensionVector2: - return 2; - case GLTFDataDimensionVector3: - return 3; - case GLTFDataDimensionVector4: - return 4; - case GLTFDataDimensionMatrix2x2: - return 4; - case GLTFDataDimensionMatrix3x3: - return 9; - case GLTFDataDimensionMatrix4x4: - return 16; - default: - return 0; - } -} - -BOOL GLTFDataTypeComponentsAreFloats(GLTFDataType type) { - switch (type) { - case GLTFDataTypeFloat: - case GLTFDataTypeFloat2: - case GLTFDataTypeFloat3: - case GLTFDataTypeFloat4: - case GLTFDataTypeFloat2x2: - case GLTFDataTypeFloat3x3: - case GLTFDataTypeFloat4x4: - return YES; - default: - return NO; - } -} - -simd_float2 GLTFVectorFloat2FromArray(NSArray *array) { - return (simd_float2){ [array[0] floatValue], [array[1] floatValue] }; -} - -simd_float3 GLTFVectorFloat3FromArray(NSArray *array) { - return (simd_float3){ [array[0] floatValue], [array[1] floatValue], [array[2] floatValue] }; -} - -simd_float4 GLTFVectorFloat4FromArray(NSArray *array) { - return (simd_float4){ [array[0] floatValue], [array[1] floatValue], [array[2] floatValue], [array[3] floatValue] }; -} - -GLTFQuaternion GLTFQuaternionFromArray(NSArray *array) { - return simd_quaternion([array[0] floatValue], [array[1] floatValue], [array[2] floatValue], [array[3] floatValue]); -} - -simd_float4x4 GLTFMatrixFloat4x4FromArray(NSArray *array) { - return (simd_float4x4){ { - { [array[0] floatValue], [array[1] floatValue], [array[2] floatValue], [array[3] floatValue] }, - { [array[4] floatValue], [array[5] floatValue], [array[6] floatValue], [array[7] floatValue] }, - { [array[8] floatValue], [array[9] floatValue], [array[10] floatValue], [array[11] floatValue] }, - { [array[12] floatValue], [array[13] floatValue], [array[14] floatValue], [array[15] floatValue] } - } }; -} diff --git a/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.h b/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.h deleted file mode 100644 index beaf2bf9d093..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.h +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import -#import "GLTFEnums.h" - -NS_ASSUME_NONNULL_BEGIN - -extern const NSInteger GLTFVertexDescriptorMaxAttributeCount; -extern const NSInteger GLTFVertexDescriptorMaxBufferLayoutCount; - -extern NSString *const GLTFAttributeSemanticPosition; -extern NSString *const GLTFAttributeSemanticTangent; -extern NSString *const GLTFAttributeSemanticNormal; -extern NSString *const GLTFAttributeSemanticTexCoord0; -extern NSString *const GLTFAttributeSemanticTexCoord1; -extern NSString *const GLTFAttributeSemanticColor0; -extern NSString *const GLTFAttributeSemanticJoints0; -extern NSString *const GLTFAttributeSemanticJoints1; -extern NSString *const GLTFAttributeSemanticWeights0; -extern NSString *const GLTFAttributeSemanticWeights1; -extern NSString *const GLTFAttributeSemanticRoughness; -extern NSString *const GLTFAttributeSemanticMetallic; - -@interface GLTFVertexAttribute : NSObject -@property (nonatomic, copy) NSString *semantic; -@property (nonatomic, assign) GLTFDataType componentType; -@property (nonatomic, assign) GLTFDataDimension dimension; -@property (nonatomic, assign) NSInteger offset; -@end - -@interface GLTFBufferLayout : NSObject -@property (nonatomic, assign) NSInteger stride; -@end - -@interface GLTFVertexDescriptor : NSObject -@property (nonatomic, copy) NSArray *attributes; -@property (nonatomic, copy) NSArray *bufferLayouts; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.mm b/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.mm deleted file mode 100644 index 599d8706baa9..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.mm +++ /dev/null @@ -1,71 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFVertexDescriptor.h" - -const NSInteger GLTFVertexDescriptorMaxAttributeCount = 16; -const NSInteger GLTFVertexDescriptorMaxBufferLayoutCount = 16; - -NSString *const GLTFAttributeSemanticPosition = @"POSITION"; -NSString *const GLTFAttributeSemanticTangent = @"TANGENT"; -NSString *const GLTFAttributeSemanticNormal = @"NORMAL"; -NSString *const GLTFAttributeSemanticTexCoord0 = @"TEXCOORD_0"; -NSString *const GLTFAttributeSemanticTexCoord1 = @"TEXCOORD_1"; -NSString *const GLTFAttributeSemanticColor0 = @"COLOR_0"; -NSString *const GLTFAttributeSemanticJoints0 = @"JOINTS_0"; -NSString *const GLTFAttributeSemanticJoints1 = @"JOINTS_1"; -NSString *const GLTFAttributeSemanticWeights0 = @"WEIGHTS_0"; -NSString *const GLTFAttributeSemanticWeights1 = @"WEIGHTS_1"; -NSString *const GLTFAttributeSemanticRoughness = @"ROUGHNESS"; -NSString *const GLTFAttributeSemanticMetallic = @"METALLIC"; - -@implementation GLTFVertexAttribute - -- (NSString *)description { - return [NSString stringWithFormat:@"GLTFVertexAttribute: component type: %d, count: %d, offset %d [[%@]]", - (int)self.componentType, (int)self.dimension, (int)self.offset, self.semantic]; -} - -@end - -@implementation GLTFBufferLayout -@end - -@implementation GLTFVertexDescriptor - -- (instancetype)init { - if ((self = [super init])) { - NSMutableArray *mutableAttributes = [NSMutableArray arrayWithCapacity:GLTFVertexDescriptorMaxAttributeCount]; - for (int i = 0; i < GLTFVertexDescriptorMaxAttributeCount; ++i) { - [mutableAttributes addObject: [GLTFVertexAttribute new]]; - } - _attributes = [mutableAttributes copy]; - - NSMutableArray *mutableLayouts = [NSMutableArray arrayWithCapacity:GLTFVertexDescriptorMaxBufferLayoutCount]; - for (int i = 0; i < GLTFVertexDescriptorMaxBufferLayoutCount; ++i) { - [mutableLayouts addObject: [GLTFBufferLayout new]]; - } - _bufferLayouts = [mutableLayouts copy]; - } - return self; -} - -- (NSString *)description { - return [NSString stringWithFormat:@"GLTFVertexDescriptor:\nattributes: %@\nlayouts: %@", - self.attributes, self.bufferLayouts]; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/shaders/brdf.metal b/platform/darwin/src/gltf/gltfkit/shaders/brdf.metal deleted file mode 100644 index 1f4e6b732872..000000000000 --- a/platform/darwin/src/gltf/gltfkit/shaders/brdf.metal +++ /dev/null @@ -1,230 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#include -using namespace metal; - -// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html -static float RadicalInverse_VdC(uint bits) -{ - bits = (bits << 16u) | (bits >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - return float(bits) * 2.3283064365386963e-10; // / 0x100000000 -} - -static float2 Hammersley(uint i, uint N) { - return float2(float(i) / float(N), RadicalInverse_VdC(i)); -} - -// http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf -static float GeometrySchlickGGX(float NdotV, float roughness) { - float a = roughness; - float k = (a * a) / 2.0; - return NdotV / (NdotV * (1.0 - k) + k); -} - -static float GeometrySmith(float NdotL, float NdotV, float roughness) { - float ggx2 = GeometrySchlickGGX(NdotV, roughness); - float ggx1 = GeometrySchlickGGX(NdotL, roughness); - return ggx1 * ggx2; -} - -static float3 ImportanceSampleGGX(float2 xi, float3 N, float roughness) { - float a = roughness * roughness; - float phi = 2 * M_PI_F * xi.x; - float cosTheta = sqrt((1 - xi.y) / (1 + (a * a - 1) * xi.y)); - float sinTheta = sqrt(1 - cosTheta * cosTheta); - - float3 H(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); - - float3 up = fabs(N.z) < 0.999 ? float3(0, 0, 1) : float3(1, 0, 0); - float3 tangent = normalize(cross(up, N)); - float3 bitangent = cross(N, tangent); - - return normalize(tangent * H.x + bitangent * H.y + N * H.z); -} - -static float2 IntegrateBRDF(float roughness, float NdotV) { - float3 N(0, 0, 1); - float3 V(sqrt(1.0 - NdotV * NdotV), 0, NdotV); - float A = 0; - float B = 0; - - const uint sampleCount = 1024; - for(uint i = 0; i < sampleCount; ++i) { - float2 x = Hammersley(i, sampleCount); - float3 H = ImportanceSampleGGX(x, N, roughness); - float3 L = normalize(2 * dot(V, H) * H - V); - - float NdotL = saturate(L.z); - float NdotH = saturate(H.z); - float VdotH = saturate(dot(V, H)); - - if(NdotL > 0) { - float G = GeometrySmith(NdotL, NdotV, roughness); - float G_Vis = G * VdotH / (NdotH * NdotV); - float Fc = powr(1 - VdotH, 5); - A += (1 - Fc) * G_Vis; - B += Fc * G_Vis; - } - } - - return float2(A, B) / float(sampleCount); -} - -kernel void integrate_brdf(texture2d lookup [[texture(0)]], - uint2 tpig [[thread_position_in_grid]]) -{ - float NdotV = (tpig.x + 1) / float(lookup.get_width()); - float roughness = (tpig.y + 1) / float(lookup.get_height()); - float2 scaleAndBias = IntegrateBRDF(roughness, NdotV); - half4 color(scaleAndBias.x, scaleAndBias.y, 0, 0); - lookup.write(color, tpig); -} - -static float2 CubeToEquirectCoords(float3 v) { - const float2 invAtan(0.1591, 0.3183); - float2 uv = float2(atan2(v.z, v.x), asin(v.y)) * invAtan + 0.5; - return uv; -} - -static float3 CubeDirectionFromUVAndFace(float2 uv, int face) { - float u = uv.x; - float v = uv.y; - float3 dir = float3(0); - switch (face) { - case 0: - dir = float3(-1, v, -u); break; // +X - case 1: - dir = float3( 1, v, u); break; // -X - case 2: - dir = float3(-u, -1, v); break; // +Y - case 3: - dir = float3(-u, 1, -v); break; // -Y - case 4: - dir = float3(-u, v, 1); break; // +Z - case 5: - dir = float3( u, v, -1); break; // -Z - } - - dir = normalize(dir); - return dir; -} - -kernel void equirect_to_cube(texture2d equirectangularMap, - texturecube cubeMap, - uint3 tpig [[thread_position_in_grid]]) -{ - constexpr sampler sampler2d(coord::normalized, filter::linear, address::repeat); - - float cubeSize = cubeMap.get_width(); - float2 cubeUV = ((float2(tpig.xy) / cubeSize) * 2 - 1); - int face = tpig.z; - float3 dir = CubeDirectionFromUVAndFace(cubeUV, face); - float2 rectUV = CubeToEquirectCoords(dir); - half4 color = equirectangularMap.sample(sampler2d, rectUV); - uint2 coords = tpig.xy; - cubeMap.write(color, coords, face); -} - -static float3 ComputeIrradiance(float3 N, texturecube environmentTexture) { - constexpr sampler cubeSampler(coord::normalized, filter::linear); - float3 irradiance = float3(0.0); - - float3 up(0.0, 1.0, 0.0); - float3 right = cross(up, N); - up = cross(N, right); - - float sampleDelta = 0.025; - float sampleCount = 0; - for (float phi = 0.0; phi < M_PI_F * 2; phi += sampleDelta) { - for (float theta = 0.0; theta < M_PI_F * 0.5; theta += sampleDelta) { - // spherical to cartesian (in tangent space) - float3 tangentSample(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); - // tangent space to world - float3 dir = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N; - - irradiance += float3(environmentTexture.sample(cubeSampler, dir).rgb) * cos(theta) * sin(theta); - sampleCount += 1; - } - } - - irradiance = M_PI_F * irradiance * (1.0 / sampleCount); - return irradiance; -} - -kernel void compute_irradiance(texturecube environmentMap, - texturecube irradianceMap, - uint3 tpig [[thread_position_in_grid]]) -{ - float cubeSize = irradianceMap.get_width(); - float2 cubeUV = ((float2(tpig.xy) / cubeSize) * 2 - 1); - int face = tpig.z; - float3 dir = CubeDirectionFromUVAndFace(cubeUV, face); - dir *= float3(-1, -1, 1); - float3 irrad = ComputeIrradiance(dir, environmentMap); - uint2 coords = tpig.xy; - irradianceMap.write(half4(half3(irrad), 1), coords, face); -} - -static float3 PrefilterEnvMap(float roughness, float3 R, texturecube environmentTexture) { - constexpr sampler cubeSampler(coord::normalized, filter::linear, mip_filter::linear); - - float3 N = R; - float3 V = R; - - float3 prefilteredColor(0); - float totalWeight = 0; - float resolution = environmentTexture.get_width(); - float saTexel = 4.0 * M_PI_F / (6.0 * resolution * resolution); - - const uint sampleCount = 512; - for(uint i = 0; i < sampleCount; ++i) { - float2 xi = Hammersley(i, sampleCount); - float3 H = ImportanceSampleGGX(xi, N, roughness); - float3 L = normalize(2 * dot(V, H) * H - V); - float NdotL = saturate(dot(N, L)); - if(NdotL > 0) { - float NdotH = saturate(dot(N, H)); - float HdotV = saturate(dot(H, V)); - float D = GeometrySchlickGGX(NdotH, roughness); - float pdf = (D * NdotH / (4.0 * HdotV)) + 0.0001; - float saSample = 1.0 / (float(sampleCount) * pdf + 0.0001); - float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel); - prefilteredColor += NdotL * float3(environmentTexture.sample(cubeSampler, L, level(mipLevel)).rgb); - totalWeight += NdotL; - } - } - return prefilteredColor / totalWeight; -} - -kernel void compute_prefiltered_specular(texturecube environmentMap, - texturecube specularMap, - constant float &roughness [[buffer(0)]], - uint3 tpig [[thread_position_in_grid]]) -{ - float cubeSize = specularMap.get_width(); - float2 cubeUV = ((float2(tpig.xy) / cubeSize) * 2 - 1); - int face = tpig.z; - float3 dir = CubeDirectionFromUVAndFace(cubeUV, face); - dir *= float3(-1, -1, 1); - float3 irrad = PrefilterEnvMap(roughness, dir, environmentMap); - uint2 coords = tpig.xy; - specularMap.write(half4(half3(irrad), 1), coords, face); -} diff --git a/platform/darwin/src/gltf/gltfkit/shaders/hdr.metal b/platform/darwin/src/gltf/gltfkit/shaders/hdr.metal deleted file mode 100644 index bb7f505a1a9f..000000000000 --- a/platform/darwin/src/gltf/gltfkit/shaders/hdr.metal +++ /dev/null @@ -1,123 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#include -using namespace metal; - -constexpr sampler linearSampler(coord::normalized, min_filter::linear, mag_filter::linear); -constexpr sampler nearestSampler(coord::normalized, min_filter::nearest, mag_filter::nearest); - -struct VertexOut { - float4 position [[position]]; - float2 texCoords; -}; - -vertex VertexOut quad_vertex_main(constant packed_float4 *vertices [[buffer(0)]], - uint vid [[vertex_id]]) -{ - VertexOut out; - float4 in = vertices[vid]; - out.position = float4(in.xy, 0, 1); - out.texCoords = in.zw; - return out; -} - -typedef VertexOut FragmentIn; - -static half3 reinhardToneMapping(half3 color) { - half exposure = 1.5; - color *= exposure / (1 + color / exposure); - return color; -} - -fragment half4 tonemap_fragment_main(FragmentIn in [[stage_in]], - texture2d sourceTexture [[texture(0)]]) -{ - // Original, pre-alpha -// half3 color = sourceTexture.sample(linearSampler, in.texCoords).rgb; -// return half4(reinhardToneMapping(color), 1); - - half4 color = sourceTexture.sample(linearSampler, in.texCoords); - return half4(reinhardToneMapping(color.rgb), color.a); - -} - - -fragment half4 bloom_threshold_fragment_main(FragmentIn in [[stage_in]], - texture2d sourceTexture [[texture(0)]]) -{ - const float bloomThreshold = 0.88; - const float bloomIntensity = 2; - half4 color = sourceTexture.sample(linearSampler, in.texCoords); - half luma = dot(color.rgb, half3(0.2126, 0.7152, 0.0722)); - return (luma > bloomThreshold) ? color * bloomIntensity : half4(0, 0, 0, 1); -} - -fragment half4 blur_horizontal7_fragment_main(FragmentIn in [[stage_in]], - texture2d sourceTexture [[texture(0)]]) -{ - float weights[]{ 0.134032, 0.126854, 0.107545, 0.08167, 0.055555, 0.033851, 0.018476, 0.009033 }; - float offset = 1.0 / sourceTexture.get_width(); - half4 color(0); - color += weights[7] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 7, 0)); - color += weights[6] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 6, 0)); - color += weights[5] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 5, 0)); - color += weights[4] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 4, 0)); - color += weights[3] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 3, 0)); - color += weights[2] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 2, 0)); - color += weights[1] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 1, 0)); - color += weights[0] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 0, 0)); - color += weights[1] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 1, 0)); - color += weights[2] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 2, 0)); - color += weights[3] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 3, 0)); - color += weights[4] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 4, 0)); - color += weights[5] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 5, 0)); - color += weights[6] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 6, 0)); - color += weights[7] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 7, 0)); - return color; -} - -fragment half4 blur_vertical7_fragment_main(FragmentIn in [[stage_in]], - texture2d sourceTexture [[texture(0)]]) -{ - float weights[]{ 0.134032, 0.126854, 0.107545, 0.08167, 0.055555, 0.033851, 0.018476, 0.009033 }; - float offset = 1.0 / sourceTexture.get_height(); - half4 color(0); - color += weights[7] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 7)); - color += weights[6] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 6)); - color += weights[5] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 5)); - color += weights[4] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 4)); - color += weights[3] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 3)); - color += weights[2] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 2)); - color += weights[1] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 1)); - color += weights[0] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 0)); - color += weights[1] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 1)); - color += weights[2] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 2)); - color += weights[3] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 3)); - color += weights[4] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 4)); - color += weights[5] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 5)); - color += weights[6] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 6)); - color += weights[7] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 7)); - return color; -} - -fragment half4 additive_blend_fragment_main(FragmentIn in [[stage_in]], - texture2d sourceTexture [[texture(0)]]) -{ - half4 color = sourceTexture.sample(linearSampler, in.texCoords); - return color; -} - diff --git a/platform/darwin/src/gltf/gltfkit/shaders/pbr.metal b/platform/darwin/src/gltf/gltfkit/shaders/pbr.metal deleted file mode 100644 index ad5ae9409c17..000000000000 --- a/platform/darwin/src/gltf/gltfkit/shaders/pbr.metal +++ /dev/null @@ -1,463 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#include -using namespace metal; - -constant half minRoughness = 0.04; - -constant int textureIndexBaseColor = 0; -constant int textureIndexNormal = 1; -constant int textureIndexMetallicRoughness = 2; -constant int textureIndexOcclusion = 3; -constant int textureIndexEmissive = 4; -constant int textureIndexDiffuseEnvironment = 5; -constant int textureIndexSpecularEnvironment = 6; -constant int textureIndexBRDFLookup = 7; - -/*%begin_replace_decls%*/ -#define USE_PBR 1 -#define USE_IBL 1 -#define USE_ALPHA_TEST 0 -#define USE_VERTEX_SKINNING 1 -#define USE_EXTENDED_VERTEX_SKINNING 1 -#define USE_DOUBLE_SIDED_MATERIAL 1 -#define HAS_TEXCOORD_0 1 -#define HAS_TEXCOORD_1 1 -#define HAS_VERTEX_COLOR 1 -#define HAS_VERTEX_ROUGHNESS 1 -#define HAS_VERTEX_METALLIC 1 -#define HAS_NORMALS 1 -#define HAS_TANGENTS 1 -#define HAS_BASE_COLOR_MAP 1 -#define HAS_NORMAL_MAP 1 -#define HAS_METALLIC_ROUGHNESS_MAP 1 -#define HAS_OCCLUSION_MAP 1 -#define HAS_EMISSIVE_MAP 1 -#define HAS_TEXTURE_TRANSFORM 1 -#define MATERIAL_IS_UNLIT 0 -#define PREMULTIPLY_BASE_COLOR 1 -#define SPECULAR_ENV_MIP_LEVELS 6 -#define MAX_LIGHTS 3 -#define MAX_MATERIAL_TEXTURES 5 - -#define BaseColorTexCoord texCoord0 -#define NormalTexCoord texCoord0 -#define MetallicRoughnessTexCoord texCoord0 -#define EmissiveTexCoord texCoord0 -#define OcclusionTexCoord texCoord0 - -struct VertexIn { - float3 position [[attribute(0)]]; - float3 normal [[attribute(1)]]; - float4 tangent [[attribute(2)]]; - float2 texCoord0 [[attribute(3)]]; - float2 texCoord1 [[attribute(4)]]; - float4 color [[attribute(5)]]; - float4 weights0 [[attribute(6)]]; - float4 weights1 [[attribute(7)]]; - ushort4 joints0 [[attribute(8)]]; - ushort4 joints1 [[attribute(9)]]; - float roughness [[attribute(10)]]; - float metalness [[attribute(11)]]; -}; -/*%end_replace_decls%*/ - -struct VertexOut { - float4 position [[position]]; - float3 worldPosition; - float2 texCoord0; - float2 texCoord1; - float4 color; - float3 tangent; - float3 bitangent; - float3 normal; - float roughness; - float metalness; -}; - -struct VertexUniforms { - float4x4 modelMatrix; - float4x4 modelViewProjectionMatrix; - float4x4 normalMatrix; -}; - -struct Light { - float4 position; - float4 color; - float intensity; - float innerConeAngle; - float outerConeAngle; - float range; - float4 spotDirection; -}; - -struct FragmentUniforms { - float normalScale; - float3 emissiveFactor; - float occlusionStrength; - float2 metallicRoughnessValues; - float4 baseColorFactor; - float3 camera; - float alphaCutoff; - float envIntensity; - Light ambientLight; - Light lights[MAX_LIGHTS]; - float3x3 textureMatrices[MAX_MATERIAL_TEXTURES]; -}; - -vertex VertexOut vertex_main(VertexIn in [[stage_in]], - constant VertexUniforms &uniforms [[buffer(16)]] -#if USE_VERTEX_SKINNING - , constant float4x4 *jointMatrices [[buffer(17)]] -#endif -) -{ - VertexOut out = { 0 }; - - float4x4 normalMatrix = uniforms.normalMatrix; - - #if USE_VERTEX_SKINNING - ushort4 jointIndices = ushort4(in.joints0); - float4 jointWeights = float4(in.weights0); - - float4x4 skinMatrix = jointWeights[0] * jointMatrices[jointIndices[0]] + - jointWeights[1] * jointMatrices[jointIndices[1]] + - jointWeights[2] * jointMatrices[jointIndices[2]] + - jointWeights[3] * jointMatrices[jointIndices[3]]; - - #if USE_EXTENDED_VERTEX_SKINNING - jointIndices = ushort4(in.joints1); - jointWeights = float4(in.weights1); - - skinMatrix += jointWeights[0] * jointMatrices[jointIndices[0]] + - jointWeights[1] * jointMatrices[jointIndices[1]] + - jointWeights[2] * jointMatrices[jointIndices[2]] + - jointWeights[3] * jointMatrices[jointIndices[3]]; - #endif - - float4 skinnedPosition = skinMatrix * float4(in.position.xyz, 1); - normalMatrix = normalMatrix * skinMatrix; - #else - float4 skinnedPosition = float4(in.position.xyz, 1); - #endif - - float4 position = uniforms.modelMatrix * skinnedPosition; - out.worldPosition = position.xyz / position.w; - - out.position = uniforms.modelViewProjectionMatrix * skinnedPosition; - - #if HAS_NORMALS - #if HAS_TANGENTS - float3 normalW = normalize(float3(normalMatrix * float4(in.normal.xyz, 0.0))); - float3 tangentW = normalize(float3(normalMatrix * float4(in.tangent.xyz, 0.0))); - float3 bitangentW = cross(normalW, tangentW) * in.tangent.w; - out.tangent = tangentW; - out.bitangent = bitangentW; - out.normal = normalW; - #else - out.normal = normalize(float3(normalMatrix * float4(in.normal.xyz, 0.0))); - #endif - #endif - - #if HAS_VERTEX_COLOR - #if VERTEX_COLOR_IS_RGB - out.color = float4(in.color, 1); - #else - out.color = in.color; - #endif - #endif - - #if HAS_VERTEX_ROUGHNESS - out.roughness = in.roughness; - #endif - - #if HAS_VERTEX_METALLIC - out.metalness = in.metalness; - #endif - - #if HAS_TEXCOORD_0 - out.texCoord0 = in.texCoord0; - #endif - - #if HAS_TEXCOORD_1 - out.texCoord1 = in.texCoord1; - #endif - - return out; -} - -static half3 LambertDiffuse(half3 baseColor) -{ - return baseColor / M_PI_F; -} - -static half3 SchlickFresnel(half3 F0, float LdotH) -{ - return F0 + (1 - F0) * pow(1.0 - LdotH, 5.0); -} - -static float SmithGeometric(float NdotL, float NdotV, float roughness) -{ - float k = roughness * 0.5; - float Gl = NdotL / ((NdotL * (1 - k)) + k); - float Gv = NdotV / ((NdotV * (1 - k)) + k); - return Gl * Gv; -} - -static float TrowbridgeReitzNDF(float NdotH, float roughness) -{ - float roughnessSq = roughness * roughness; - float f = NdotH * (NdotH * roughnessSq - NdotH) + 1; - return roughnessSq / (M_PI_F * f * f); -} - -fragment half4 fragment_main(VertexOut in [[stage_in]], -#if HAS_BASE_COLOR_MAP - texture2d baseColorTexture [[texture(textureIndexBaseColor)]], - sampler baseColorSampler [[sampler(textureIndexBaseColor)]], -#endif -#if HAS_NORMAL_MAP - texture2d normalTexture [[texture(textureIndexNormal)]], - sampler normalSampler [[sampler(textureIndexNormal)]], -#endif -#if HAS_EMISSIVE_MAP - texture2d emissiveTexture [[texture(textureIndexEmissive)]], - sampler emissiveSampler [[sampler(textureIndexEmissive)]], -#endif -#if HAS_METALLIC_ROUGHNESS_MAP - texture2d metallicRoughnessTexture [[texture(textureIndexMetallicRoughness)]], - sampler metallicRoughnessSampler [[sampler(textureIndexMetallicRoughness)]], -#endif -#if HAS_OCCLUSION_MAP - texture2d occlusionTexture [[texture(textureIndexOcclusion)]], - sampler occlusionSampler [[sampler(textureIndexOcclusion)]], -#endif -#if USE_IBL - texturecube diffuseEnvTexture [[texture(textureIndexDiffuseEnvironment)]], - texturecube specularEnvTexture [[texture(textureIndexSpecularEnvironment)]], - texture2d brdfLUT [[texture(textureIndexBRDFLookup)]], -#endif - constant FragmentUniforms &uniforms [[buffer(0)]], - bool frontFacing [[front_facing]]) -{ - - #if HAS_TEXTURE_TRANSFORM - float2 baseColorTexCoord = (uniforms.textureMatrices[textureIndexBaseColor] * float3(in.BaseColorTexCoord, 1)).xy; - float2 normalTexCoord = (uniforms.textureMatrices[textureIndexNormal] * float3(in.NormalTexCoord, 1)).xy; - float2 metallicRoughnessTexCoord = (uniforms.textureMatrices[textureIndexMetallicRoughness] * float3(in.MetallicRoughnessTexCoord, 1)).xy; - float2 occlusionTexCoord = (uniforms.textureMatrices[textureIndexOcclusion] * float3(in.OcclusionTexCoord, 1)).xy; - float2 emissiveTexCoord = (uniforms.textureMatrices[textureIndexEmissive] * float3(in.EmissiveTexCoord, 1)).xy; - #else - float2 baseColorTexCoord = in.BaseColorTexCoord; - float2 normalTexCoord = in.NormalTexCoord; - float2 metallicRoughnessTexCoord = in.MetallicRoughnessTexCoord; - float2 occlusionTexCoord = in.OcclusionTexCoord; - float2 emissiveTexCoord = in.EmissiveTexCoord; - #endif - - float3x3 tbn; - #if !HAS_TANGENTS - float3 pos_dx = dfdx(in.worldPosition); - float3 pos_dy = dfdy(in.worldPosition); - float3 tex_dx = dfdx(float3(normalTexCoord, 0)); - float3 tex_dy = dfdy(float3(normalTexCoord, 0)); - float3 t = (tex_dy.y * pos_dx - tex_dx.y * pos_dy) / (tex_dx.x * tex_dy.y - tex_dy.x * tex_dx.y); - - float3 ng(0); - #if HAS_NORMALS - ng = normalize(in.normal); - #else - ng = cross(pos_dx, pos_dy); - #endif - t = normalize(t - ng * dot(ng, t)); - float3 b = normalize(cross(ng, t)); - tbn = float3x3(t, b, ng); - #else - tbn = float3x3(in.tangent, in.bitangent, in.normal); - #endif - - float3 N(0, 0, 1); - #if HAS_NORMAL_MAP - N = normalTexture.sample(normalSampler, normalTexCoord).rgb; - N = normalize(tbn * ((2 * N - 1) * float3(uniforms.normalScale, uniforms.normalScale, 1))); - #else - N = tbn[2].xyz; - #endif - - #if USE_DOUBLE_SIDED_MATERIAL - N *= frontFacing ? 1 : -1; - #endif - - half perceptualRoughness = uniforms.metallicRoughnessValues.y; - half metallic = uniforms.metallicRoughnessValues.x; - - #if HAS_METALLIC_ROUGHNESS_MAP - half4 mrSample = metallicRoughnessTexture.sample(metallicRoughnessSampler, metallicRoughnessTexCoord); - perceptualRoughness = mrSample.g * perceptualRoughness; - metallic = mrSample.b * metallic; - #endif - - #if HAS_VERTEX_ROUGHNESS - perceptualRoughness = in.roughness; - #endif - - #if HAS_VERTEX_METALLIC - metallic = in.metalness; - #endif - - perceptualRoughness = clamp(perceptualRoughness, minRoughness, 1.0h); - metallic = saturate(metallic); - - half4 baseColor; - #if HAS_BASE_COLOR_MAP - baseColor = baseColorTexture.sample(baseColorSampler, baseColorTexCoord); - #if PREMULTIPLY_BASE_COLOR - baseColor.rgb *= baseColor.a; - #endif - baseColor *= half4(uniforms.baseColorFactor); - #else - baseColor = half4(uniforms.baseColorFactor); - #endif - - #if HAS_VERTEX_COLOR - baseColor *= half4(in.color); - #endif - - #if MATERIAL_IS_UNLIT - #if USE_ALPHA_TEST - if (baseColor.a < uniforms.alphaCutoff) { - discard_fragment(); - } - #endif - return baseColor; - #endif - - half3 f0(0.04); - half3 diffuseColor = mix(baseColor.rgb * (1 - f0), half3(0), metallic); - half3 specularColor = mix(f0, baseColor.rgb, metallic); - - half3 F0 = specularColor.rgb; - - float alphaRoughness = perceptualRoughness * perceptualRoughness; - - float3 V = normalize(uniforms.camera - in.worldPosition); - float NdotV = saturate(dot(N, V)); - - float3 reflection = normalize(reflect(V, N)) * float3(-1, -1, 1); - - half3 color(0); - - #if USE_PBR - color += half3(uniforms.ambientLight.color.rgb * uniforms.ambientLight.intensity) * diffuseColor; - - for (int i = 0; i < MAX_LIGHTS; ++i) { - Light light = uniforms.lights[i]; - - float3 L = normalize((light.position.w == 0) ? -light.position.xyz : (light.position.xyz - in.worldPosition)); - float3 H = normalize(L + V); - - float NdotL = saturate(dot(N, L)); - float NdotH = saturate(dot(N, H)); - float VdotH = saturate(dot(V, H)); - - half3 F = SchlickFresnel(F0, VdotH); - float G = SmithGeometric(NdotL, NdotV, alphaRoughness); - float D = TrowbridgeReitzNDF(NdotH, alphaRoughness); - - half3 diffuseContrib(0); - half3 specContrib(0); - if (NdotL > 0) { - diffuseContrib = NdotL * LambertDiffuse(diffuseColor); - specContrib = NdotL * D * F * G / (4.0 * NdotL * NdotV); - } - - half lightDist = length(light.position.xyz - in.worldPosition); - half attenNum = (light.range > 0) ? saturate(1.0 - powr(lightDist / light.range, 4)) : 1; - half atten = (light.position.w == 0) ? 1 : attenNum / powr(lightDist, 2); - - float relativeSpotAngle = acos(dot(-L, normalize(light.spotDirection.xyz))); - float spotAttenParam = 1 - clamp((relativeSpotAngle - light.innerConeAngle) / max(0.001, light.outerConeAngle - light.innerConeAngle), 0.0, 1.0); - float spotAtten = spotAttenParam * spotAttenParam * (3 - 2 * spotAttenParam); - atten *= spotAtten; - - color += half3(light.color.rgb * light.intensity) * atten * (diffuseContrib + specContrib); - } - #endif - -// baseColor = baseColorTexture.sample(baseColorSampler, baseColorTexCoord); - - half3 diffuseLight1 = half3(0.5,0.5,0.5); - diffuseLight1 *= uniforms.envIntensity; - half3 specularLight1(0.5); - specularLight1 *= uniforms.envIntensity; - half3 iblDiffuse1 = diffuseLight1 * diffuseColor; - half3 iblSpecular1 = specularLight1;// * ((specularColor * brdf.x) + brdf.y); - half3 iblColor1 = iblDiffuse1 + iblSpecular1; - color += iblColor1; - color = baseColor.rgb * NdotV; - - - - - return half4(color, baseColor.a); - - - #if USE_IBL - constexpr sampler cubeSampler(coord::normalized, filter::linear, mip_filter::linear); - float mipCount = SPECULAR_ENV_MIP_LEVELS; - float lod = perceptualRoughness * (mipCount - 1); - half2 brdf = brdfLUT.sample(cubeSampler, float2(NdotV, perceptualRoughness)).xy; - half3 diffuseLight = diffuseEnvTexture.sample(cubeSampler, N).rgb; - diffuseLight *= uniforms.envIntensity; - - half3 specularLight(0); - if (mipCount > 1) { - specularLight = specularEnvTexture.sample(cubeSampler, reflection, level(lod)).rgb; - } else { - specularLight = specularEnvTexture.sample(cubeSampler, reflection).rgb; - } - specularLight *= uniforms.envIntensity; - - half3 iblDiffuse = diffuseLight * diffuseColor; - half3 iblSpecular = specularLight * ((specularColor * brdf.x) + brdf.y); - - half3 iblColor = iblDiffuse + iblSpecular; - - color += iblColor; - #endif - - - #if HAS_OCCLUSION_MAP - half ao = occlusionTexture.sample(occlusionSampler, occlusionTexCoord).r; - color = mix(color, color * ao, half(uniforms.occlusionStrength)); - #endif - - #if HAS_EMISSIVE_MAP - half3 emissive = emissiveTexture.sample(emissiveSampler, emissiveTexCoord).rgb; - color += emissive * half3(uniforms.emissiveFactor); - #else - color += half3(uniforms.emissiveFactor); - #endif - - #if USE_ALPHA_TEST - if (baseColor.a < uniforms.alphaCutoff) { - discard_fragment(); - } - #endif - - return half4(color, baseColor.a); -} diff --git a/platform/darwin/src/gltf/gltfkit/shaders/pbr.txt b/platform/darwin/src/gltf/gltfkit/shaders/pbr.txt deleted file mode 100644 index ad5ae9409c17..000000000000 --- a/platform/darwin/src/gltf/gltfkit/shaders/pbr.txt +++ /dev/null @@ -1,463 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#include -using namespace metal; - -constant half minRoughness = 0.04; - -constant int textureIndexBaseColor = 0; -constant int textureIndexNormal = 1; -constant int textureIndexMetallicRoughness = 2; -constant int textureIndexOcclusion = 3; -constant int textureIndexEmissive = 4; -constant int textureIndexDiffuseEnvironment = 5; -constant int textureIndexSpecularEnvironment = 6; -constant int textureIndexBRDFLookup = 7; - -/*%begin_replace_decls%*/ -#define USE_PBR 1 -#define USE_IBL 1 -#define USE_ALPHA_TEST 0 -#define USE_VERTEX_SKINNING 1 -#define USE_EXTENDED_VERTEX_SKINNING 1 -#define USE_DOUBLE_SIDED_MATERIAL 1 -#define HAS_TEXCOORD_0 1 -#define HAS_TEXCOORD_1 1 -#define HAS_VERTEX_COLOR 1 -#define HAS_VERTEX_ROUGHNESS 1 -#define HAS_VERTEX_METALLIC 1 -#define HAS_NORMALS 1 -#define HAS_TANGENTS 1 -#define HAS_BASE_COLOR_MAP 1 -#define HAS_NORMAL_MAP 1 -#define HAS_METALLIC_ROUGHNESS_MAP 1 -#define HAS_OCCLUSION_MAP 1 -#define HAS_EMISSIVE_MAP 1 -#define HAS_TEXTURE_TRANSFORM 1 -#define MATERIAL_IS_UNLIT 0 -#define PREMULTIPLY_BASE_COLOR 1 -#define SPECULAR_ENV_MIP_LEVELS 6 -#define MAX_LIGHTS 3 -#define MAX_MATERIAL_TEXTURES 5 - -#define BaseColorTexCoord texCoord0 -#define NormalTexCoord texCoord0 -#define MetallicRoughnessTexCoord texCoord0 -#define EmissiveTexCoord texCoord0 -#define OcclusionTexCoord texCoord0 - -struct VertexIn { - float3 position [[attribute(0)]]; - float3 normal [[attribute(1)]]; - float4 tangent [[attribute(2)]]; - float2 texCoord0 [[attribute(3)]]; - float2 texCoord1 [[attribute(4)]]; - float4 color [[attribute(5)]]; - float4 weights0 [[attribute(6)]]; - float4 weights1 [[attribute(7)]]; - ushort4 joints0 [[attribute(8)]]; - ushort4 joints1 [[attribute(9)]]; - float roughness [[attribute(10)]]; - float metalness [[attribute(11)]]; -}; -/*%end_replace_decls%*/ - -struct VertexOut { - float4 position [[position]]; - float3 worldPosition; - float2 texCoord0; - float2 texCoord1; - float4 color; - float3 tangent; - float3 bitangent; - float3 normal; - float roughness; - float metalness; -}; - -struct VertexUniforms { - float4x4 modelMatrix; - float4x4 modelViewProjectionMatrix; - float4x4 normalMatrix; -}; - -struct Light { - float4 position; - float4 color; - float intensity; - float innerConeAngle; - float outerConeAngle; - float range; - float4 spotDirection; -}; - -struct FragmentUniforms { - float normalScale; - float3 emissiveFactor; - float occlusionStrength; - float2 metallicRoughnessValues; - float4 baseColorFactor; - float3 camera; - float alphaCutoff; - float envIntensity; - Light ambientLight; - Light lights[MAX_LIGHTS]; - float3x3 textureMatrices[MAX_MATERIAL_TEXTURES]; -}; - -vertex VertexOut vertex_main(VertexIn in [[stage_in]], - constant VertexUniforms &uniforms [[buffer(16)]] -#if USE_VERTEX_SKINNING - , constant float4x4 *jointMatrices [[buffer(17)]] -#endif -) -{ - VertexOut out = { 0 }; - - float4x4 normalMatrix = uniforms.normalMatrix; - - #if USE_VERTEX_SKINNING - ushort4 jointIndices = ushort4(in.joints0); - float4 jointWeights = float4(in.weights0); - - float4x4 skinMatrix = jointWeights[0] * jointMatrices[jointIndices[0]] + - jointWeights[1] * jointMatrices[jointIndices[1]] + - jointWeights[2] * jointMatrices[jointIndices[2]] + - jointWeights[3] * jointMatrices[jointIndices[3]]; - - #if USE_EXTENDED_VERTEX_SKINNING - jointIndices = ushort4(in.joints1); - jointWeights = float4(in.weights1); - - skinMatrix += jointWeights[0] * jointMatrices[jointIndices[0]] + - jointWeights[1] * jointMatrices[jointIndices[1]] + - jointWeights[2] * jointMatrices[jointIndices[2]] + - jointWeights[3] * jointMatrices[jointIndices[3]]; - #endif - - float4 skinnedPosition = skinMatrix * float4(in.position.xyz, 1); - normalMatrix = normalMatrix * skinMatrix; - #else - float4 skinnedPosition = float4(in.position.xyz, 1); - #endif - - float4 position = uniforms.modelMatrix * skinnedPosition; - out.worldPosition = position.xyz / position.w; - - out.position = uniforms.modelViewProjectionMatrix * skinnedPosition; - - #if HAS_NORMALS - #if HAS_TANGENTS - float3 normalW = normalize(float3(normalMatrix * float4(in.normal.xyz, 0.0))); - float3 tangentW = normalize(float3(normalMatrix * float4(in.tangent.xyz, 0.0))); - float3 bitangentW = cross(normalW, tangentW) * in.tangent.w; - out.tangent = tangentW; - out.bitangent = bitangentW; - out.normal = normalW; - #else - out.normal = normalize(float3(normalMatrix * float4(in.normal.xyz, 0.0))); - #endif - #endif - - #if HAS_VERTEX_COLOR - #if VERTEX_COLOR_IS_RGB - out.color = float4(in.color, 1); - #else - out.color = in.color; - #endif - #endif - - #if HAS_VERTEX_ROUGHNESS - out.roughness = in.roughness; - #endif - - #if HAS_VERTEX_METALLIC - out.metalness = in.metalness; - #endif - - #if HAS_TEXCOORD_0 - out.texCoord0 = in.texCoord0; - #endif - - #if HAS_TEXCOORD_1 - out.texCoord1 = in.texCoord1; - #endif - - return out; -} - -static half3 LambertDiffuse(half3 baseColor) -{ - return baseColor / M_PI_F; -} - -static half3 SchlickFresnel(half3 F0, float LdotH) -{ - return F0 + (1 - F0) * pow(1.0 - LdotH, 5.0); -} - -static float SmithGeometric(float NdotL, float NdotV, float roughness) -{ - float k = roughness * 0.5; - float Gl = NdotL / ((NdotL * (1 - k)) + k); - float Gv = NdotV / ((NdotV * (1 - k)) + k); - return Gl * Gv; -} - -static float TrowbridgeReitzNDF(float NdotH, float roughness) -{ - float roughnessSq = roughness * roughness; - float f = NdotH * (NdotH * roughnessSq - NdotH) + 1; - return roughnessSq / (M_PI_F * f * f); -} - -fragment half4 fragment_main(VertexOut in [[stage_in]], -#if HAS_BASE_COLOR_MAP - texture2d baseColorTexture [[texture(textureIndexBaseColor)]], - sampler baseColorSampler [[sampler(textureIndexBaseColor)]], -#endif -#if HAS_NORMAL_MAP - texture2d normalTexture [[texture(textureIndexNormal)]], - sampler normalSampler [[sampler(textureIndexNormal)]], -#endif -#if HAS_EMISSIVE_MAP - texture2d emissiveTexture [[texture(textureIndexEmissive)]], - sampler emissiveSampler [[sampler(textureIndexEmissive)]], -#endif -#if HAS_METALLIC_ROUGHNESS_MAP - texture2d metallicRoughnessTexture [[texture(textureIndexMetallicRoughness)]], - sampler metallicRoughnessSampler [[sampler(textureIndexMetallicRoughness)]], -#endif -#if HAS_OCCLUSION_MAP - texture2d occlusionTexture [[texture(textureIndexOcclusion)]], - sampler occlusionSampler [[sampler(textureIndexOcclusion)]], -#endif -#if USE_IBL - texturecube diffuseEnvTexture [[texture(textureIndexDiffuseEnvironment)]], - texturecube specularEnvTexture [[texture(textureIndexSpecularEnvironment)]], - texture2d brdfLUT [[texture(textureIndexBRDFLookup)]], -#endif - constant FragmentUniforms &uniforms [[buffer(0)]], - bool frontFacing [[front_facing]]) -{ - - #if HAS_TEXTURE_TRANSFORM - float2 baseColorTexCoord = (uniforms.textureMatrices[textureIndexBaseColor] * float3(in.BaseColorTexCoord, 1)).xy; - float2 normalTexCoord = (uniforms.textureMatrices[textureIndexNormal] * float3(in.NormalTexCoord, 1)).xy; - float2 metallicRoughnessTexCoord = (uniforms.textureMatrices[textureIndexMetallicRoughness] * float3(in.MetallicRoughnessTexCoord, 1)).xy; - float2 occlusionTexCoord = (uniforms.textureMatrices[textureIndexOcclusion] * float3(in.OcclusionTexCoord, 1)).xy; - float2 emissiveTexCoord = (uniforms.textureMatrices[textureIndexEmissive] * float3(in.EmissiveTexCoord, 1)).xy; - #else - float2 baseColorTexCoord = in.BaseColorTexCoord; - float2 normalTexCoord = in.NormalTexCoord; - float2 metallicRoughnessTexCoord = in.MetallicRoughnessTexCoord; - float2 occlusionTexCoord = in.OcclusionTexCoord; - float2 emissiveTexCoord = in.EmissiveTexCoord; - #endif - - float3x3 tbn; - #if !HAS_TANGENTS - float3 pos_dx = dfdx(in.worldPosition); - float3 pos_dy = dfdy(in.worldPosition); - float3 tex_dx = dfdx(float3(normalTexCoord, 0)); - float3 tex_dy = dfdy(float3(normalTexCoord, 0)); - float3 t = (tex_dy.y * pos_dx - tex_dx.y * pos_dy) / (tex_dx.x * tex_dy.y - tex_dy.x * tex_dx.y); - - float3 ng(0); - #if HAS_NORMALS - ng = normalize(in.normal); - #else - ng = cross(pos_dx, pos_dy); - #endif - t = normalize(t - ng * dot(ng, t)); - float3 b = normalize(cross(ng, t)); - tbn = float3x3(t, b, ng); - #else - tbn = float3x3(in.tangent, in.bitangent, in.normal); - #endif - - float3 N(0, 0, 1); - #if HAS_NORMAL_MAP - N = normalTexture.sample(normalSampler, normalTexCoord).rgb; - N = normalize(tbn * ((2 * N - 1) * float3(uniforms.normalScale, uniforms.normalScale, 1))); - #else - N = tbn[2].xyz; - #endif - - #if USE_DOUBLE_SIDED_MATERIAL - N *= frontFacing ? 1 : -1; - #endif - - half perceptualRoughness = uniforms.metallicRoughnessValues.y; - half metallic = uniforms.metallicRoughnessValues.x; - - #if HAS_METALLIC_ROUGHNESS_MAP - half4 mrSample = metallicRoughnessTexture.sample(metallicRoughnessSampler, metallicRoughnessTexCoord); - perceptualRoughness = mrSample.g * perceptualRoughness; - metallic = mrSample.b * metallic; - #endif - - #if HAS_VERTEX_ROUGHNESS - perceptualRoughness = in.roughness; - #endif - - #if HAS_VERTEX_METALLIC - metallic = in.metalness; - #endif - - perceptualRoughness = clamp(perceptualRoughness, minRoughness, 1.0h); - metallic = saturate(metallic); - - half4 baseColor; - #if HAS_BASE_COLOR_MAP - baseColor = baseColorTexture.sample(baseColorSampler, baseColorTexCoord); - #if PREMULTIPLY_BASE_COLOR - baseColor.rgb *= baseColor.a; - #endif - baseColor *= half4(uniforms.baseColorFactor); - #else - baseColor = half4(uniforms.baseColorFactor); - #endif - - #if HAS_VERTEX_COLOR - baseColor *= half4(in.color); - #endif - - #if MATERIAL_IS_UNLIT - #if USE_ALPHA_TEST - if (baseColor.a < uniforms.alphaCutoff) { - discard_fragment(); - } - #endif - return baseColor; - #endif - - half3 f0(0.04); - half3 diffuseColor = mix(baseColor.rgb * (1 - f0), half3(0), metallic); - half3 specularColor = mix(f0, baseColor.rgb, metallic); - - half3 F0 = specularColor.rgb; - - float alphaRoughness = perceptualRoughness * perceptualRoughness; - - float3 V = normalize(uniforms.camera - in.worldPosition); - float NdotV = saturate(dot(N, V)); - - float3 reflection = normalize(reflect(V, N)) * float3(-1, -1, 1); - - half3 color(0); - - #if USE_PBR - color += half3(uniforms.ambientLight.color.rgb * uniforms.ambientLight.intensity) * diffuseColor; - - for (int i = 0; i < MAX_LIGHTS; ++i) { - Light light = uniforms.lights[i]; - - float3 L = normalize((light.position.w == 0) ? -light.position.xyz : (light.position.xyz - in.worldPosition)); - float3 H = normalize(L + V); - - float NdotL = saturate(dot(N, L)); - float NdotH = saturate(dot(N, H)); - float VdotH = saturate(dot(V, H)); - - half3 F = SchlickFresnel(F0, VdotH); - float G = SmithGeometric(NdotL, NdotV, alphaRoughness); - float D = TrowbridgeReitzNDF(NdotH, alphaRoughness); - - half3 diffuseContrib(0); - half3 specContrib(0); - if (NdotL > 0) { - diffuseContrib = NdotL * LambertDiffuse(diffuseColor); - specContrib = NdotL * D * F * G / (4.0 * NdotL * NdotV); - } - - half lightDist = length(light.position.xyz - in.worldPosition); - half attenNum = (light.range > 0) ? saturate(1.0 - powr(lightDist / light.range, 4)) : 1; - half atten = (light.position.w == 0) ? 1 : attenNum / powr(lightDist, 2); - - float relativeSpotAngle = acos(dot(-L, normalize(light.spotDirection.xyz))); - float spotAttenParam = 1 - clamp((relativeSpotAngle - light.innerConeAngle) / max(0.001, light.outerConeAngle - light.innerConeAngle), 0.0, 1.0); - float spotAtten = spotAttenParam * spotAttenParam * (3 - 2 * spotAttenParam); - atten *= spotAtten; - - color += half3(light.color.rgb * light.intensity) * atten * (diffuseContrib + specContrib); - } - #endif - -// baseColor = baseColorTexture.sample(baseColorSampler, baseColorTexCoord); - - half3 diffuseLight1 = half3(0.5,0.5,0.5); - diffuseLight1 *= uniforms.envIntensity; - half3 specularLight1(0.5); - specularLight1 *= uniforms.envIntensity; - half3 iblDiffuse1 = diffuseLight1 * diffuseColor; - half3 iblSpecular1 = specularLight1;// * ((specularColor * brdf.x) + brdf.y); - half3 iblColor1 = iblDiffuse1 + iblSpecular1; - color += iblColor1; - color = baseColor.rgb * NdotV; - - - - - return half4(color, baseColor.a); - - - #if USE_IBL - constexpr sampler cubeSampler(coord::normalized, filter::linear, mip_filter::linear); - float mipCount = SPECULAR_ENV_MIP_LEVELS; - float lod = perceptualRoughness * (mipCount - 1); - half2 brdf = brdfLUT.sample(cubeSampler, float2(NdotV, perceptualRoughness)).xy; - half3 diffuseLight = diffuseEnvTexture.sample(cubeSampler, N).rgb; - diffuseLight *= uniforms.envIntensity; - - half3 specularLight(0); - if (mipCount > 1) { - specularLight = specularEnvTexture.sample(cubeSampler, reflection, level(lod)).rgb; - } else { - specularLight = specularEnvTexture.sample(cubeSampler, reflection).rgb; - } - specularLight *= uniforms.envIntensity; - - half3 iblDiffuse = diffuseLight * diffuseColor; - half3 iblSpecular = specularLight * ((specularColor * brdf.x) + brdf.y); - - half3 iblColor = iblDiffuse + iblSpecular; - - color += iblColor; - #endif - - - #if HAS_OCCLUSION_MAP - half ao = occlusionTexture.sample(occlusionSampler, occlusionTexCoord).r; - color = mix(color, color * ao, half(uniforms.occlusionStrength)); - #endif - - #if HAS_EMISSIVE_MAP - half3 emissive = emissiveTexture.sample(emissiveSampler, emissiveTexCoord).rgb; - color += emissive * half3(uniforms.emissiveFactor); - #else - color += half3(uniforms.emissiveFactor); - #endif - - #if USE_ALPHA_TEST - if (baseColor.a < uniforms.alphaCutoff) { - discard_fragment(); - } - #endif - - return half4(color, baseColor.a); -} diff --git a/platform/ios/BUILD.bazel b/platform/ios/BUILD.bazel index e2d15d7eb226..5adfca264247 100644 --- a/platform/ios/BUILD.bazel +++ b/platform/ios/BUILD.bazel @@ -95,7 +95,6 @@ public_hdrs = [ ":mln_defines", ":ios_public_hdrs", ":ios_sdk_hdrs", - "//platform/darwin:darwin_gltf_hdrs", "//platform/darwin:darwin_objc_hdrs", "//platform/darwin:generated_style_public_hdrs", ] From 24636500a1e1352f7fd60c59a134c682be3d1ecd Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 2 Jul 2025 14:33:00 +0300 Subject: [PATCH 102/221] Revert "Reduce duplicate GPU buffer uploads (#3577)" This reverts commit 779b89346816b804af78eeae88933ca130858328. --- include/mbgl/mtl/render_pass.hpp | 5 ----- src/mbgl/mtl/buffer_resource.cpp | 11 ++--------- src/mbgl/mtl/drawable.cpp | 2 +- src/mbgl/mtl/render_pass.cpp | 9 --------- 4 files changed, 3 insertions(+), 24 deletions(-) diff --git a/include/mbgl/mtl/render_pass.hpp b/include/mbgl/mtl/render_pass.hpp index c7a94821b183..a86788fcd4b7 100644 --- a/include/mbgl/mtl/render_pass.hpp +++ b/include/mbgl/mtl/render_pass.hpp @@ -41,9 +41,6 @@ class RenderPass final : public gfx::RenderPass { /// Set the sampler for a texture binding void setFragmentSamplerState(const MTLSamplerStatePtr&, int32_t location); - /// Set the render pipeline state - void setRenderPipelineState(const MTLRenderPipelineStatePtr&); - void endEncoding(); /// Resets the states and bindings of the render pass to deal @@ -72,8 +69,6 @@ class RenderPass final : public gfx::RenderPass { mtl::CommandEncoder& commandEncoder; MTLRenderCommandEncoderPtr encoder; MTLDepthStencilStatePtr currentDepthStencilState; - MTLRenderPipelineStatePtr currentPipelineState; - int32_t currentStencilReferenceValue = 0; std::vector> debugGroups; diff --git a/src/mbgl/mtl/buffer_resource.cpp b/src/mbgl/mtl/buffer_resource.cpp index ab2f75174529..a2d2db61eb3f 100644 --- a/src/mbgl/mtl/buffer_resource.cpp +++ b/src/mbgl/mtl/buffer_resource.cpp @@ -103,22 +103,15 @@ void BufferResource::update(const void* newData, std::size_t updateSize, std::si // Until we can be sure that the buffer is not still in use to render the // previous frame, replace it with a new buffer instead of updating it. + auto& device = context.getBackend().getDevice(); const uint8_t* newBufferSource = nullptr; std::unique_ptr tempBuffer; - const bool updateIsEntireBuffer = (offset == 0 && updateSize == size); - - // If the entire buffer is being updated, make sure it's changed - if (updateIsEntireBuffer) { - if (memcmp(buffer->contents(), newData, updateSize) == 0) { - return; - } - } - auto& device = context.getBackend().getDevice(); // `[MTLBuffer contents]` may involve memory mapping and/or synchronization. If the entire // buffer is being replaced, avoid accessing the old one by creating the new buffer directly // from the given data. If it's just being updated, apply the update to a local buffer to // avoid needing to access the new buffer. + const bool updateIsEntireBuffer = (offset == 0 && updateSize == size); if (updateIsEntireBuffer) { newBufferSource = static_cast(newData); } else { diff --git a/src/mbgl/mtl/drawable.cpp b/src/mbgl/mtl/drawable.cpp index f41d84d5c8c2..0472ed9aff53 100644 --- a/src/mbgl/mtl/drawable.cpp +++ b/src/mbgl/mtl/drawable.cpp @@ -223,7 +223,7 @@ void Drawable::draw(PaintParameters& parameters) const { mbgl::util::hash(getColorMode().hash(), impl->vertexDescHash)); } if (impl->pipelineState) { - renderPass.setRenderPipelineState(impl->pipelineState); + encoder->setRenderPipelineState(impl->pipelineState.get()); } else { assert(!"Failed to create render pipeline state"); return; diff --git a/src/mbgl/mtl/render_pass.cpp b/src/mbgl/mtl/render_pass.cpp index d053016a9356..4c8ac237a746 100644 --- a/src/mbgl/mtl/render_pass.cpp +++ b/src/mbgl/mtl/render_pass.cpp @@ -66,7 +66,6 @@ void RenderPass::endEncoding() { } void RenderPass::resetState() { - currentPipelineState.reset(); currentDepthStencilState.reset(); currentStencilReferenceValue = 0; for (int i = 0; i < maxBinds; ++i) { @@ -194,14 +193,6 @@ void RenderPass::setFragmentSamplerState(const MTLSamplerStatePtr& state, int32_ } } -/// Set the render pipeline state -void RenderPass::setRenderPipelineState(const MTLRenderPipelineStatePtr& pipelineState) { - if (pipelineState != currentPipelineState) { - currentPipelineState = pipelineState; - encoder->setRenderPipelineState(currentPipelineState.get()); - } -} - void RenderPass::setCullMode(const MTL::CullMode mode) { if (mode != currentCullMode) { encoder->setCullMode(mode); From 8d68df22f36782ba5b932e5bd4c9b3bdb13020c0 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 2 Jul 2025 14:33:46 +0300 Subject: [PATCH 103/221] make ios 6.15.3 release --- platform/ios/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/VERSION b/platform/ios/VERSION index 0bffdbe7afb7..93cf8e367b18 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.15.2 +6.15.3 From fff5a2b3604ac7d5907ff134e9eadee88de9d39d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Wed, 2 Jul 2025 12:46:39 -0400 Subject: [PATCH 104/221] Added near clip matrix --- platform/darwin/src/MLNPluginLayer.h | 1 + platform/ios/src/MLNMapView.mm | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/platform/darwin/src/MLNPluginLayer.h b/platform/darwin/src/MLNPluginLayer.h index b188e4fb2376..f9d3bef25229 100644 --- a/platform/darwin/src/MLNPluginLayer.h +++ b/platform/darwin/src/MLNPluginLayer.h @@ -80,6 +80,7 @@ typedef struct MLNPluginLayerDrawingContext { CGFloat fieldOfView; /// A 4×4 matrix representing the map view’s current projection state. MLNMatrix4 projectionMatrix; + MLNMatrix4 nearClippedProjMatrix; } MLNPluginLayerDrawingContext; MLN_EXPORT diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 0aeffd84e1ce..2fdca15b788a 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -7831,9 +7831,14 @@ -(void)addPluginLayerType:(Class)pluginLayerClass { drawingContext.direction = mbgl::util::rad2deg(-state.getBearing()); drawingContext.pitch = state.getPitch(); drawingContext.fieldOfView = state.getFieldOfView(); - mbgl::mat4 projMatrix; - state.getProjMatrix(projMatrix); - drawingContext.projectionMatrix = MLNMatrix4Make(projMatrix); +// mbgl::mat4 projMatrix; +// state.getProjMatrix(projMatrix); +// drawingContext.projectionMatrix = MLNMatrix4Make(projMatrix); + drawingContext.projectionMatrix = MLNMatrix4Make(paintParameters.transformParams.projMatrix); + +// mbgl::mat4 nearClippedProjMatrix; +// state.getProjMatrix(nearClippedProjMatrix, static_cast(0.1 * state.getCameraToCenterDistance())); + drawingContext.nearClippedProjMatrix = MLNMatrix4Make(paintParameters.transformParams.nearClippedProjMatrix); //NSLog(@"Rendering"); From 5aa01ea0010d5a70a7db3a170c6c4aabad136af4 Mon Sep 17 00:00:00 2001 From: Abdulelah Hajjar Date: Thu, 3 Jul 2025 10:49:23 +0300 Subject: [PATCH 105/221] =?UTF-8?q?feat(annotations):=20Support=20re-creat?= =?UTF-8?q?ing=20the=20user=E2=80=99s=20location=20annotation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Abdulelah Hajjar --- platform/ios/VERSION | 2 +- .../MLNFaux3DUserLocationAnnotationView.mm | 13 ++++++ platform/ios/src/MLNMapView.h | 6 +++ platform/ios/src/MLNMapView.mm | 46 +++++++++++-------- 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/platform/ios/VERSION b/platform/ios/VERSION index 93cf8e367b18..cece3b9b05c3 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.15.3 +6.15.4 diff --git a/platform/ios/src/MLNFaux3DUserLocationAnnotationView.mm b/platform/ios/src/MLNFaux3DUserLocationAnnotationView.mm index 72691ed2688d..65fafe34f3ae 100644 --- a/platform/ios/src/MLNFaux3DUserLocationAnnotationView.mm +++ b/platform/ios/src/MLNFaux3DUserLocationAnnotationView.mm @@ -259,6 +259,11 @@ - (void)drawPuck [self.layer addSublayer:_puckArrow]; } + else if (!CGColorEqualToColor(_puckArrow.fillColor, [arrowColor CGColor])) + { + _puckArrow.fillColor = [arrowColor CGColor]; + _puckArrow.strokeColor = [arrowColor CGColor]; + } if (self.userLocation.location.course >= 0) { _puckArrow.affineTransform = CGAffineTransformRotate(CGAffineTransformIdentity, -MLNRadiansFromDegrees(self.mapView.direction - self.userLocation.location.course)); @@ -461,6 +466,10 @@ - (void)drawDot [self.layer addSublayer:_haloLayer]; } + else if (!CGColorEqualToColor(_haloLayer.backgroundColor, [haloColor CGColor])) + { + _haloLayer.backgroundColor = [haloColor CGColor]; + } // background dot (white with black shadow) // @@ -513,6 +522,10 @@ - (void)drawDot [self.layer addSublayer:_dotLayer]; } + else if (!CGColorEqualToColor(_dotLayer.backgroundColor, [puckBackgroundColor CGColor])) + { + _dotLayer.backgroundColor = [puckBackgroundColor CGColor]; + } if (_puckModeActivated) { diff --git a/platform/ios/src/MLNMapView.h b/platform/ios/src/MLNMapView.h index c07053aee287..a8e133381ee6 100644 --- a/platform/ios/src/MLNMapView.h +++ b/platform/ios/src/MLNMapView.h @@ -678,6 +678,12 @@ MLN_EXPORT */ - (void)updateUserLocationAnnotationViewAnimatedWithDuration:(NSTimeInterval)duration; +/** + Creates or updates the user location annotation view. This method calls the `mapView:viewForAnnotation:` + delegate method to obtain a custom view. If no custom view is provided, it defaults to a native one. + */ +- (void)createUserLocationAnnotationView; + /** A Boolean value indicating whether the user location annotation may display a permanent heading indicator. diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 0aeffd84e1ce..2e015a7a2b36 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -6109,6 +6109,32 @@ - (NSString *)accuracyDescriptionString { return dictionary[@"MLNAccuracyAuthorizationDescription"]; } +- (void)createUserLocationAnnotationView { + MLNUserLocationAnnotationView *userLocationAnnotationView; + + if ([self.delegate respondsToSelector:@selector(mapView:viewForAnnotation:)]) + { + userLocationAnnotationView = (MLNUserLocationAnnotationView *)[self.delegate mapView:self viewForAnnotation:self.userLocation]; + if (userLocationAnnotationView && ! [userLocationAnnotationView isKindOfClass:MLNUserLocationAnnotationView.class]) + { + [NSException raise:MLNUserLocationAnnotationTypeException + format:@"User location annotation view must be a kind of MLNUserLocationAnnotationView. %@", userLocationAnnotationView.debugDescription]; + } + } + + if (self.userLocationAnnotationView) { + [self.userLocationAnnotationView removeFromSuperview]; + } + self.userLocationAnnotationView = userLocationAnnotationView ?: self.useLocationIndicatorLayer ? [[MLNLocationIndicatorUserLocationAnnotationView alloc] init] : [[MLNFaux3DUserLocationAnnotationView alloc] init]; + self.userLocationAnnotationView.mapView = self; + self.userLocationAnnotationView.userLocation = self.userLocation; + + self.userLocationAnnotationView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | + UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin); + + [self.userLocationAnnotationView update]; +} + - (void)setShowsUserLocation:(BOOL)showsUserLocation { MLNLogDebug(@"Setting showsUserLocation: %@", MLNStringFromBOOL(showsUserLocation)); @@ -6124,25 +6150,7 @@ - (void)setShowsUserLocation:(BOOL)showsUserLocation } self.userLocation = [[MLNUserLocation alloc] initWithMapView:self]; - - MLNUserLocationAnnotationView *userLocationAnnotationView; - - if ([self.delegate respondsToSelector:@selector(mapView:viewForAnnotation:)]) - { - userLocationAnnotationView = (MLNUserLocationAnnotationView *)[self.delegate mapView:self viewForAnnotation:self.userLocation]; - if (userLocationAnnotationView && ! [userLocationAnnotationView isKindOfClass:MLNUserLocationAnnotationView.class]) - { - [NSException raise:MLNUserLocationAnnotationTypeException - format:@"User location annotation view must be a kind of MLNUserLocationAnnotationView. %@", userLocationAnnotationView.debugDescription]; - } - } - - self.userLocationAnnotationView = userLocationAnnotationView ?: self.useLocationIndicatorLayer ? [[MLNLocationIndicatorUserLocationAnnotationView alloc] init] : [[MLNFaux3DUserLocationAnnotationView alloc] init]; - self.userLocationAnnotationView.mapView = self; - self.userLocationAnnotationView.userLocation = self.userLocation; - - self.userLocationAnnotationView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | - UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin); + [self createUserLocationAnnotationView]; [self validateLocationServices]; } From 40396944bffa7dcc2bc655a59c251c93e810fb13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Mon, 7 Jul 2025 01:50:21 -0400 Subject: [PATCH 106/221] Very prelim --- bazel/core.bzl | 2 + platform/darwin/src/MLNPluginLayer.h | 13 ++ platform/darwin/src/MLNPluginLayer.mm | 12 ++ platform/ios/src/MLNMapView.mm | 45 ++++++ src/mbgl/plugin/plugin_layer.hpp | 6 +- src/mbgl/plugin/plugin_layer_factory.cpp | 14 +- src/mbgl/plugin/plugin_layer_factory.hpp | 3 + src/mbgl/plugin/plugin_layer_impl.hpp | 7 + src/mbgl/plugin/raw_bucket.cpp | 185 ++++++++++++++++++++++ src/mbgl/plugin/raw_bucket.hpp | 113 +++++++++++++ src/mbgl/renderer/render_orchestrator.cpp | 7 + src/mbgl/tile/geometry_tile_worker.cpp | 10 +- 12 files changed, 410 insertions(+), 7 deletions(-) create mode 100644 src/mbgl/plugin/raw_bucket.cpp create mode 100644 src/mbgl/plugin/raw_bucket.hpp diff --git a/bazel/core.bzl b/bazel/core.bzl index b27bbd8d925b..efc259dbed87 100644 --- a/bazel/core.bzl +++ b/bazel/core.bzl @@ -4,6 +4,7 @@ MLN_LAYER_PLUGIN_HEADERS = [ "src/mbgl/plugin/plugin_layer_impl.hpp", "src/mbgl/plugin/plugin_layer_render.hpp", "src/mbgl/plugin/plugin_layer_properties.hpp", + "src/mbgl/plugin/raw_bucket.hpp", ] MLN_LAYER_PLUGIN_SOURCE = [ @@ -12,6 +13,7 @@ MLN_LAYER_PLUGIN_SOURCE = [ "src/mbgl/plugin/plugin_layer_impl.cpp", "src/mbgl/plugin/plugin_layer_render.cpp", "src/mbgl/plugin/plugin_layer_properties.cpp", + "src/mbgl/plugin/raw_bucket.cpp", ] MLN_PUBLIC_GENERATED_STYLE_HEADERS = [ diff --git a/platform/darwin/src/MLNPluginLayer.h b/platform/darwin/src/MLNPluginLayer.h index b188e4fb2376..3b87995e1862 100644 --- a/platform/darwin/src/MLNPluginLayer.h +++ b/platform/darwin/src/MLNPluginLayer.h @@ -42,6 +42,13 @@ MLN_EXPORT @end +@interface MLNPluginLayerTileFeature : NSObject + +@property NSDictionary *featureProperties; +@property NSArray *featureCoordinates; + +@end + typedef enum { MLNPluginLayerTileKindGeometry, MLNPluginLayerTileKindRaster, @@ -55,6 +62,9 @@ MLN_EXPORT @property (copy) NSString *layerID; @property BOOL requiresPass3D; +//! Set this to true if this layer can support reading features from the tiles +@property BOOL supportsReadingTileFeatures; + //! This is a list of layer properties that this layer supports. @property (copy) NSArray *layerProperties; @@ -101,6 +111,9 @@ MLN_EXPORT /// dynamic properties are updated - (void)onUpdateLayerProperties:(NSDictionary *)layerProperties; +/// Called when a feature is loaded from the tile +- (void)onFeatureLoaded:(MLNPluginLayerTileFeature *)tileFeature; + /// Added to a map view - (void)didMoveToMapView:(MLNMapView *)mapView; diff --git a/platform/darwin/src/MLNPluginLayer.mm b/platform/darwin/src/MLNPluginLayer.mm index cff0044d05ac..712552d9f39d 100644 --- a/platform/darwin/src/MLNPluginLayer.mm +++ b/platform/darwin/src/MLNPluginLayer.mm @@ -1,5 +1,9 @@ #import "MLNPluginLayer.h" +@implementation MLNPluginLayerTileFeature + +@end + @implementation MLNPluginLayerProperty +(MLNPluginLayerProperty *)propertyWithName:(NSString *)propertyName @@ -65,12 +69,20 @@ - (void)onUpdateLayer:(MLNPluginLayerDrawingContext)drawingContext { -(void)onUpdateLayerProperties:(NSDictionary *)layerProperties { // Base class does nothing } + +// If the layer properties indicate that this layer has a the ability to intercept +// features, then this method will be called when a feature is loaded +- (void)onFeatureLoaded:(MLNPluginLayerTileFeature *)tileFeature { + // Base class does nothing +} + /// Added to a map view - (void)didMoveToMapView:(MLNMapView *)mapView { // Base class does nothing } + @end diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 1337f0c6bd36..43b93c081e55 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -7675,6 +7676,10 @@ -(void)addPluginLayerType:(Class)pluginLayerClass { if (capabilities.requiresPass3D) { pass3D = mbgl::style::LayerTypeInfo::Pass3D::Required; } + + + tileKind = mbgl::style::LayerTypeInfo::TileKind::Geometry; + source = mbgl::style::LayerTypeInfo::Source::Required; auto factory = std::make_unique(layerType, source, @@ -7687,6 +7692,7 @@ -(void)addPluginLayerType:(Class)pluginLayerClass { __weak MLNMapView *weakMapView = self; Class layerClass = pluginLayerClass; + factory->_supportsRawBuckets = capabilities.supportsReadingTileFeatures; factory->setOnLayerCreatedEvent([layerClass, weakMapView, pluginLayerClass](mbgl::style::PluginLayer *pluginLayer) { //NSLog(@"Creating Plugin Layer: %@", layerClass); @@ -7782,6 +7788,45 @@ -(void)addPluginLayerType:(Class)pluginLayerClass { [weakPlugInLayer onUpdateLayerProperties:properties]; } }); + + // If this layer can read tile features, then setup that lambda + if (capabilities.supportsReadingTileFeatures) { + pluginLayerImpl->setFeatureLoadedFunction([weakPlugInLayer](const std::shared_ptr feature) { + + @autoreleasepool { + MLNPluginLayerTileFeature *tileFeature = [[MLNPluginLayerTileFeature alloc] init]; + + NSMutableDictionary *tileProperties = [NSMutableDictionary dictionary]; + for (auto p: feature->_featureProperties) { + NSString *key = [NSString stringWithUTF8String:p.first.c_str()]; + NSString *value = [NSString stringWithUTF8String:p.second.c_str()]; + [tileProperties setObject:value forKey:key]; + } + + tileFeature.featureProperties = [NSDictionary dictionaryWithDictionary:tileProperties]; + + NSMutableArray *featureCoordinates = [NSMutableArray array]; + for (auto & coordinateCollection: feature->_featureCoordinates) { + + for (auto & coordinate: coordinateCollection._coordinates) { + CLLocationCoordinate2D c = CLLocationCoordinate2DMake(coordinate._lat, coordinate._lon); + NSValue *value = [NSValue valueWithBytes:&c objCType:@encode(CLLocationCoordinate2D)]; + [featureCoordinates addObject:value]; + } + + } + // TODO: Need to figure out how we're going to handle multiple coordinate groups/etc + if ([featureCoordinates count] > 0) { + tileFeature.featureCoordinates = [NSArray arrayWithArray:featureCoordinates]; + } + + + [weakPlugInLayer onFeatureLoaded:tileFeature]; + + } + + }); + } }); diff --git a/src/mbgl/plugin/plugin_layer.hpp b/src/mbgl/plugin/plugin_layer.hpp index f8f95a4c4c70..7b5ae19f349b 100644 --- a/src/mbgl/plugin/plugin_layer.hpp +++ b/src/mbgl/plugin/plugin_layer.hpp @@ -6,8 +6,11 @@ namespace mbgl { +class RawBucketFeature; + namespace style { + class PluginLayer final : public Layer { public: PluginLayer(const std::string& layerID, @@ -28,7 +31,8 @@ class PluginLayer final : public Layer { using OnRenderLayer = std::function; using OnUpdateLayer = std::function; using OnUpdateLayerProperties = std::function; - + using OnFeatureLoaded = std::function feature)>; + void* _platformReference = nullptr; protected: diff --git a/src/mbgl/plugin/plugin_layer_factory.cpp b/src/mbgl/plugin/plugin_layer_factory.cpp index f33fb701f29f..4d68fad43fb3 100644 --- a/src/mbgl/plugin/plugin_layer_factory.cpp +++ b/src/mbgl/plugin/plugin_layer_factory.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -66,7 +67,7 @@ PluginLayerFactory::PluginLayerFactory(std::string& layerType, mbgl::style::LayerTypeInfo::TileKind tileKind) : _layerTypeInfo(getDefaultInfo()), _layerType(layerType) { - _layerTypeInfo.type = layerType.c_str(); + _layerTypeInfo.type = _layerType.c_str(); plugins::NonConstLayerTypeInfo* lti = (plugins::NonConstLayerTypeInfo*)&_layerTypeInfo; lti->source = (plugins::NonConstLayerTypeInfo::Source)((int)source); lti->pass3d = (plugins::NonConstLayerTypeInfo::Pass3D)((int)pass3D); @@ -149,10 +150,11 @@ std::unique_ptr PluginLayerFactory::createLayer(const std::string& } } - std::string source = "source"; + auto source = getSource(value); + std::string sourceStr = source.has_value() ? source.value() : "source"; auto tempResult = std::unique_ptr(new (std::nothrow) - style::PluginLayer(id, source, _layerTypeInfo, layerProperties + style::PluginLayer(id, sourceStr, _layerTypeInfo, layerProperties //,*customProperties )); @@ -172,8 +174,10 @@ std::unique_ptr PluginLayerFactory::createLayer(const std::string& std::unique_ptr PluginLayerFactory::createBucket( [[maybe_unused]] const BucketParameters& parameters, [[maybe_unused]] const std::vector>& layers) noexcept { - // Returning null for now. Not using buckets in plug-ins yet. - return nullptr; + if (_supportsRawBuckets) { + return std::make_unique(parameters, layers); + } + return nullptr; } std::unique_ptr PluginLayerFactory::createRenderLayer(Immutable impl) noexcept { diff --git a/src/mbgl/plugin/plugin_layer_factory.hpp b/src/mbgl/plugin/plugin_layer_factory.hpp index 0a976b37a9f1..d35c5ca8bc48 100644 --- a/src/mbgl/plugin/plugin_layer_factory.hpp +++ b/src/mbgl/plugin/plugin_layer_factory.hpp @@ -23,6 +23,9 @@ class PluginLayerFactory : public LayerFactory { mbgl::style::LayerTypeInfo::CrossTileIndex crossTileIndex, mbgl::style::LayerTypeInfo::TileKind tileKind); + // Set to false, but if the caller wants to support on features loaded, then set this to true + bool _supportsRawBuckets = false; + using OnLayerCreatedEvent = std::function; void setOnLayerCreatedEvent(OnLayerCreatedEvent onLayerCreated) { _onLayerCreated = onLayerCreated; } diff --git a/src/mbgl/plugin/plugin_layer_impl.hpp b/src/mbgl/plugin/plugin_layer_impl.hpp index 512cec427a33..6b58c42f8e7f 100644 --- a/src/mbgl/plugin/plugin_layer_impl.hpp +++ b/src/mbgl/plugin/plugin_layer_impl.hpp @@ -99,6 +99,10 @@ class PluginLayer::Impl : public Layer::Impl { _updateLayerPropertiesFunction = updateLayerPropertiesFunction; } + void setFeatureLoadedFunction(OnFeatureLoaded featureLoadedFunction) { + _featureLoadedFunction = featureLoadedFunction; + } + //! The property manager handles all of the custom properties for this layer type / instance PluginLayerPropertyManager _propertyManager; @@ -113,6 +117,9 @@ class PluginLayer::Impl : public Layer::Impl { //! Optional: Called when the layer properties change. The properties are passed as JSON for now OnUpdateLayerProperties _updateLayerPropertiesFunction; + //! Optional: Called when feature is loaded + OnFeatureLoaded _featureLoadedFunction; + private: LayerTypeInfo _layerTypeInfo; std::string _layerProperties; diff --git a/src/mbgl/plugin/raw_bucket.cpp b/src/mbgl/plugin/raw_bucket.cpp new file mode 100644 index 000000000000..9322cc4b3e8a --- /dev/null +++ b/src/mbgl/plugin/raw_bucket.cpp @@ -0,0 +1,185 @@ +// +// raw_bucket.cpp +// App +// +// Created by Malcolm Toon on 7/3/25. +// + +#include +#include +#include + +#include "raw_bucket.hpp" + +#include + +using namespace mbgl; + +RawBucket::~RawBucket() { + +} + +RawBucket::RawBucket(const BucketParameters& bucketParameters, + const std::vector>& layers) { + _layers = layers; +} + +void geometryToLatLon( + const GeometryCoordinate& coord, + int tileX, int tileY, int zoom, + double& lat, double& lon, + int extent = 8192, + int tileSize = 512 +) { + double px = coord.x / double(extent); + double py = coord.y / double(extent); + + double worldPixelX = (tileX + px) * tileSize; + double worldPixelY = (tileY + py) * tileSize; + + double worldSize = tileSize * (1 << zoom); + + double mercX = worldPixelX / worldSize * 2.0 - 1.0; + double mercY = 1.0 - worldPixelY / worldSize * 2.0; + + lon = mercX * 180.0; + lat = 180.0 / M_PI * (2.0 * atan(exp(mercY * M_PI)) - M_PI / 2.0); +} + +void RawBucket::addFeature(const GeometryTileFeature& tileFeature, + const GeometryCollection& geometeryCollection, + const mbgl::ImagePositions& imagePositions, + const PatternLayerMap& patternLayerMap, + std::size_t size, + const CanonicalTileID& tileID) { + + std::shared_ptr tempFeature = std::make_shared(); + + switch (tileFeature.getType()) { + case FeatureType::Point: + std::cout << "Adding Point" << "\n"; + tempFeature->_featureType = RawBucketFeature::FeatureType::FeatureTypePoint; + break; + case FeatureType::Unknown: + std::cout << "Unknown Type Found\n"; + break; + case FeatureType::LineString: + std::cout << "LineString Type Found\n"; + tempFeature->_featureType = RawBucketFeature::FeatureType::FeatureTypeLine; + break; + case FeatureType::Polygon: + std::cout << "Polygon Type Found\n"; + tempFeature->_featureType = RawBucketFeature::FeatureType::FeatureTypePolygon; + break; + + + } + + auto pm = tileFeature.getProperties(); + for (auto p: pm) { + + auto name = p.first; + mapbox::feature::value value = p.second; + + if (auto iVal = value.getInt()) { + std::cout << "Found Int: " << name << ": " << *iVal << "\n"; + tempFeature->_featureProperties[name] = std::to_string(*iVal); + } else if (auto uIVal = value.getUint()) { + std::cout << "Found UInt: " << name << ": " << *uIVal << "\n"; + tempFeature->_featureProperties[name] = std::to_string(*uIVal); + + } else if (auto s = value.getString()) { + + std::cout << "Found String: " << name << ": " << *s << "\n"; + tempFeature->_featureProperties[name] = *s; + + } else if (auto d = value.getDouble()) { + std::cout << "Found Double: " << name << ": " << *d << "\n"; + tempFeature->_featureProperties[name] = std::to_string(*d); + } else if (auto b = value.getBool()) { + std::cout << "Found Bool: " << name << ": " << *b << "\n"; + tempFeature->_featureProperties[name] = std::to_string(*b); + } else if (auto a = value.getArray()) { + std::cout << "Found Array: " << name << ": " << *b << "\n"; + tempFeature->_featureProperties[name] = std::to_string(*b); + } + + +// DECLARE_VALUE_TYPE_ACCESOR(Array, array_type) +// DECLARE_VALUE_TYPE_ACCESOR(Object, object_type) + + } + + LatLngBounds b(tileID); + + + + for (const auto& g : geometeryCollection) { + // g is GeometryCoordinates + RawBucketFeatureCoordinateCollection c; + for (std::size_t i = 0, len = g.size(); i < len; i++) { + const GeometryCoordinate& p1 = g[i]; + + auto d = b.west(); + +// auto c = project( + + +// void geometryToLatLon( +// const GeometryCoordinate& coord, +// int tileX, int tileY, int zoom, +// double& lat, double& lon, +// int extent = 8192, +// int tileSize = 512 + double lat = 0; + double lon = 0; + geometryToLatLon(p1, tileID.x, tileID.y, tileID.z, lat, lon); + + c._coordinates.push_back(RawBucketFeatureCoordinate(lat, lon)); + } + tempFeature->_featureCoordinates.push_back(c); + + } + + for (auto l: _layers) { + auto bi = l->baseImpl; + auto bip = bi.get(); + auto pluginLayer = static_cast(bip); + if (pluginLayer != nullptr) { + if (pluginLayer->_featureLoadedFunction != nullptr) { + pluginLayer->_featureLoadedFunction(tempFeature); + } + + } + // auto pluginLayer = std::dynamic_pointer_cast>(bi); + +// auto pluginLayer = std::dynamic_pointer_cast(l->baseImpl); +// if (pluginLayer != nullptr) { +// if (pluginLayer->_featureLoadedFunction != nullptr) { +// pluginLayer->_featureLoadedFunction(tempFeature); +// } +// } + } + + _features.push_back(tempFeature); + +// std::cout << "Adding Feature Type: " << tileFeature.getType() << "\n"; + +} + +bool RawBucket::hasData() const { + return true; +} + +void RawBucket::upload(gfx::UploadPass&) { + +} + +float RawBucket::getQueryRadius(const RenderLayer&) const { + return 0; +} + +void RawBucket::update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) { + +} + diff --git a/src/mbgl/plugin/raw_bucket.hpp b/src/mbgl/plugin/raw_bucket.hpp new file mode 100644 index 000000000000..507667375d23 --- /dev/null +++ b/src/mbgl/plugin/raw_bucket.hpp @@ -0,0 +1,113 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace mbgl { + +class BucketParameters; +class RenderFillLayer; + +//using FillBinders = PaintPropertyBinders; +//using FillLayoutVertex = gfx::Vertex>; + +class RawBucketFeatureCoordinate { +public: + RawBucketFeatureCoordinate(double lat, double lon) : _lat(lat), _lon(lon) { + + } + double _lat = 0; + double _lon = 0; +}; + +// This is a list of coordinates. Broken out into it's own class because +// a raw bucket feature can have an array of these +class RawBucketFeatureCoordinateCollection { +public: + std::vector _coordinates; +}; + +class RawBucketFeature { +public: + RawBucketFeature() {}; + enum class FeatureType { + FeatureTypeUnknown, + FeatureTypePoint, + FeatureTypeLine, + FeatureTypePolygon + }; + FeatureType _featureType = FeatureType::FeatureTypeUnknown; + std::map _featureProperties; + std::vector _featureCoordinates; +}; + +class RawBucket final : public Bucket { +public: + ~RawBucket() override; + //using PossiblyEvaluatedLayoutProperties = style::FillLayoutProperties::PossiblyEvaluated; + + RawBucket(const BucketParameters&, const std::vector>&); + + void addFeature(const GeometryTileFeature&, + const GeometryCollection&, + const mbgl::ImagePositions&, + const PatternLayerMap&, + std::size_t, + const CanonicalTileID&) override; + + bool hasData() const override; + + void upload(gfx::UploadPass&) override; + + float getQueryRadius(const RenderLayer&) const override; + + void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override; + + // Array of features + std::vector> _features; + + std::vector> _layers; + + /* + static FillLayoutVertex layoutVertex(Point p) { return FillLayoutVertex{{{p.x, p.y}}}; } + +#if MLN_TRIANGULATE_FILL_OUTLINES + using LineVertexVector = gfx::VertexVector; + const std::shared_ptr sharedLineVertices = std::make_shared(); + LineVertexVector& lineVertices = *sharedLineVertices; + + using LineIndexVector = gfx::IndexVector; + const std::shared_ptr sharedLineIndexes = std::make_shared(); + LineIndexVector& lineIndexes = *sharedLineIndexes; + + SegmentVector lineSegments; +#endif // MLN_TRIANGULATE_FILL_OUTLINES + + using BasicLineIndexVector = gfx::IndexVector; + const std::shared_ptr sharedBasicLineIndexes = std::make_shared(); + BasicLineIndexVector& basicLines = *sharedBasicLineIndexes; + + SegmentVector basicLineSegments; + + using VertexVector = gfx::VertexVector; + const std::shared_ptr sharedVertices = std::make_shared(); + VertexVector& vertices = *sharedVertices; + + using TriangleIndexVector = gfx::IndexVector; + const std::shared_ptr sharedTriangles = std::make_shared(); + TriangleIndexVector& triangles = *sharedTriangles; + + SegmentVector triangleSegments; + + std::map paintPropertyBinders; + */ +}; + +} // namespace mbgl diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index 8f6e3abf0419..127355fa769d 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -29,6 +29,8 @@ #include #include +#include + namespace mbgl { using namespace style; @@ -371,6 +373,11 @@ std::unique_ptr RenderOrchestrator::createRenderTree( for (std::size_t index = 0; index < orderedLayers.size(); ++index) { RenderLayer& layer = orderedLayers[index]; const auto* layerInfo = layer.baseImpl->getTypeInfo(); + std::string s1(layerInfo->type); + //std::cout << " -> " << s1 << "\n"; +// if (s1 == "hudhud::gltf-model-layer") { +// std::cout << "Found plugin\n"; +// } const bool layerIsVisible = layer.baseImpl->visibility != style::VisibilityType::None; const bool zoomFitsLayer = layer.supportsZoom(zoomHistory.lastZoom); renderTreeParameters->has3D |= (layerInfo->pass3d == LayerTypeInfo::Pass3D::Required); diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp index 4935bc5f3382..874494cd94a5 100644 --- a/src/mbgl/tile/geometry_tile_worker.cpp +++ b/src/mbgl/tile/geometry_tile_worker.cpp @@ -24,6 +24,7 @@ #include #include +#include namespace mbgl { @@ -396,7 +397,14 @@ void GeometryTileWorker::parse() { groupMap.reserve(layers->size()); for (auto layer : *layers) { - groupMap[layoutKey(*layer->baseImpl)].push_back(std::move(layer)); + auto lk = layoutKey(*layer->baseImpl); + //std::cout << "LK: " << lk << "\n"; + if (lk.find("parking_space1") != std::string::npos) { + // std::cout << " Found PLugin\n"; + } else { + // continue; + } + groupMap[lk].push_back(std::move(layer)); } for (auto& pair : groupMap) { From cb546ff64bdd104a946b66518dbe286dd4c42350 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 9 Jul 2025 17:53:45 +0300 Subject: [PATCH 107/221] revert change that broke zooming --- src/mbgl/text/placement.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp index 71c2b92bf173..c21756ee9dc5 100644 --- a/src/mbgl/text/placement.cpp +++ b/src/mbgl/text/placement.cpp @@ -278,9 +278,9 @@ JointPlacement Placement::placeSymbol(const SymbolInstance& symbolInstance, cons } // Place the symbol only at the current level to prevent it from blinking during the transition. - if (ctx.getOverscaledID().overscaledZ != int(placementZoom)) { - return kUnplaced; - } + // if (ctx.getOverscaledID().overscaledZ != int(placementZoom)) { + // return kUnplaced; + // } const SymbolBucket& bucket = ctx.getBucket(); const mat4& posMatrix = ctx.getRenderTile().matrix; From 8042cfe7fc9b9dd4bed4a3e3831fae593131689b Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 9 Jul 2025 17:59:12 +0300 Subject: [PATCH 108/221] make new ios release 6.17.1 --- platform/ios/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/VERSION b/platform/ios/VERSION index 1980a78f2054..369689dd813e 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.17.0 +6.17.1 From 5f3b25704292fa18f5f54884136b76bf4b3c277f Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 10 Jul 2025 16:42:12 +0300 Subject: [PATCH 109/221] fix callbacks when calling setcontentinset --- platform/ios/src/MLNMapView.mm | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 129252f68b2c..7383f5adfa87 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -2267,7 +2267,7 @@ - (void)handlePanGesture:(UIPanGestureRecognizer *)pan } if (self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone) { - [self didUpdateLocationWithUserTrackingAnimated:true completionHandler:nil cancelTransitions:false]; + [self didUpdateLocationWithUserTrackingAnimated:true cancelTransitions:false completionHandler:nil]; } } @@ -2328,7 +2328,7 @@ - (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch } [self cameraIsChanging]; if (self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone) { - [self didUpdateLocationWithUserTrackingAnimated:true completionHandler:nil cancelTransitions:false]; + [self didUpdateLocationWithUserTrackingAnimated:true cancelTransitions:false completionHandler:nil]; } } else if (pinch.state == UIGestureRecognizerStateEnded || pinch.state == UIGestureRecognizerStateCancelled) @@ -2457,7 +2457,7 @@ - (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate [self cameraIsChanging]; if (self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone) { - [self didUpdateLocationWithUserTrackingAnimated:true completionHandler:nil cancelTransitions:false]; + [self didUpdateLocationWithUserTrackingAnimated:true cancelTransitions:false completionHandler:nil]; } // Trigger a light haptic feedback event when the user rotates to due north. if (@available(iOS 10.0, *)) @@ -2638,7 +2638,7 @@ - (void)handleDoubleTapGesture:(UITapGestureRecognizer *)doubleTap }]; if (self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone) { - [self didUpdateLocationWithUserTrackingAnimated:true completionHandler:nil cancelTransitions:false]; + [self didUpdateLocationWithUserTrackingAnimated:true cancelTransitions:false completionHandler:nil]; } } else @@ -2685,7 +2685,7 @@ - (void)handleTwoFingerTapGesture:(UITapGestureRecognizer *)twoFingerTap }]; if (self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone) { - [self didUpdateLocationWithUserTrackingAnimated:true completionHandler:nil cancelTransitions:false]; + [self didUpdateLocationWithUserTrackingAnimated:true cancelTransitions:false completionHandler:nil]; } } } @@ -2732,7 +2732,7 @@ - (void)handleQuickZoomGesture:(UILongPressGestureRecognizer *)quickZoom [self cameraIsChanging]; if (self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone) { - [self didUpdateLocationWithUserTrackingAnimated:true completionHandler:nil cancelTransitions:false]; + [self didUpdateLocationWithUserTrackingAnimated:true cancelTransitions:false completionHandler:nil]; } } else if (quickZoom.state == UIGestureRecognizerStateEnded || quickZoom.state == UIGestureRecognizerStateCancelled) @@ -2804,7 +2804,7 @@ - (void)handleTwoFingerDragGesture:(UIPanGestureRecognizer *)twoFingerDrag [self cameraIsChanging]; if (self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone) { - [self didUpdateLocationWithUserTrackingAnimated:true completionHandler:nil cancelTransitions:false]; + [self didUpdateLocationWithUserTrackingAnimated:true cancelTransitions:false completionHandler:nil]; } } @@ -4047,7 +4047,7 @@ - (void)setZoomLevel:(double)zoomLevel animated:(BOOL)animated .withZoom(zoomLevel), MLNDurationFromTimeInterval(duration)); if (self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone) { - [self didUpdateLocationWithUserTrackingAnimated:true completionHandler:nil cancelTransitions:false]; + [self didUpdateLocationWithUserTrackingAnimated:true cancelTransitions:false completionHandler:nil]; } } @@ -6419,10 +6419,10 @@ - (void)locationManager:(__unused id)manager didUpdateLocati - (void)didUpdateLocationWithUserTrackingAnimated:(BOOL)animated completionHandler:(nullable void (^)(void))completion { BOOL cancel = self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone; - [self didUpdateLocationWithUserTrackingAnimated:animated completionHandler:completion cancelTransitions:cancel]; + [self didUpdateLocationWithUserTrackingAnimated:animated cancelTransitions:cancel completionHandler:completion]; } -- (void)didUpdateLocationWithUserTrackingAnimated:(BOOL)animated completionHandler:(nullable void (^)(void))completion cancelTransitions:(BOOL)cancel +- (void)didUpdateLocationWithUserTrackingAnimated:(BOOL)animated cancelTransitions:(BOOL)cancel completionHandler:(nullable void (^)(void))completion { [self didUpdateLocationWithUserTrackingDuration:animated ? MLNUserLocationAnimationDuration : 0 completionHandler:completion cancelTransitions:cancel]; } From 33e26aab1210024a5ec1cb7af4b7a1dff9f3c7d5 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 10 Jul 2025 16:42:39 +0300 Subject: [PATCH 110/221] make new release 6.17.2 --- platform/ios/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/VERSION b/platform/ios/VERSION index 369689dd813e..e0fd9e0715e3 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.17.1 +6.17.2 From 61817e36d4a0bd64d86e44cd2796bc5284ab94a0 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Tue, 22 Jul 2025 17:16:37 +0300 Subject: [PATCH 111/221] consolidate concurrent camera animations with changes after maplibre discussions --- platform/ios/src/MLNMapView.mm | 113 ++-------- src/mbgl/map/transform_active.cpp | 357 ++++++++++++++++++------------ src/mbgl/map/transform_active.hpp | 82 ++++++- test/map/transform.test.cpp | 116 ++++++++++ 4 files changed, 416 insertions(+), 252 deletions(-) diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 7383f5adfa87..b3b3839d67c0 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -2148,9 +2148,7 @@ - (void)touchesBegan:(__unused NSSet *)touches withEvent:(__unused UI [self setUserTrackingMode:MLNUserTrackingModeNone animated:NO completionHandler:nil]; } - if (!(self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone)) { - [self cancelTransitions]; - } + [self cancelTransitions]; } - (void)notifyGestureDidBegin { @@ -2200,9 +2198,7 @@ - (void)handlePanGesture:(UIPanGestureRecognizer *)pan { if ( ! self.isScrollEnabled) return; - if (!(self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone)) { - [self cancelTransitions]; - } + [self cancelTransitions]; MLNMapCamera *oldCamera = self.camera; @@ -2265,10 +2261,6 @@ - (void)handlePanGesture:(UIPanGestureRecognizer *)pan self.mbglMap.moveBy({ offset.x, offset.y }, MLNDurationFromTimeInterval(self.decelerationRate)); } } - - if (self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone) { - [self didUpdateLocationWithUserTrackingAnimated:true cancelTransitions:false completionHandler:nil]; - } } [self notifyGestureDidEndWithDrift:drift]; @@ -2279,9 +2271,7 @@ - (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch { if ( ! self.isZoomEnabled) return; - if (!(self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone)) { - [self cancelTransitions]; - } + [self cancelTransitions]; CGPoint centerPoint = [self anchorPointForGesture:pinch]; if (self.anchorRotateOrZoomGesturesToCenterCoordinate) { @@ -2327,9 +2317,6 @@ - (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch } } [self cameraIsChanging]; - if (self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone) { - [self didUpdateLocationWithUserTrackingAnimated:true cancelTransitions:false completionHandler:nil]; - } } else if (pinch.state == UIGestureRecognizerStateEnded || pinch.state == UIGestureRecognizerStateCancelled) { @@ -2396,9 +2383,7 @@ - (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate { if ( ! self.isRotateEnabled) return; - if (!(self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone)) { - [self cancelTransitions]; - } + [self cancelTransitions]; CGPoint centerPoint = [self anchorPointForGesture:rotate]; if (self.anchorRotateOrZoomGesturesToCenterCoordinate) { @@ -2456,9 +2441,6 @@ - (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate } [self cameraIsChanging]; - if (self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone) { - [self didUpdateLocationWithUserTrackingAnimated:true cancelTransitions:false completionHandler:nil]; - } // Trigger a light haptic feedback event when the user rotates to due north. if (@available(iOS 10.0, *)) { @@ -2608,9 +2590,7 @@ - (void)handleDoubleTapGesture:(UITapGestureRecognizer *)doubleTap if ( ! self.isZoomEnabled) return; - if (!(self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone)) { - [self cancelTransitions]; - } + [self cancelTransitions]; self.cameraChangeReasonBitmask |= MLNCameraChangeReasonGestureZoomIn; @@ -2636,10 +2616,6 @@ - (void)handleDoubleTapGesture:(UITapGestureRecognizer *)doubleTap { [weakSelf unrotateIfNeededForGesture]; }]; - - if (self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone) { - [self didUpdateLocationWithUserTrackingAnimated:true cancelTransitions:false completionHandler:nil]; - } } else { @@ -2655,9 +2631,7 @@ - (void)handleTwoFingerTapGesture:(UITapGestureRecognizer *)twoFingerTap if ([self zoomLevel] == *self.mbglMap.getBounds().minZoom) return; - if (!(self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone)) { - [self cancelTransitions]; - } + [self cancelTransitions]; self.cameraChangeReasonBitmask |= MLNCameraChangeReasonGestureZoomOut; @@ -2683,10 +2657,6 @@ - (void)handleTwoFingerTapGesture:(UITapGestureRecognizer *)twoFingerTap { [weakSelf unrotateIfNeededForGesture]; }]; - - if (self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone) { - [self didUpdateLocationWithUserTrackingAnimated:true cancelTransitions:false completionHandler:nil]; - } } } @@ -2694,9 +2664,7 @@ - (void)handleQuickZoomGesture:(UILongPressGestureRecognizer *)quickZoom { if ( ! self.isZoomEnabled) return; - if (!(self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone)) { - [self cancelTransitions]; - } + [self cancelTransitions]; self.cameraChangeReasonBitmask |= MLNCameraChangeReasonGestureOneFingerZoom; @@ -2731,9 +2699,6 @@ - (void)handleQuickZoomGesture:(UILongPressGestureRecognizer *)quickZoom } [self cameraIsChanging]; - if (self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone) { - [self didUpdateLocationWithUserTrackingAnimated:true cancelTransitions:false completionHandler:nil]; - } } else if (quickZoom.state == UIGestureRecognizerStateEnded || quickZoom.state == UIGestureRecognizerStateCancelled) { @@ -2746,9 +2711,7 @@ - (void)handleTwoFingerDragGesture:(UIPanGestureRecognizer *)twoFingerDrag { if ( ! self.isPitchEnabled) return; - if (!(self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone)) { - [self cancelTransitions]; - } + [self cancelTransitions]; self.cameraChangeReasonBitmask |= MLNCameraChangeReasonGestureTilt; static CGFloat initialPitch; @@ -2803,10 +2766,6 @@ - (void)handleTwoFingerDragGesture:(UIPanGestureRecognizer *)twoFingerDrag } [self cameraIsChanging]; - if (self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone) { - [self didUpdateLocationWithUserTrackingAnimated:true cancelTransitions:false completionHandler:nil]; - } - } @@ -3942,12 +3901,6 @@ - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:( } - (void)_setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate edgePadding:(UIEdgeInsets)insets zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion -{ - BOOL cancel = self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone; - [self _setCenterCoordinate:centerCoordinate edgePadding:insets zoomLevel:zoomLevel direction:direction duration:duration animationTimingFunction:function completionHandler:completion cancelTransitions:cancel]; -} - -- (void)_setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate edgePadding:(UIEdgeInsets)insets zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion cancelTransitions:(BOOL)cancelOtherTransitions { if (!_mbglMap) { @@ -4006,9 +3959,7 @@ - (void)_setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate edgePaddin return; } - if (cancelOtherTransitions) { - [self cancelTransitions]; - } + [self cancelTransitions]; self.cameraChangeReasonBitmask |= MLNCameraChangeReasonProgrammatic; @@ -4035,9 +3986,7 @@ - (void)setZoomLevel:(double)zoomLevel animated:(BOOL)animated { MLNLogDebug(@"Setting zoomLevel: %f animated: %@", zoomLevel, MLNStringFromBOOL(animated)); if (zoomLevel == self.zoomLevel) return; - if (!(self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone)) { - [self cancelTransitions]; - } + [self cancelTransitions]; self.cameraChangeReasonBitmask |= MLNCameraChangeReasonProgrammatic; @@ -4045,10 +3994,6 @@ - (void)setZoomLevel:(double)zoomLevel animated:(BOOL)animated self.mbglMap.easeTo(mbgl::CameraOptions() .withZoom(zoomLevel), MLNDurationFromTimeInterval(duration)); - - if (self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone) { - [self didUpdateLocationWithUserTrackingAnimated:true cancelTransitions:false completionHandler:nil]; - } } - (void)setMinimumZoomLevel:(double)minimumZoomLevel @@ -4283,9 +4228,7 @@ - (void)_setDirection:(CLLocationDirection)direction center:(CLLocationCoordinat } if (direction == self.direction) return; - if (!(self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone)) { - [self cancelTransitions]; - } + [self cancelTransitions]; CGFloat duration = animated ? MLNAnimationDuration : 0; @@ -4379,11 +4322,6 @@ - (void)setCamera:(MLNMapCamera *)camera withDuration:(NSTimeInterval)duration a } - (void)setCamera:(MLNMapCamera *)camera withDuration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function edgePadding:(UIEdgeInsets)edgePadding completionHandler:(nullable void (^)(void))completion { - MLNLogDebug(@"Setting camera: %@ duration: %f animationTimingFunction: %@ edgePadding: %@ completionHandler: %@", camera, duration, function, edgePadding, completion); - [self setCamera:camera withDuration:duration animationTimingFunction:function edgePadding:edgePadding cancelTransitions:false completionHandler:completion]; -} - -- (void)setCamera:(MLNMapCamera *)camera withDuration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function edgePadding:(UIEdgeInsets)edgePadding cancelTransitions:(BOOL)cancelOtherTransitions completionHandler:(nullable void (^)(void))completion { if (!_mbglMap) { if (completion) @@ -4393,7 +4331,7 @@ - (void)setCamera:(MLNMapCamera *)camera withDuration:(NSTimeInterval)duration a return; } - MLNLogDebug(@"Setting camera: %@ duration: %f animationTimingFunction: %@ edgePadding: %@ cancelTransitions: %@ completionHandler: %@", camera, duration, function, NSStringFromUIEdgeInsets(edgePadding), cancelOtherTransitions, completion); + MLNLogDebug(@"Setting camera: %@ duration: %f animationTimingFunction: %@ edgePadding: %@ completionHandler: %@", camera, duration, function, NSStringFromUIEdgeInsets(edgePadding), completion); edgePadding = MLNEdgeInsetsInsetEdgeInset(edgePadding, self.contentInset); @@ -4432,9 +4370,7 @@ - (void)setCamera:(MLNMapCamera *)camera withDuration:(NSTimeInterval)duration a } [self willChangeValueForKey:@"camera"]; - if (cancelOtherTransitions) { - [self cancelTransitions]; - } + [self cancelTransitions]; self.cameraChangeReasonBitmask |= MLNCameraChangeReasonProgrammatic; @@ -4530,7 +4466,7 @@ - (void)_flyToCamera:(MLNMapCamera *)camera edgePadding:(UIEdgeInsets)insets wit } - (void)cancelTransitions { - if (!_mbglMap) + if (!_mbglMap || (self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone && self.userTrackingMode != MLNUserTrackingModeFollow)) { return; } @@ -6418,22 +6354,10 @@ - (void)locationManager:(__unused id)manager didUpdateLocati - (void)didUpdateLocationWithUserTrackingAnimated:(BOOL)animated completionHandler:(nullable void (^)(void))completion { - BOOL cancel = self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone; - [self didUpdateLocationWithUserTrackingAnimated:animated cancelTransitions:cancel completionHandler:completion]; -} - -- (void)didUpdateLocationWithUserTrackingAnimated:(BOOL)animated cancelTransitions:(BOOL)cancel completionHandler:(nullable void (^)(void))completion -{ - [self didUpdateLocationWithUserTrackingDuration:animated ? MLNUserLocationAnimationDuration : 0 completionHandler:completion cancelTransitions:cancel]; + [self didUpdateLocationWithUserTrackingAnimated:animated completionHandler:completion]; } - (void)didUpdateLocationWithUserTrackingDuration:(NSTimeInterval)duration completionHandler:(nullable void (^)(void))completion -{ - BOOL cancel = self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone; - [self didUpdateLocationWithUserTrackingDuration:duration completionHandler:completion cancelTransitions:cancel]; -} - -- (void)didUpdateLocationWithUserTrackingDuration:(NSTimeInterval)duration completionHandler:(nullable void (^)(void))completion cancelTransitions:(BOOL)cancelTransitions { CLLocation *location = self.userLocation.location; if ( ! _showsUserLocation || ! location @@ -6479,13 +6403,13 @@ - (void)didUpdateLocationWithUserTrackingDuration:(NSTimeInterval)duration compl else if (self.userTrackingState == MLNUserTrackingStateChanged) { // Subsequent updates get a more subtle animation. - [self didUpdateLocationIncrementallyDuration:duration completionHandler:completion cancelTransitions:cancelTransitions]; + [self didUpdateLocationIncrementallyDuration:duration completionHandler:completion]; } [self unrotateIfNeededAnimated:YES]; } /// Changes the viewport based on an incremental location update. -- (void)didUpdateLocationIncrementallyDuration:(NSTimeInterval)duration completionHandler:(nullable void (^)(void))completion cancelTransitions:(BOOL)cancelTransitions +- (void)didUpdateLocationIncrementallyDuration:(NSTimeInterval)duration completionHandler:(nullable void (^)(void))completion { [self _setCenterCoordinate:self.userLocation.location.coordinate edgePadding:self.edgePaddingForFollowing @@ -6493,8 +6417,7 @@ - (void)didUpdateLocationIncrementallyDuration:(NSTimeInterval)duration completi direction:self.directionByFollowingWithCourse duration:duration animationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear] - completionHandler:completion - cancelTransitions:cancelTransitions]; + completionHandler:completion]; } /// Changes the viewport based on a significant location update, such as the diff --git a/src/mbgl/map/transform_active.cpp b/src/mbgl/map/transform_active.cpp index 31466b7b1849..d0c651807237 100644 --- a/src/mbgl/map/transform_active.cpp +++ b/src/mbgl/map/transform_active.cpp @@ -7,13 +7,13 @@ using namespace std::numbers; namespace mbgl { -void TransformActive::easeTo(const CameraOptions& inputCamera, const AnimationOptions& animation) { +void TransformActive::easeTo(const CameraOptions& inputCamera, const AnimationOptions& animationOptions) { CameraOptions camera = inputCamera; - Duration duration = animation.duration.value_or(Duration::zero()); + Duration duration = animationOptions.duration.value_or(Duration::zero()); if (state.getLatLngBounds() == LatLngBounds() && !isGestureInProgress() && duration != Duration::zero()) { // reuse flyTo, without exaggerated animation, to achieve constant ground speed. - return flyTo(camera, animation, true); + return flyTo(camera, animationOptions, true); } double zoom = camera.zoom.value_or(getZoom()); @@ -28,8 +28,8 @@ void TransformActive::easeTo(const CameraOptions& inputCamera, const AnimationOp double pitch = camera.pitch ? util::deg2rad(*camera.pitch) : getPitch(); if (std::isnan(zoom) || std::isnan(bearing) || std::isnan(pitch)) { - if (animation.transitionFinishFn) { - animation.transitionFinishFn(); + if (animationOptions.transitionFinishFn) { + animationOptions.transitionFinishFn(); } return; } @@ -63,75 +63,90 @@ void TransformActive::easeTo(const CameraOptions& inputCamera, const AnimationOp const double startBearing = state.getBearing(); const double startPitch = state.getPitch(); const EdgeInsets startEdgeInsets = state.getEdgeInsets(); - - auto pa = std::make_shared( - Clock::now(), duration, animation, unwrappedLatLng != startLatLng, zoom != startZoom, bearing != startBearing); + auto animation = std::make_shared(Clock::now(), + duration, + animationOptions, + unwrappedLatLng != startLatLng, + zoom != startZoom, + bearing != startBearing); // NOTE: For tests only - transitionStart = pa->start; - transitionDuration = pa->duration; + transitionStart = animation->start; + transitionDuration = animation->duration; - if (!pas.zoom.set || startZoom != zoom) { - animationFinishFrame(pas.zoom.pa); - pas.zoom = { - .pa = pa, + if (!properties.zoom.set || startZoom != zoom) { + if (properties.zoom.set && properties.zoom.current != properties.zoom.target && properties.zoom.animation) { + animationFinishFrame(*properties.zoom.animation); + } + properties.zoom = { + .animation = animation, .current = startZoom, .target = zoom, .set = true, .frameZoomFunc = - [=, this](TimePoint now) { - return util::interpolate(pas.zoom.current, pas.zoom.target, pas.zoom.pa->t(now)); + [startZoom, zoom, animation](TimePoint now) { + return util::interpolate(startZoom, zoom, animation->interpolant(now)); }, }; } - if (!pas.latlng.set || startPoint != endPoint) { - animationFinishFrame(pas.latlng.pa); - pas.latlng = { - .pa = pa, + if (!properties.latlng.set || startPoint != endPoint) { + if (properties.latlng.set && properties.latlng.current != properties.latlng.target && + properties.latlng.animation) { + animationFinishFrame(*properties.latlng.animation); + } + properties.latlng = { + .animation = animation, .current = startPoint, .target = endPoint, .set = true, .frameLatLngFunc = - [=, this](TimePoint now) { - Point framePoint = util::interpolate( - pas.latlng.current, pas.latlng.target, pas.latlng.pa->t(now)); + [startPoint, endPoint, startZoom, animation, this](TimePoint now) { + Point framePoint = util::interpolate(startPoint, endPoint, animation->interpolant(now)); return Projection::unproject(framePoint, state.zoomScale(startZoom)); }, }; } - if (!pas.bearing.set || bearing != startBearing) { - animationFinishFrame(pas.bearing.pa); - pas.bearing = { - .pa = pa, + if (!properties.bearing.set || bearing != startBearing) { + if (properties.bearing.set && properties.bearing.current != properties.bearing.target && + properties.bearing.animation) { + animationFinishFrame(*properties.bearing.animation); + } + properties.bearing = { + .animation = animation, .current = startBearing, .target = bearing, .set = true, }; } - if (!pas.padding.set || padding != startEdgeInsets) { - animationFinishFrame(pas.padding.pa); - pas.padding = { - .pa = pa, + if (!properties.padding.set || padding != startEdgeInsets) { + if (properties.padding.set && properties.padding.current != properties.padding.target && + properties.padding.animation) { + animationFinishFrame(*properties.padding.animation); + } + properties.padding = { + .animation = animation, .current = startEdgeInsets, .target = padding, .set = true, }; } - if (!pas.pitch.set || pitch != startPitch) { - animationFinishFrame(pas.pitch.pa); - pas.pitch = { - .pa = pa, + if (!properties.pitch.set || pitch != startPitch) { + if (properties.pitch.set && properties.pitch.current != properties.pitch.target && properties.pitch.animation) { + animationFinishFrame(*properties.pitch.animation); + } + properties.pitch = { + .animation = animation, .current = startPitch, .target = pitch, .set = true, }; } - startTransition(camera, duration); + startTransition(camera, duration, *animation); } void TransformActive::flyTo(const CameraOptions& inputCamera, - const AnimationOptions& animation, + const AnimationOptions& animationOptions, bool linearZoomInterpolation) { CameraOptions camera = inputCamera; @@ -145,8 +160,8 @@ void TransformActive::flyTo(const CameraOptions& inputCamera, double pitch = camera.pitch ? util::deg2rad(*camera.pitch) : getPitch(); if (std::isnan(zoom) || std::isnan(bearing) || std::isnan(pitch) || state.getSize().isEmpty()) { - if (animation.transitionFinishFn) { - animation.transitionFinishFn(); + if (animationOptions.transitionFinishFn) { + animationOptions.transitionFinishFn(); } return; } @@ -190,8 +205,8 @@ void TransformActive::flyTo(const CameraOptions& inputCamera, root mean squared average velocity, VRMS. A value of 1 produces a circular motion. */ double rho = 1.42; - if (animation.minZoom || linearZoomInterpolation) { - double minZoom = util::min(animation.minZoom.value_or(startZoom), startZoom, zoom); + if (animationOptions.minZoom || linearZoomInterpolation) { + double minZoom = util::min(animationOptions.minZoom.value_or(startZoom), startZoom, zoom); minZoom = util::clamp(minZoom, state.getMinZoom(), state.getMaxZoom()); /// wm: Maximum visible span, measured in pixels with respect /// to the initial scale. @@ -234,21 +249,21 @@ void TransformActive::flyTo(const CameraOptions& inputCamera, double S = (isClose ? (std::abs(std::log(w1 / w0)) / rho) : ((r1 - r0) / rho)); Duration duration; - if (animation.duration) { - duration = *animation.duration; + if (animationOptions.duration) { + duration = *animationOptions.duration; } else { /// V: Average velocity, measured in ρ-screenfuls per second. double velocity = 1.2; - if (animation.velocity) { - velocity = *animation.velocity / rho; + if (animationOptions.velocity) { + velocity = *animationOptions.velocity / rho; } duration = std::chrono::duration_cast(std::chrono::duration(S / velocity)); } if (duration == Duration::zero()) { // Perform an instantaneous transition. jumpTo(camera); - if (animation.transitionFinishFn) { - animation.transitionFinishFn(); + if (animationOptions.transitionFinishFn) { + animationOptions.transitionFinishFn(); } return; } @@ -256,126 +271,142 @@ void TransformActive::flyTo(const CameraOptions& inputCamera, const double startScale = state.getScale(); const EdgeInsets startEdgeInsets = state.getEdgeInsets(); - auto pa = std::make_shared( - Clock::now(), duration, animation, true, true, bearing != startBearing); + auto animation = std::make_shared( + Clock::now(), duration, animationOptions, true, true, bearing != startBearing); // NOTE: For tests only - transitionStart = pa->start; - transitionDuration = pa->duration; + transitionStart = animation->start; + transitionDuration = animation->duration; - if (!pas.zoom.set || startZoom != zoom) { - animationFinishFrame(pas.zoom.pa); - pas.zoom = { - .pa = pa, + if (!properties.zoom.set || startZoom != zoom) { + if (properties.zoom.set && properties.zoom.current != properties.zoom.target && properties.zoom.animation) { + animationFinishFrame(*properties.zoom.animation); + } + properties.zoom = { + .animation = animation, .current = startZoom, .target = zoom, .set = true, .frameZoomFunc = - [=, this](TimePoint now) { - double t = pas.zoom.pa->t(now); + [linearZoomInterpolation, startZoom, zoom, S, w, this](TimePoint now) { + double t = properties.zoom.animation->interpolant(now); double s = t * S; - double frameZoom = linearZoomInterpolation ? util::interpolate(pas.zoom.current, pas.zoom.target, t) - : pas.zoom.current + state.scaleZoom(1 / w(s)); + double frameZoom = linearZoomInterpolation ? util::interpolate(startZoom, zoom, t) + : startZoom + state.scaleZoom(1 / w(s)); if (std::isnan(frameZoom)) { - frameZoom = pas.zoom.target; + frameZoom = zoom; } return frameZoom; }, }; } - if (!pas.latlng.set || startPoint != endPoint) { - animationFinishFrame(pas.latlng.pa); - pas.latlng = { - .pa = pa, + if (!properties.latlng.set || startPoint != endPoint) { + if (properties.latlng.set && properties.latlng.current != properties.latlng.target && + properties.latlng.animation) { + animationFinishFrame(*properties.latlng.animation); + } + properties.latlng = { + .animation = animation, .current = startPoint, .target = endPoint, .set = true, .frameLatLngFunc = - [=, this](TimePoint now) { - double t = pas.latlng.pa->t(now); + [startScale, S, u, this](TimePoint now) { + double t = properties.latlng.animation->interpolant(now); double s = t * S; double us = t == 1.0 ? 1.0 : u(s); - Point framePoint = util::interpolate(pas.latlng.current, pas.latlng.target, us); + Point framePoint = util::interpolate( + properties.latlng.current, properties.latlng.target, us); return Projection::unproject(framePoint, startScale); }, }; } - if (!pas.bearing.set || bearing != startBearing) { - animationFinishFrame(pas.bearing.pa); - pas.bearing = { - .pa = pa, + if (!properties.bearing.set || bearing != startBearing) { + if (properties.bearing.set && properties.bearing.current != properties.bearing.target && + properties.bearing.animation) { + animationFinishFrame(*properties.bearing.animation); + } + properties.bearing = { + .animation = animation, .current = startBearing, .target = bearing, .set = true, }; } - if (!pas.padding.set || padding != startEdgeInsets) { - animationFinishFrame(pas.padding.pa); - pas.padding = {.pa = pa, .current = startEdgeInsets, .target = padding, .set = true}; + if (!properties.padding.set || padding != startEdgeInsets) { + if (properties.padding.set && properties.padding.current != properties.padding.target && + properties.padding.animation) { + animationFinishFrame(*properties.padding.animation); + } + properties.padding = {.animation = animation, .current = startEdgeInsets, .target = padding, .set = true}; } - if (!pas.pitch.set || pitch != startPitch) { - animationFinishFrame(pas.pitch.pa); - pas.pitch = { - .pa = pa, + if (!properties.pitch.set || pitch != startPitch) { + if (properties.pitch.set && properties.pitch.current != properties.pitch.target && properties.pitch.animation) { + animationFinishFrame(*properties.pitch.animation); + } + properties.pitch = { + .animation = animation, .current = startPitch, .target = pitch, .set = true, }; } - startTransition(camera, duration); + startTransition(camera, duration, *animation); } -bool TransformActive::animationTransitionFrame(std::shared_ptr& pa, double t) { - if (pa->ran) { - return pa->done; +bool TransformActive::animationTransitionFrame(Animation& animation, double t) { + if (animation.ran) { + return animation.done; } - pa->ran = true; + animation.ran = true; if (t < 1.0) { - if (pa->animation.transitionFrameFn) { - pa->animation.transitionFrameFn(t); + if (animation.options.transitionFrameFn) { + animation.options.transitionFrameFn(t); } observer.onCameraIsChanging(); - pa->done = false; + animation.done = false; } else { - pa->done = true; + animation.done = true; } - return pa->done; + return animation.done; } -void TransformActive::animationFinishFrame(std::shared_ptr& pa) { - if (!pa || pa->finished) { +void TransformActive::animationFinishFrame(Animation& animation) { + if (animation.finished) { return; } - if (pa->animation.transitionFinishFn) { - pa->animation.transitionFinishFn(); + if (animation.options.transitionFinishFn) { + animation.options.transitionFinishFn(); } - pa->finished = true; + animation.finished = true; + + if (animation.anchor) animation.anchor = std::nullopt; - observer.onCameraDidChange(pa->isAnimated() ? MapObserver::CameraChangeMode::Animated - : MapObserver::CameraChangeMode::Immediate); + observer.onCameraDidChange(animation.isAnimated() ? MapObserver::CameraChangeMode::Animated + : MapObserver::CameraChangeMode::Immediate); } -void TransformActive::startTransition(const CameraOptions& camera, const Duration& duration) { - bool isAnimated = duration != Duration::zero(); +void TransformActive::startTransition(const CameraOptions& camera, const Duration& duration, Animation& animation) { + const bool isAnimated = duration != Duration::zero(); observer.onCameraWillChange(isAnimated ? MapObserver::CameraChangeMode::Animated : MapObserver::CameraChangeMode::Immediate); // Associate the anchor, if given, with a coordinate. // Anchor and center points are mutually exclusive, with preference for the // center point when both are set. - pas.anchor = camera.center ? std::nullopt : camera.anchor; - if (pas.anchor) { - pas.anchor->y = state.getSize().height - pas.anchor->y; - pas.anchorLatLng = state.screenCoordinateToLatLng(*pas.anchor); + if (!camera.center && camera.anchor) { + animation.anchor = camera.anchor; + animation.anchor->y = state.getSize().height - animation.anchor->y; + animation.anchorLatLng = state.screenCoordinateToLatLng(*animation.anchor); } if (!isAnimated) { @@ -385,19 +416,22 @@ void TransformActive::startTransition(const CameraOptions& camera, const Duratio } bool TransformActive::inTransition() const { - return pas.latlng.set || pas.zoom.set || pas.bearing.set || pas.padding.set || pas.pitch.set; + return properties.latlng.set || properties.zoom.set || properties.bearing.set || properties.padding.set || + properties.pitch.set; } void TransformActive::updateTransitions(const TimePoint& now) { if (!activeAnimation) { activeAnimation = true; - bool panning = false, scaling = false, rotating = false; - visit_pas([&](std::shared_ptr& pa) { - if (pa) { - panning |= pa->panning; - scaling |= pa->scaling; - rotating |= pa->rotating; + bool panning = false; + bool scaling = false; + bool rotating = false; + visitProperties([&](Animation& animation) { + if (!animation.done) { + panning |= animation.panning; + scaling |= animation.scaling; + rotating |= animation.rotating; } }); @@ -406,68 +440,97 @@ void TransformActive::updateTransitions(const TimePoint& now) { .withScalingInProgress(scaling) .withRotatingInProgress(rotating)); - if (pas.latlng.frameLatLngFunc && pas.zoom.frameZoomFunc) { - if (pas.latlng.set || pas.zoom.set) { - state.setLatLngZoom(pas.latlng.frameLatLngFunc(now), pas.zoom.frameZoomFunc(now)); - if (animationTransitionFrame(pas.latlng.pa, pas.latlng.pa->t(now))) { - pas.latlng.set = false; - } - if (animationTransitionFrame(pas.zoom.pa, pas.zoom.pa->t(now))) { - pas.zoom.set = false; - } + const bool zoomSet = properties.zoom.set && properties.zoom.animation; + if ((properties.latlng.set && properties.latlng.animation) || zoomSet) { + state.setLatLngZoom( + properties.latlng.frameLatLngFunc ? properties.latlng.frameLatLngFunc(now) : state.getLatLng(), + properties.zoom.frameZoomFunc ? properties.zoom.frameZoomFunc(now) : state.getZoom()); + if (properties.latlng.animation && + animationTransitionFrame(*properties.latlng.animation, properties.latlng.animation->interpolant(now))) { + properties.latlng.set = false; + } + if (properties.zoom.animation && + animationTransitionFrame(*properties.zoom.animation, properties.zoom.animation->interpolant(now))) { + properties.zoom.set = false; } - } - if (pas.bearing.set) { - double bearing_t = pas.bearing.pa->t(now); - state.setBearing( - util::wrap(util::interpolate(pas.bearing.current, pas.bearing.target, bearing_t), -pi, pi)); - if (animationTransitionFrame(pas.bearing.pa, bearing_t)) { - pas.bearing.set = false; + if (zoomSet && properties.zoom.animation->anchor) { + state.moveLatLng(properties.zoom.animation->anchorLatLng, *properties.zoom.animation->anchor); + } + } + if (properties.bearing.set && properties.bearing.animation) { + const double bearing_t = properties.bearing.animation->interpolant(now); + state.setBearing(util::wrap( + util::interpolate(properties.bearing.current, properties.bearing.target, bearing_t), -pi, pi)); + if (animationTransitionFrame(*properties.bearing.animation, bearing_t)) { + properties.bearing.set = false; } } - if (pas.padding.set) { - double padding_t = pas.padding.pa->t(now); + if (properties.padding.set && properties.padding.animation) { + const double padding_t = properties.padding.animation->interpolant(now); state.setEdgeInsets( - {util::interpolate(pas.padding.current.top(), pas.padding.target.top(), padding_t), - util::interpolate(pas.padding.current.left(), pas.padding.target.left(), padding_t), - util::interpolate(pas.padding.current.bottom(), pas.padding.target.bottom(), padding_t), - util::interpolate(pas.padding.current.right(), pas.padding.target.right(), padding_t)}); - if (animationTransitionFrame(pas.padding.pa, padding_t)) { - pas.padding.set = false; + {util::interpolate(properties.padding.current.top(), properties.padding.target.top(), padding_t), + util::interpolate(properties.padding.current.left(), properties.padding.target.left(), padding_t), + util::interpolate(properties.padding.current.bottom(), properties.padding.target.bottom(), padding_t), + util::interpolate(properties.padding.current.right(), properties.padding.target.right(), padding_t)}); + if (animationTransitionFrame(*properties.padding.animation, padding_t)) { + properties.padding.set = false; } } - double maxPitch = getMaxPitchForEdgeInsets(state.getEdgeInsets()); - if (pas.pitch.set || maxPitch < pas.pitch.current) { - double pitch_t = pas.pitch.pa->t(now); - state.setPitch(std::min(maxPitch, util::interpolate(pas.pitch.current, pas.pitch.target, pitch_t))); - if (animationTransitionFrame(pas.pitch.pa, pitch_t)) { - pas.pitch.set = false; + const double maxPitch = getMaxPitchForEdgeInsets(state.getEdgeInsets()); + if ((properties.pitch.set || maxPitch < properties.pitch.current) && properties.pitch.animation) { + double pitch_t = properties.pitch.animation->interpolant(now); + state.setPitch( + std::min(maxPitch, util::interpolate(properties.pitch.current, properties.pitch.target, pitch_t))); + if (animationTransitionFrame(*properties.pitch.animation, pitch_t)) { + properties.pitch.set = false; } - } - if (pas.anchor) { - state.moveLatLng(pas.anchorLatLng, *pas.anchor); + if (properties.pitch.set && properties.pitch.animation && properties.pitch.animation->anchor) { + state.moveLatLng(properties.pitch.animation->anchorLatLng, *properties.pitch.animation->anchor); + } } - visit_pas([&](std::shared_ptr& pa) { - if (pa) { - if (pa->done) animationFinishFrame(pa); - pa->ran = false; + panning = false; + scaling = false; + rotating = false; + visitProperties([&](Animation& animation) { + if (animation.done) { + animationFinishFrame(animation); + } else { + panning |= animation.panning; + scaling |= animation.scaling; + rotating |= animation.rotating; } + animation.ran = false; }); + state.setProperties(TransformStateProperties() + .withPanningInProgress(panning) + .withScalingInProgress(scaling) + .withRotatingInProgress(rotating)); + activeAnimation = false; } } void TransformActive::cancelTransitions() { - visit_pas([this](std::shared_ptr& pa) { animationFinishFrame(pa); }); + visitProperties([this](Animation& animation) { animationFinishFrame(animation); }); - pas = {}; + properties = {}; activeAnimation = false; } +double TransformActive::Animation::interpolant(const TimePoint& now) const { + double t = isAnimated() ? (std::chrono::duration(now - start) / duration) : 1.0f; + if (t >= 1.0) { + return 1.0; + } + + util::UnitBezier ease = options.easing ? *options.easing : util::DEFAULT_TRANSITION_EASE; + return ease.solve(t, 0.001); +} + } // namespace mbgl diff --git a/src/mbgl/map/transform_active.hpp b/src/mbgl/map/transform_active.hpp index dcf15272390d..7e1fb81938c9 100644 --- a/src/mbgl/map/transform_active.hpp +++ b/src/mbgl/map/transform_active.hpp @@ -62,20 +62,82 @@ class TransformActive : public Transform { assert(false); }; - void startTransition(const CameraOptions&, const Duration&); + struct Animation { + const TimePoint start; + const Duration duration; + const AnimationOptions options; + bool ran = false; // Did this property animation run this frame + bool finished = false; // Did we execute the finish frame for this property animation this frame + bool done = false; // Did this property animation reach the end of the frame + // The below variables keep track of the panning, scaling, and rotating transform state + // so we can correctly set it at the end of the `updateTransitions` if more + // than one `Animation` is running at the same time. + const bool panning; + const bool scaling; + const bool rotating; + + // Anchor + std::optional anchor; + LatLng anchorLatLng; + + Animation(TimePoint start_, + Duration duration_, + AnimationOptions options_, + bool panning_, + bool scaling_, + bool rotating_) + : start(start_), + duration(duration_), + options(options_), + panning(panning_), + scaling(scaling_), + rotating(rotating_) {} + + double interpolant(const TimePoint&) const; + + bool isAnimated() const { return duration != Duration::zero(); } + }; + + template + struct Property { + std::shared_ptr animation; + T current; + T target; + bool set = false; - bool animationTransitionFrame(std::shared_ptr&, double); - void animationFinishFrame(std::shared_ptr&); + std::function frameLatLngFunc = nullptr; + std::function frameZoomFunc = nullptr; + }; + + struct Properties { + Property> latlng; + Property zoom, bearing, pitch; + Property padding; + }; - void visit_pas(const std::function&)>& f) { - f(pas.latlng.pa); - f(pas.zoom.pa); - f(pas.bearing.pa); - f(pas.pitch.pa); - f(pas.padding.pa); + void startTransition(const CameraOptions&, const Duration&, Animation&); + bool animationTransitionFrame(Animation&, const double); + void animationFinishFrame(Animation&); + + void visitProperties(const std::function& f) { + if (properties.zoom.animation) { + f(*properties.zoom.animation); + } + if (properties.latlng.animation) { + f(*properties.latlng.animation); + } + if (properties.bearing.animation) { + f(*properties.bearing.animation); + } + if (properties.padding.animation) { + f(*properties.padding.animation); + } + if (properties.pitch.animation) { + f(*properties.pitch.animation); + } } - PropertyAnimations pas; + Properties properties; bool activeAnimation = false; }; diff --git a/test/map/transform.test.cpp b/test/map/transform.test.cpp index 69aa6bffa6af..207ab77ba041 100644 --- a/test/map/transform.test.cpp +++ b/test/map/transform.test.cpp @@ -1206,6 +1206,122 @@ TEST_P(TransfromParametrized, FreeCameraOptionsStateSynchronization) { EXPECT_THAT(forward, Vec3NearEquals1E5(vec3{{0, -0.866025, -0.5}})); } +TEST(Transform, ConcurrentAnimation) { + TransformActive transform; + transform.resize({1, 1}); + + const LatLng defaultLatLng{0, 0}; + CameraOptions defaultCameraOptions = + CameraOptions().withCenter(defaultLatLng).withZoom(0).withPitch(0).withBearing(0); + transform.jumpTo(defaultCameraOptions); + ASSERT_DOUBLE_EQ(transform.getLatLng().latitude(), 0); + ASSERT_DOUBLE_EQ(transform.getLatLng().longitude(), 0); + ASSERT_DOUBLE_EQ(0, transform.getZoom()); + ASSERT_DOUBLE_EQ(0, transform.getPitch()); + ASSERT_DOUBLE_EQ(0, transform.getBearing()); + + const LatLng latLng{45, 135}; + const double zoom = 10; + CameraOptions zoomLatLngCameraOptions = CameraOptions().withCenter(latLng).withZoom(zoom); + AnimationOptions zoomLatLngOptions(Seconds(1)); + int zoomLatLngFrameCallbackCount = 0; + zoomLatLngOptions.transitionFrameFn = [&](double t) { + zoomLatLngFrameCallbackCount++; + + ASSERT_TRUE(t >= 0 && t <= 1); + ASSERT_GE(latLng.latitude(), transform.getLatLng().latitude()); + ASSERT_GE(latLng.longitude(), transform.getLatLng().longitude()); + ASSERT_GE(zoom, transform.getZoom()); + }; + int zoomLatLngFinishCallbackCount = 0; + zoomLatLngOptions.transitionFinishFn = [&]() { + zoomLatLngFinishCallbackCount++; + + ASSERT_DOUBLE_EQ(latLng.latitude(), transform.getLatLng().latitude()); + ASSERT_DOUBLE_EQ(latLng.longitude(), transform.getLatLng().longitude()); + ASSERT_DOUBLE_EQ(zoom, transform.getZoom()); + }; + transform.easeTo(zoomLatLngCameraOptions, zoomLatLngOptions); + + ASSERT_TRUE(transform.inTransition()); + + TimePoint transitionStart = transform.getTransitionStart(); + + const double pitch = 60; + const double bearing = 45; + CameraOptions pitchBearingCameraOptions = CameraOptions().withPitch(pitch).withBearing(bearing); + AnimationOptions pitchBearingOptions(Seconds(2)); + int pitchBearingFrameCallbackCount = 0; + pitchBearingOptions.transitionFrameFn = [&](double t) { + pitchBearingFrameCallbackCount++; + + ASSERT_TRUE(t >= 0 && t <= 1); + ASSERT_GE(util::deg2rad(pitch), transform.getPitch()); + ASSERT_LE(-util::deg2rad(bearing), transform.getBearing()); + }; + int pitchBearingFinishCallbackCount = 0; + pitchBearingOptions.transitionFinishFn = [&]() { + pitchBearingFinishCallbackCount++; + + ASSERT_DOUBLE_EQ(util::deg2rad(pitch), transform.getPitch()); + ASSERT_DOUBLE_EQ(-util::deg2rad(bearing), transform.getBearing()); + }; + transform.easeTo(pitchBearingCameraOptions, pitchBearingOptions); + + ASSERT_TRUE(transform.inTransition()); + transform.updateTransitions(transitionStart + Milliseconds(500)); + transform.updateTransitions(transitionStart + Milliseconds(900)); + ASSERT_TRUE(transform.inTransition()); // Second Transition is still running + transform.updateTransitions(transform.getTransitionStart() + Seconds(2)); + ASSERT_FALSE(transform.inTransition()); + + ASSERT_EQ(zoomLatLngFrameCallbackCount, 2); + ASSERT_EQ(zoomLatLngFinishCallbackCount, 1); + ASSERT_EQ(pitchBearingFrameCallbackCount, 2); + ASSERT_EQ(pitchBearingFinishCallbackCount, 1); + + // Test cancelTransitions with concurrent animations + const LatLng latLng2{0, 0}; + const double zoom2 = 0; + CameraOptions zoomLatLngCameraOptions2 = CameraOptions().withCenter(latLng2).withZoom(zoom2); + AnimationOptions zoomLatLngOptions2(Seconds(1)); + transform.easeTo(zoomLatLngCameraOptions2, zoomLatLngOptions2); + + const double pitch2 = 0; + const double bearing2 = 0; + CameraOptions pitchBearingCameraOptions2 = CameraOptions().withPitch(pitch2).withBearing(bearing2); + AnimationOptions pitchBearingOptions2(Seconds(2)); + transform.easeTo(pitchBearingCameraOptions2, pitchBearingOptions2); + + ASSERT_TRUE(transform.inTransition()); + transform.cancelTransitions(); + ASSERT_FALSE(transform.inTransition()); + + // Reset State + transform.jumpTo(defaultCameraOptions); + + zoomLatLngFrameCallbackCount = 0; + zoomLatLngFinishCallbackCount = 0; + transform.easeTo(zoomLatLngCameraOptions, zoomLatLngOptions); + + transitionStart = transform.getTransitionStart(); + + pitchBearingFrameCallbackCount = 0; + pitchBearingFinishCallbackCount = 0; + pitchBearingOptions.duration = Seconds(0); + transform.easeTo(pitchBearingCameraOptions, pitchBearingOptions); + + ASSERT_TRUE(transform.inTransition()); + transform.updateTransitions(transitionStart + Milliseconds(500)); + transform.updateTransitions(transitionStart + Seconds(1)); + ASSERT_FALSE(transform.inTransition()); + + ASSERT_EQ(zoomLatLngFrameCallbackCount, 2); + ASSERT_EQ(zoomLatLngFinishCallbackCount, 1); + ASSERT_EQ(pitchBearingFrameCallbackCount, 0); + ASSERT_EQ(pitchBearingFinishCallbackCount, 1); +} + INSTANTIATE_TEST_SUITE_P(Transform, TransfromParametrized, ::testing::Values(std::make_shared(TransformObserver::nullObserver()), From bc18431ed48fae1ce783cf5c2d51ef9c66e1d99f Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 24 Jul 2025 14:37:06 +0300 Subject: [PATCH 112/221] release new ios version --- platform/ios/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/VERSION b/platform/ios/VERSION index e0fd9e0715e3..83aa95a7ad49 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.17.2 +6.17.3 From 3aa92dbe8a1d0888495cd8909e3e6f8e0c3ff409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Fri, 25 Jul 2025 10:35:16 -0400 Subject: [PATCH 113/221] Initial commit --- bazel/core.bzl | 6 +- platform/darwin/app/PluginLayerExample.mm | 58 +++++- platform/darwin/src/MLNPluginLayer.h | 19 ++ platform/darwin/src/MLNPluginLayer.mm | 15 ++ platform/ios/src/MLNMapView.mm | 119 ++++++++--- src/mbgl/plugin/feature_collection.cpp | 8 + src/mbgl/plugin/feature_collection.hpp | 74 +++++++ ...cket.cpp => feature_collection_bucket.cpp} | 103 +++++++--- ...cket.hpp => feature_collection_bucket.hpp} | 73 ++++--- src/mbgl/plugin/plugin_layer.hpp | 7 +- src/mbgl/plugin/plugin_layer_factory.cpp | 16 +- src/mbgl/plugin/plugin_layer_factory.hpp | 2 +- src/mbgl/plugin/plugin_layer_impl.hpp | 14 ++ src/mbgl/plugin/plugin_layer_render.cpp | 191 +++++++++++++++++- src/mbgl/plugin/plugin_layer_render.hpp | 4 + src/mbgl/renderer/render_orchestrator.cpp | 5 - src/mbgl/tile/geometry_tile.cpp | 2 +- 17 files changed, 603 insertions(+), 113 deletions(-) create mode 100644 src/mbgl/plugin/feature_collection.cpp create mode 100644 src/mbgl/plugin/feature_collection.hpp rename src/mbgl/plugin/{raw_bucket.cpp => feature_collection_bucket.cpp} (58%) rename src/mbgl/plugin/{raw_bucket.hpp => feature_collection_bucket.hpp} (66%) diff --git a/bazel/core.bzl b/bazel/core.bzl index efc259dbed87..3fbf7eeea8aa 100644 --- a/bazel/core.bzl +++ b/bazel/core.bzl @@ -4,7 +4,8 @@ MLN_LAYER_PLUGIN_HEADERS = [ "src/mbgl/plugin/plugin_layer_impl.hpp", "src/mbgl/plugin/plugin_layer_render.hpp", "src/mbgl/plugin/plugin_layer_properties.hpp", - "src/mbgl/plugin/raw_bucket.hpp", + "src/mbgl/plugin/feature_collection_bucket.hpp", + "src/mbgl/plugin/feature_collection.hpp", ] MLN_LAYER_PLUGIN_SOURCE = [ @@ -13,7 +14,8 @@ MLN_LAYER_PLUGIN_SOURCE = [ "src/mbgl/plugin/plugin_layer_impl.cpp", "src/mbgl/plugin/plugin_layer_render.cpp", "src/mbgl/plugin/plugin_layer_properties.cpp", - "src/mbgl/plugin/raw_bucket.cpp", + "src/mbgl/plugin/feature_collection_bucket.cpp", + "src/mbgl/plugin/feature_collection.cpp", ] MLN_PUBLIC_GENERATED_STYLE_HEADERS = [ diff --git a/platform/darwin/app/PluginLayerExample.mm b/platform/darwin/app/PluginLayerExample.mm index 0cb01054d155..9aa8d60fc88f 100644 --- a/platform/darwin/app/PluginLayerExample.mm +++ b/platform/darwin/app/PluginLayerExample.mm @@ -7,15 +7,17 @@ @implementation PluginLayerExample +(MLNPluginLayerCapabilities *)layerCapabilities { MLNPluginLayerCapabilities *tempResult = [[MLNPluginLayerCapabilities alloc] init]; - tempResult.layerID = @"plugin-layer-test"; + tempResult.layerID = @"hudhud::gltf-model-layer"; tempResult.requiresPass3D = YES; + tempResult.supportsReadingTileFeatures = YES; return tempResult; } // The overrides --(void)onRenderLayer { - NSLog(@"PluginLayerExample: On Render Layer"); +-(void)onRenderLayer:(MLNMapView *)mapView + renderEncoder:(id)renderEncoder { + // NSLog(@"PluginLayerExample: On Render Layer"); } @@ -23,8 +25,56 @@ -(void)onUpdateLayer { } +//-(void)onBucketLoaded:(MLNRawBucket *)bucket { +// +//} + -(void)onUpdateLayerProperties:(NSDictionary *)layerProperties { - // NSLog(@"Layer Properties: %@", layerProperties); + // NSLog(@"Layer Properties: %@", layerProperties); +} + +-(void)featureLoaded:(MLNPluginLayerTileFeature *)tileFeature { + // NSLog(@"Tile Feature Properties: %@", tileFeature.featureProperties); + + for (NSValue *v in tileFeature.featureCoordinates) { + + +// NSValue *value = [NSValue valueWithBytes:&c objCType:@encode(CLLocationCoordinate2D)]; +// [featureCoordinates addObject:value]; + + CLLocationCoordinate2D coord; + [v getValue:&coord]; + + } +} + +-(void)featureUnloaded:(MLNPluginLayerTileFeature *)tileFeature { + // NSLog(@"Tile Features Unloaded: %@", tileFeature.featureProperties); + +} + + +- (void)onFeatureLoaded:(MLNPluginLayerTileFeature *)tileFeature { + + [self featureLoaded:tileFeature]; + +} + +/// Called when a set of features are loaded from the tile +- (void)onFeatureCollectionLoaded:(MLNPluginLayerTileFeatureCollection *)tileFeatureCollection { + //NSLog(@"Feature Collection Loaded for tile: %@", tileFeatureCollection.tileID); + for (MLNPluginLayerTileFeature *feature in tileFeatureCollection.features) { + [self featureLoaded:feature]; + } + +} + +/// Called when a set of features are unloaded because the tile goes out of scene/etc +- (void)onFeatureCollectionUnloaded:(MLNPluginLayerTileFeatureCollection *)tileFeatureCollection { + //NSLog(@"Feature Collection Unloaded for tile: %@", tileFeatureCollection.tileID); + for (MLNPluginLayerTileFeature *feature in tileFeatureCollection.features) { + [self featureUnloaded:feature]; + } } @end diff --git a/platform/darwin/src/MLNPluginLayer.h b/platform/darwin/src/MLNPluginLayer.h index bc4962324831..7fb38a34338c 100644 --- a/platform/darwin/src/MLNPluginLayer.h +++ b/platform/darwin/src/MLNPluginLayer.h @@ -44,11 +44,20 @@ MLN_EXPORT @interface MLNPluginLayerTileFeature : NSObject +// This is the unique feature ID in the tile source if applicable. Can be empty +@property NSString *featureID; @property NSDictionary *featureProperties; @property NSArray *featureCoordinates; @end +@interface MLNPluginLayerTileFeatureCollection : NSObject + +@property NSArray *features; +@property NSString *tileID; // z,x,y + +@end + typedef enum { MLNPluginLayerTileKindGeometry, MLNPluginLayerTileKindRaster, @@ -117,6 +126,16 @@ MLN_EXPORT /// Called when a feature is loaded from the tile - (void)onFeatureLoaded:(MLNPluginLayerTileFeature *)tileFeature; +/// Called when a set of features are loaded from the tile +/* + TODO: Think about returning that this layer doesn't care about this feature collection via a bool/etc and then + the underlying layer won't have to track this collection. + */ +- (void)onFeatureCollectionLoaded:(MLNPluginLayerTileFeatureCollection *)tileFeatureCollection; + +/// Called when a set of features are unloaded because the tile goes out of scene/etc +- (void)onFeatureCollectionUnloaded:(MLNPluginLayerTileFeatureCollection *)tileFeatureCollection; + /// Added to a map view - (void)didMoveToMapView:(MLNMapView *)mapView; diff --git a/platform/darwin/src/MLNPluginLayer.mm b/platform/darwin/src/MLNPluginLayer.mm index 712552d9f39d..73327779d8b2 100644 --- a/platform/darwin/src/MLNPluginLayer.mm +++ b/platform/darwin/src/MLNPluginLayer.mm @@ -4,6 +4,10 @@ @implementation MLNPluginLayerTileFeature @end +@implementation MLNPluginLayerTileFeatureCollection + +@end + @implementation MLNPluginLayerProperty +(MLNPluginLayerProperty *)propertyWithName:(NSString *)propertyName @@ -76,6 +80,17 @@ - (void)onFeatureLoaded:(MLNPluginLayerTileFeature *)tileFeature { // Base class does nothing } +// If the layer properties indicate that this layer has a the ability to intercept +// features, then this method will be called when a feature is loaded +- (void)onFeatureCollectionLoaded:(MLNPluginLayerTileFeatureCollection *)tileFeatureCollection { + // Base class does nothing +} + +/// Called when a set of features are unloaded because the tile goes out of scene/etc +- (void)onFeatureCollectionUnloaded:(MLNPluginLayerTileFeatureCollection *)tileFeatureCollection { + // Base class does nothing +} + /// Added to a map view - (void)didMoveToMapView:(MLNMapView *)mapView { diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index eab051c8bc1b..38faabadb6ba 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -7653,6 +7653,44 @@ - (void)triggerRepaint _mbglMap->triggerRepaint(); } +-(MLNPluginLayerTileFeature *)featureFromCore:(std::shared_ptr)feature { + + MLNPluginLayerTileFeature *tempResult = [[MLNPluginLayerTileFeature alloc] init]; + + NSMutableDictionary *tileProperties = [NSMutableDictionary dictionary]; + for (auto p: feature->_featureProperties) { + NSString *key = [NSString stringWithUTF8String:p.first.c_str()]; + NSString *value = [NSString stringWithUTF8String:p.second.c_str()]; + [tileProperties setObject:value forKey:key]; + } + + tempResult.featureProperties = [NSDictionary dictionaryWithDictionary:tileProperties]; + + NSMutableArray *featureCoordinates = [NSMutableArray array]; + for (auto & coordinateCollection: feature->_featureCoordinates) { + + for (auto & coordinate: coordinateCollection._coordinates) { + CLLocationCoordinate2D c = CLLocationCoordinate2DMake(coordinate._lat, coordinate._lon); + NSValue *value = [NSValue valueWithBytes:&c objCType:@encode(CLLocationCoordinate2D)]; + [featureCoordinates addObject:value]; + } + + } + // TODO: Need to figure out how we're going to handle multiple coordinate groups/etc + if ([featureCoordinates count] > 0) { + tempResult.featureCoordinates = [NSArray arrayWithArray:featureCoordinates]; + } + + tempResult.featureID = [NSString stringWithUTF8String:feature->_featureID.c_str()]; + + return tempResult; +} + +-(NSString *)tileIDToString:(mbgl::OverscaledTileID &)tileID { + NSString *tempResult = [NSString stringWithFormat:@"%i,%i,%i", tileID.canonical.z, tileID.canonical.x, tileID.canonical.y]; + return tempResult; +} + /** Adds a plug-in layer that is external to this library */ @@ -7678,8 +7716,11 @@ -(void)addPluginLayerType:(Class)pluginLayerClass { } - tileKind = mbgl::style::LayerTypeInfo::TileKind::Geometry; - source = mbgl::style::LayerTypeInfo::Source::Required; + // If we read tile features, then we need to set these things + if (capabilities.supportsReadingTileFeatures) { + tileKind = mbgl::style::LayerTypeInfo::TileKind::Geometry; + source = mbgl::style::LayerTypeInfo::Source::Required; + } auto factory = std::make_unique(layerType, source, @@ -7692,7 +7733,7 @@ -(void)addPluginLayerType:(Class)pluginLayerClass { __weak MLNMapView *weakMapView = self; Class layerClass = pluginLayerClass; - factory->_supportsRawBuckets = capabilities.supportsReadingTileFeatures; + factory->_supportsFeatureCollectionBuckets = capabilities.supportsReadingTileFeatures; factory->setOnLayerCreatedEvent([layerClass, weakMapView, pluginLayerClass](mbgl::style::PluginLayer *pluginLayer) { //NSLog(@"Creating Plugin Layer: %@", layerClass); @@ -7788,41 +7829,65 @@ -(void)addPluginLayerType:(Class)pluginLayerClass { // If this layer can read tile features, then setup that lambda if (capabilities.supportsReadingTileFeatures) { - pluginLayerImpl->setFeatureLoadedFunction([weakPlugInLayer](const std::shared_ptr feature) { + pluginLayerImpl->setFeatureLoadedFunction([weakPlugInLayer, weakMapView](const std::shared_ptr feature) { @autoreleasepool { - MLNPluginLayerTileFeature *tileFeature = [[MLNPluginLayerTileFeature alloc] init]; + MLNPluginLayerTileFeature *tileFeature = [weakMapView featureFromCore:feature]; - NSMutableDictionary *tileProperties = [NSMutableDictionary dictionary]; - for (auto p: feature->_featureProperties) { - NSString *key = [NSString stringWithUTF8String:p.first.c_str()]; - NSString *value = [NSString stringWithUTF8String:p.second.c_str()]; - [tileProperties setObject:value forKey:key]; - } + [weakPlugInLayer onFeatureLoaded:tileFeature]; + + } + + }); + + + pluginLayerImpl->setFeatureCollectionLoadedFunction([weakPlugInLayer, weakMapView](const std::shared_ptr featureCollection) { + + @autoreleasepool { - tileFeature.featureProperties = [NSDictionary dictionaryWithDictionary:tileProperties]; + MLNPluginLayerTileFeatureCollection *collection = [[MLNPluginLayerTileFeatureCollection alloc] init]; - NSMutableArray *featureCoordinates = [NSMutableArray array]; - for (auto & coordinateCollection: feature->_featureCoordinates) { - - for (auto & coordinate: coordinateCollection._coordinates) { - CLLocationCoordinate2D c = CLLocationCoordinate2DMake(coordinate._lat, coordinate._lon); - NSValue *value = [NSValue valueWithBytes:&c objCType:@encode(CLLocationCoordinate2D)]; - [featureCoordinates addObject:value]; - } - - } - // TODO: Need to figure out how we're going to handle multiple coordinate groups/etc - if ([featureCoordinates count] > 0) { - tileFeature.featureCoordinates = [NSArray arrayWithArray:featureCoordinates]; + // Add the features + NSMutableArray *featureList = [NSMutableArray arrayWithCapacity:featureCollection->_features.size()]; + for (auto f: featureCollection->_features) { + [featureList addObject:[weakMapView featureFromCore:f]]; } + collection.features = [NSArray arrayWithArray:featureList]; + collection.tileID = [weakMapView tileIDToString:featureCollection->_featureCollectionTileID]; + + + [weakPlugInLayer onFeatureCollectionLoaded:collection]; + + } + + }); + + pluginLayerImpl->setFeatureCollectionUnloadedFunction([weakPlugInLayer, weakMapView](const std::shared_ptr featureCollection) { + + @autoreleasepool { + // TODO: Map these collections to local vars and maybe don't keep recreating it - [weakPlugInLayer onFeatureLoaded:tileFeature]; + MLNPluginLayerTileFeatureCollection *collection = [[MLNPluginLayerTileFeatureCollection alloc] init]; + + // Add the features + NSMutableArray *featureList = [NSMutableArray arrayWithCapacity:featureCollection->_features.size()]; + for (auto f: featureCollection->_features) { + [featureList addObject:[weakMapView featureFromCore:f]]; + } + collection.features = [NSArray arrayWithArray:featureList]; + collection.tileID = [weakMapView tileIDToString:featureCollection->_featureCollectionTileID]; + + [weakPlugInLayer onFeatureCollectionUnloaded:collection]; } }); + + + + + } }); diff --git a/src/mbgl/plugin/feature_collection.cpp b/src/mbgl/plugin/feature_collection.cpp new file mode 100644 index 000000000000..c5d067494a8a --- /dev/null +++ b/src/mbgl/plugin/feature_collection.cpp @@ -0,0 +1,8 @@ +// +// feature_collection.cpp +// App +// +// Created by Malcolm Toon on 7/15/25. +// + +#include "feature_collection.hpp" diff --git a/src/mbgl/plugin/feature_collection.hpp b/src/mbgl/plugin/feature_collection.hpp new file mode 100644 index 000000000000..6b170d321e09 --- /dev/null +++ b/src/mbgl/plugin/feature_collection.hpp @@ -0,0 +1,74 @@ +// +// feature_collection.hpp +// App +// +// Created by Malcolm Toon on 7/15/25. +// + +#ifndef feature_collection_hpp +#define feature_collection_hpp + +#include + +#include +#include +#include +#include + +namespace mbgl { + +namespace plugin { + +//using FillBinders = PaintPropertyBinders; +//using FillLayoutVertex = gfx::Vertex>; + +class FeatureCoordinate { +public: + FeatureCoordinate(double lat, double lon) : _lat(lat), _lon(lon) { + + } + double _lat = 0; + double _lon = 0; + double _tileX = 0; // Tile coord + double _tileY = 0; // Tile coord +}; + +// This is a list of coordinates. Broken out into it's own class because +// a raw bucket feature can have an array of these +class FeatureCoordinateCollection { +public: + std::vector _coordinates; +}; + +class Feature { +public: + Feature() {}; + enum class FeatureType { + FeatureTypeUnknown, + FeatureTypePoint, + FeatureTypeLine, + FeatureTypePolygon + }; + FeatureType _featureType = FeatureType::FeatureTypeUnknown; + std::map _featureProperties; + std::vector _featureCoordinates; + std::string _featureID; // Unique id from the data source for this + +}; + +class FeatureCollection { +public: + FeatureCollection(OverscaledTileID tileID): _featureCollectionTileID(tileID) {}; + std::vector> _features; + + // TODO: Open question about this.. should feature collections be tied to tile id? + // TODO: Question: Is overscaled the right thing or just canonical? + OverscaledTileID _featureCollectionTileID; +}; + + +} + +} + +#endif /* feature_collection_hpp */ diff --git a/src/mbgl/plugin/raw_bucket.cpp b/src/mbgl/plugin/feature_collection_bucket.cpp similarity index 58% rename from src/mbgl/plugin/raw_bucket.cpp rename to src/mbgl/plugin/feature_collection_bucket.cpp index 9322cc4b3e8a..4028ae214e38 100644 --- a/src/mbgl/plugin/raw_bucket.cpp +++ b/src/mbgl/plugin/feature_collection_bucket.cpp @@ -8,20 +8,21 @@ #include #include #include - -#include "raw_bucket.hpp" +#include #include using namespace mbgl; -RawBucket::~RawBucket() { +FeatureCollectionBucket::~FeatureCollectionBucket() { } -RawBucket::RawBucket(const BucketParameters& bucketParameters, - const std::vector>& layers) { +FeatureCollectionBucket::FeatureCollectionBucket(const BucketParameters& bucketParameters, + const std::vector>& layers): +_tileID(bucketParameters.tileID) { _layers = layers; + _featureCollection = std::make_shared(bucketParameters.tileID); } void geometryToLatLon( @@ -46,30 +47,72 @@ void geometryToLatLon( lat = 180.0 / M_PI * (2.0 * atan(exp(mercY * M_PI)) - M_PI / 2.0); } -void RawBucket::addFeature(const GeometryTileFeature& tileFeature, +std::string toString(FeatureIdentifier & v) { + // auto v = toValue(value); + + // null_value_t, uint64_t, int64_t, double, std::string> + + std::string tempResult = ""; + auto ti = v.which(); + if (ti == 0) { + return tempResult; + } else if (ti == 1) { + tempResult = std::to_string(v.get()); + } else if (ti == 2) { + tempResult = std::to_string(v.get()); + } else if (ti == 3) { + tempResult = v.get(); + } + return tempResult; + /* + if (auto iVal = v.value().getInt()) { + std::string tempResult = std::to_string(*iVal); + output.append(tempResult); + } else if (auto uIVal = v.value().getUint()) { + std::string tempResult = std::to_string(*uIVal); + output.append(tempResult); + + } else if (auto s = v.value().getString()) { + output.append("\""); + output.append(s->c_str()); + output.append("\""); + + } else if (auto d = v.value().getDouble()) { + output.append(std::to_string(*d)); + } + */ + +} + +void FeatureCollectionBucket::addFeature(const GeometryTileFeature& tileFeature, const GeometryCollection& geometeryCollection, const mbgl::ImagePositions& imagePositions, const PatternLayerMap& patternLayerMap, std::size_t size, const CanonicalTileID& tileID) { - std::shared_ptr tempFeature = std::make_shared(); + std::shared_ptr tempFeature = std::make_shared(); + + auto featureID = tileFeature.getID(); + auto featureIDString = toString(featureID); + tempFeature->_featureID = featureIDString; + switch (tileFeature.getType()) { case FeatureType::Point: - std::cout << "Adding Point" << "\n"; - tempFeature->_featureType = RawBucketFeature::FeatureType::FeatureTypePoint; + //std::cout << "Adding Point" << "\n"; + tempFeature->_featureType = plugin::Feature::FeatureType::FeatureTypePoint; break; case FeatureType::Unknown: - std::cout << "Unknown Type Found\n"; + //std::cout << "Unknown Type Found\n"; break; case FeatureType::LineString: - std::cout << "LineString Type Found\n"; - tempFeature->_featureType = RawBucketFeature::FeatureType::FeatureTypeLine; + //std::cout << "LineString Type Found\n"; + tempFeature->_featureType = plugin::Feature::FeatureType::FeatureTypeLine; break; case FeatureType::Polygon: - std::cout << "Polygon Type Found\n"; - tempFeature->_featureType = RawBucketFeature::FeatureType::FeatureTypePolygon; + //std::cout << "Polygon Type Found\n"; + tempFeature->_featureType = plugin::Feature::FeatureType::FeatureTypePolygon; break; @@ -90,17 +133,17 @@ void RawBucket::addFeature(const GeometryTileFeature& tileFeature, } else if (auto s = value.getString()) { - std::cout << "Found String: " << name << ": " << *s << "\n"; + // std::cout << "Found String: " << name << ": " << *s << "\n"; tempFeature->_featureProperties[name] = *s; } else if (auto d = value.getDouble()) { - std::cout << "Found Double: " << name << ": " << *d << "\n"; + // std::cout << "Found Double: " << name << ": " << *d << "\n"; tempFeature->_featureProperties[name] = std::to_string(*d); } else if (auto b = value.getBool()) { - std::cout << "Found Bool: " << name << ": " << *b << "\n"; + // std::cout << "Found Bool: " << name << ": " << *b << "\n"; tempFeature->_featureProperties[name] = std::to_string(*b); } else if (auto a = value.getArray()) { - std::cout << "Found Array: " << name << ": " << *b << "\n"; + // std::cout << "Found Array: " << name << ": " << *b << "\n"; tempFeature->_featureProperties[name] = std::to_string(*b); } @@ -116,7 +159,7 @@ void RawBucket::addFeature(const GeometryTileFeature& tileFeature, for (const auto& g : geometeryCollection) { // g is GeometryCoordinates - RawBucketFeatureCoordinateCollection c; + plugin::FeatureCoordinateCollection c; for (std::size_t i = 0, len = g.size(); i < len; i++) { const GeometryCoordinate& p1 = g[i]; @@ -135,7 +178,7 @@ void RawBucket::addFeature(const GeometryTileFeature& tileFeature, double lon = 0; geometryToLatLon(p1, tileID.x, tileID.y, tileID.z, lat, lon); - c._coordinates.push_back(RawBucketFeatureCoordinate(lat, lon)); + c._coordinates.push_back(plugin::FeatureCoordinate(lat, lon)); } tempFeature->_featureCoordinates.push_back(c); @@ -161,25 +204,29 @@ void RawBucket::addFeature(const GeometryTileFeature& tileFeature, // } } - _features.push_back(tempFeature); + + _featureCollection->_features.push_back(tempFeature); + // _features.push_back(tempFeature); // std::cout << "Adding Feature Type: " << tileFeature.getType() << "\n"; } -bool RawBucket::hasData() const { - return true; +bool FeatureCollectionBucket::hasData() const { + return _featureCollection->_features.size() > 0; } -void RawBucket::upload(gfx::UploadPass&) { - +void FeatureCollectionBucket::upload(gfx::UploadPass&) { + std::cout << "FeatureCollectionBucket::upload\n"; + uploaded = true; } -float RawBucket::getQueryRadius(const RenderLayer&) const { +float FeatureCollectionBucket::getQueryRadius(const RenderLayer&) const { return 0; } -void RawBucket::update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) { - +void FeatureCollectionBucket::update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) { + std::cout << "FeatureCollectionBucket::update\n"; + } diff --git a/src/mbgl/plugin/raw_bucket.hpp b/src/mbgl/plugin/feature_collection_bucket.hpp similarity index 66% rename from src/mbgl/plugin/raw_bucket.hpp rename to src/mbgl/plugin/feature_collection_bucket.hpp index 507667375d23..c78a5a811a39 100644 --- a/src/mbgl/plugin/raw_bucket.hpp +++ b/src/mbgl/plugin/feature_collection_bucket.hpp @@ -7,53 +7,48 @@ #include #include #include +#include #include -namespace mbgl { +/* + + Open Questions + + + * Should we load up a vector of these RawFeatures by tile? + * How does that interop with the render layer's update flow + * Should the call back from render layer be more of a batch thing at that update stage? + * Should there be a callback when a tile or collection of these features go out of scope? + * Should the concept of managing arrays of features be something done by the core or just + hand off the features to the plug-in layer and let it do it's thing or have the option for both? + + * How do we get to the osm id of features in the stream? Is that tileFeature.getID()? + * Is there already a set of classes or a paradigm out there that could be used to represent the + feature / feature geometry? + * What are the "binders"? + + + Thoughts + * Possibly have ability to keep tile coordinates using some kind flag + + + + */ -class BucketParameters; -class RenderFillLayer; -//using FillBinders = PaintPropertyBinders; -//using FillLayoutVertex = gfx::Vertex>; -class RawBucketFeatureCoordinate { -public: - RawBucketFeatureCoordinate(double lat, double lon) : _lat(lat), _lon(lon) { - - } - double _lat = 0; - double _lon = 0; -}; - -// This is a list of coordinates. Broken out into it's own class because -// a raw bucket feature can have an array of these -class RawBucketFeatureCoordinateCollection { -public: - std::vector _coordinates; -}; +namespace mbgl { -class RawBucketFeature { -public: - RawBucketFeature() {}; - enum class FeatureType { - FeatureTypeUnknown, - FeatureTypePoint, - FeatureTypeLine, - FeatureTypePolygon - }; - FeatureType _featureType = FeatureType::FeatureTypeUnknown; - std::map _featureProperties; - std::vector _featureCoordinates; -}; +class BucketParameters; +class RenderFillLayer; -class RawBucket final : public Bucket { +class FeatureCollectionBucket final : public Bucket { public: - ~RawBucket() override; + ~FeatureCollectionBucket() override; //using PossiblyEvaluatedLayoutProperties = style::FillLayoutProperties::PossiblyEvaluated; - RawBucket(const BucketParameters&, const std::vector>&); + FeatureCollectionBucket(const BucketParameters&, const std::vector>&); void addFeature(const GeometryTileFeature&, const GeometryCollection&, @@ -70,8 +65,12 @@ class RawBucket final : public Bucket { void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override; + // The tile ID + OverscaledTileID _tileID; + // Array of features - std::vector> _features; + std::shared_ptr _featureCollection = nullptr; + //std::vector> _features; std::vector> _layers; diff --git a/src/mbgl/plugin/plugin_layer.hpp b/src/mbgl/plugin/plugin_layer.hpp index 7b5ae19f349b..0767491022c5 100644 --- a/src/mbgl/plugin/plugin_layer.hpp +++ b/src/mbgl/plugin/plugin_layer.hpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace mbgl { @@ -31,8 +32,10 @@ class PluginLayer final : public Layer { using OnRenderLayer = std::function; using OnUpdateLayer = std::function; using OnUpdateLayerProperties = std::function; - using OnFeatureLoaded = std::function feature)>; - + using OnFeatureLoaded = std::function feature)>; + using OnFeatureCollectionLoaded = std::function featureCollection)>; + using OnFeatureCollectionUnloaded = std::function featureCollection)>; + void* _platformReference = nullptr; protected: diff --git a/src/mbgl/plugin/plugin_layer_factory.cpp b/src/mbgl/plugin/plugin_layer_factory.cpp index 4d68fad43fb3..1354113065e8 100644 --- a/src/mbgl/plugin/plugin_layer_factory.cpp +++ b/src/mbgl/plugin/plugin_layer_factory.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include @@ -150,8 +150,14 @@ std::unique_ptr PluginLayerFactory::createLayer(const std::string& } } - auto source = getSource(value); - std::string sourceStr = source.has_value() ? source.value() : "source"; + std::string sourceStr = "pluginLayerNoSource"; + if (_supportsFeatureCollectionBuckets) { + auto source = getSource(value); + if (source.has_value()) { + sourceStr = source.value(); + } + } + auto tempResult = std::unique_ptr(new (std::nothrow) style::PluginLayer(id, sourceStr, _layerTypeInfo, layerProperties @@ -174,8 +180,8 @@ std::unique_ptr PluginLayerFactory::createLayer(const std::string& std::unique_ptr PluginLayerFactory::createBucket( [[maybe_unused]] const BucketParameters& parameters, [[maybe_unused]] const std::vector>& layers) noexcept { - if (_supportsRawBuckets) { - return std::make_unique(parameters, layers); + if (_supportsFeatureCollectionBuckets) { + return std::make_unique(parameters, layers); } return nullptr; } diff --git a/src/mbgl/plugin/plugin_layer_factory.hpp b/src/mbgl/plugin/plugin_layer_factory.hpp index d35c5ca8bc48..7d75b7681c45 100644 --- a/src/mbgl/plugin/plugin_layer_factory.hpp +++ b/src/mbgl/plugin/plugin_layer_factory.hpp @@ -24,7 +24,7 @@ class PluginLayerFactory : public LayerFactory { mbgl::style::LayerTypeInfo::TileKind tileKind); // Set to false, but if the caller wants to support on features loaded, then set this to true - bool _supportsRawBuckets = false; + bool _supportsFeatureCollectionBuckets = false; using OnLayerCreatedEvent = std::function; void setOnLayerCreatedEvent(OnLayerCreatedEvent onLayerCreated) { _onLayerCreated = onLayerCreated; } diff --git a/src/mbgl/plugin/plugin_layer_impl.hpp b/src/mbgl/plugin/plugin_layer_impl.hpp index 6b58c42f8e7f..ee4d3982230f 100644 --- a/src/mbgl/plugin/plugin_layer_impl.hpp +++ b/src/mbgl/plugin/plugin_layer_impl.hpp @@ -102,6 +102,14 @@ class PluginLayer::Impl : public Layer::Impl { void setFeatureLoadedFunction(OnFeatureLoaded featureLoadedFunction) { _featureLoadedFunction = featureLoadedFunction; } + + void setFeatureCollectionLoadedFunction(OnFeatureCollectionLoaded featureCollectionLoadedFunction) { + _featureCollectionLoadedFunction = featureCollectionLoadedFunction; + } + + void setFeatureCollectionUnloadedFunction(OnFeatureCollectionUnloaded featureCollectionUnloadedFunction) { + _featureCollectionUnloadedFunction = featureCollectionUnloadedFunction; + } //! The property manager handles all of the custom properties for this layer type / instance PluginLayerPropertyManager _propertyManager; @@ -120,6 +128,12 @@ class PluginLayer::Impl : public Layer::Impl { //! Optional: Called when feature is loaded OnFeatureLoaded _featureLoadedFunction; + //! Optional: Called when a feature collection is loaded + OnFeatureCollectionLoaded _featureCollectionLoadedFunction; + + //! Optional: Called when a feature colleciton is unloaded from the scene (tile goes out of scene/etc) + OnFeatureCollectionUnloaded _featureCollectionUnloadedFunction; + private: LayerTypeInfo _layerTypeInfo; std::string _layerProperties; diff --git a/src/mbgl/plugin/plugin_layer_render.cpp b/src/mbgl/plugin/plugin_layer_render.cpp index 5021fa33f82f..2a3eae53e2bd 100644 --- a/src/mbgl/plugin/plugin_layer_render.cpp +++ b/src/mbgl/plugin/plugin_layer_render.cpp @@ -14,8 +14,13 @@ #include #include +// TODO: Remove #include + +#include +#include + using namespace mbgl; namespace mbgl { @@ -85,6 +90,166 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis [[maybe_unused]] const std::shared_ptr& updateParameters, [[maybe_unused]] const RenderTree& renderTree, [[maybe_unused]] UniqueChangeRequestVec& changes) { + + auto pluginLayer = static_cast(*baseImpl); + + std::vector removedTiles; + bool removeAllTiles = ((renderTiles == nullptr) || (renderTiles->empty())); + + // TODO: Remove + static int passCount = 0; + passCount++; + if (removeAllTiles) { + std::cout << passCount << ": Remove All Tiles\n"; + } + + // Get list of tiles to remove and then remove them + for (auto currentCollection: _featureCollectionByTile) { + if (removeAllTiles || !hasRenderTile(currentCollection.first)) { + removedTiles.push_back(currentCollection.first); + } + } + if (removedTiles.size() > 0) { + for (auto tileID: removedTiles) { + auto featureCollection = _featureCollectionByTile[tileID]; + if (pluginLayer._featureCollectionUnloadedFunction) { + pluginLayer._featureCollectionUnloadedFunction(featureCollection); + } + // TODO: Remove this logging + std::cout << passCount << ": Removing Feature Collection for Tile: " << (int)tileID.canonical.z << "," << tileID.canonical.x << "," << tileID.canonical.y << "\n"; + _featureCollectionByTile.erase(tileID); + } + } + + + if (renderTiles) { + if (!renderTiles->empty()) { + + auto drawPass = RenderPass::Pass3D; + + // If we're reading feature collections, go through + // and notify the plugin of any new feature collections + for (const RenderTile& tile : *renderTiles) { + const auto& tileID = tile.getOverscaledTileID(); + + if (!hasRenderTile(tileID)) { + std::cout << passCount << ": Tile was there and not anymore\n"; + } + + // TODO: Remove +// if ((tileID.canonical.x == 1289) && (tileID.canonical.y == 879)) { +// std::cout << "Found tile\n"; +// } + + const auto* optRenderData = getRenderDataForPass(tile, drawPass); + if (!optRenderData || !optRenderData->bucket || !optRenderData->bucket->hasData()) { + removeTile(drawPass, tileID); + continue; + } + const auto& renderData = *optRenderData; + auto& bucket = static_cast(*renderData.bucket); + // TODO: Remove + //std::cout << "Found Bucket\n"; + auto featureCollection = bucket._featureCollection; + if (featureCollection == nullptr) { + continue; + } + + // See if we already have this tile'a feature collection + if (_featureCollectionByTile.contains(tileID)) { + continue; + } + + _featureCollectionByTile[tileID] = featureCollection; + +// static_cast(*baseImpl); +// auto layer = static_cast(*renderData.layerProperties->baseImpl); + if (pluginLayer._featureCollectionLoadedFunction) { + if (featureCollection != nullptr) { + pluginLayer._featureCollectionLoadedFunction(featureCollection); + + // TODO: Remove logging + std::cout << passCount << ": Adding Feature Collection for Tile: " << (int)tileID.canonical.z << "," << tileID.canonical.x << "," << tileID.canonical.y << "\n"; + + } + } + + /* + + const auto prevBucketID = getRenderTileBucketID(tileID); + if (prevBucketID != util::SimpleIdentity::Empty && prevBucketID != bucket.getID()) { + // This tile was previously set up from a different bucket, drop and re-create any drawables for it. + removeTile(drawPass, tileID); + } + setRenderTileBucketID(tileID, bucket.getID()); + */ + + } + + } + + } + + /* + if (!renderTiles || renderTiles->empty() || passes == RenderPass::None) { +// removeAllDrawables(); + return; + } + + // Set up a layer group + if (!layerGroup) { + if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, + 64, // initialCapacity= + getID())) { + setLayerGroup(std::move(layerGroup_), changes); + } else { + return; + } + } + + auto* tileLayerGroup = static_cast(layerGroup.get()); + +// const auto& evaluated = static_cast(*evaluatedProperties).evaluated; + + constexpr auto drawPass = RenderPass::Translucent; + + for (const RenderTile& tile : *renderTiles) { + const auto& tileID = tile.getOverscaledTileID(); + + const auto* optRenderData = getRenderDataForPass(tile, drawPass); + if (!optRenderData || !optRenderData->bucket || !optRenderData->bucket->hasData()) { + removeTile(drawPass, tileID); + continue; + } + + const auto& renderData = *optRenderData; + auto& bucket = static_cast(*renderData.bucket); + + const auto prevBucketID = getRenderTileBucketID(tileID); + if (prevBucketID != util::SimpleIdentity::Empty && prevBucketID != bucket.getID()) { + // This tile was previously set up from a different bucket, drop and re-create any drawables for it. + removeTile(drawPass, tileID); + } + setRenderTileBucketID(tileID, bucket.getID()); + } + + */ + + + + + + + + + + + + + + + + // create layer group if (!layerGroup) { if (auto layerGroup_ = context.createLayerGroup(layerIndex, /*initialCapacity=*/1, getID())) { @@ -128,6 +293,15 @@ void RenderPluginLayer::render(PaintParameters& paintParameters) { } void RenderPluginLayer::prepare(const LayerPrepareParameters& layerParameters) { + + // This check is here because base prepare will assert on these and crash + if (layerParameters.source != nullptr) { + if (layerParameters.source->isEnabled()) { + RenderLayer::prepare(layerParameters); + } + } + + if (_updateFunction) { _updateFunction(layerParameters); } @@ -163,6 +337,20 @@ void RenderPluginLayer::evaluate(const PropertyEvaluationParameters& parameters) std::string jsonProperties = pm.propertiesAsJSON(); i->_updateLayerPropertiesFunction(jsonProperties); + + + auto properties = makeMutable(staticImmutableCast(baseImpl)); + passes = RenderPass::Pass3D; +// passes = RenderPass::Pass3D; (evaluated.get().constantOr(1.0) > 0 && +// evaluated.get().constantOr(Color::black()).a > 0 && +// evaluated.get().constantOr(1.0) > 0) +// ? RenderPass::Translucent +// : RenderPass::None; + properties->renderPasses = mbgl::underlying_type(passes); + evaluatedProperties = std::move(properties); + + + } bool RenderPluginLayer::hasTransition() const { @@ -188,7 +376,8 @@ void RenderPluginLayer::layerChanged([[maybe_unused]] const TransitionParameters /// Remove all drawables for the tile from the layer group /// @return The number of drawables actually removed. -std::size_t RenderPluginLayer::removeTile([[maybe_unused]] RenderPass, [[maybe_unused]] const OverscaledTileID&) { +std::size_t RenderPluginLayer::removeTile([[maybe_unused]] RenderPass renderPass, + [[maybe_unused]] const OverscaledTileID& tileID) { return 0; } diff --git a/src/mbgl/plugin/plugin_layer_render.hpp b/src/mbgl/plugin/plugin_layer_render.hpp index cc2ea2db7a6e..847aea6003f8 100644 --- a/src/mbgl/plugin/plugin_layer_render.hpp +++ b/src/mbgl/plugin/plugin_layer_render.hpp @@ -5,6 +5,7 @@ #include #include +#include #include namespace mbgl { @@ -67,6 +68,9 @@ class RenderPluginLayer final : public RenderLayer { style::PluginLayer::OnUpdateLayer _updateFunction = nullptr; style::PluginLayer::OnUpdateLayerProperties _updateLayerPropertiesFunction = nullptr; + + std::map> _featureCollectionByTile; + }; } // namespace mbgl diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index 127355fa769d..9805979f524a 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -373,11 +373,6 @@ std::unique_ptr RenderOrchestrator::createRenderTree( for (std::size_t index = 0; index < orderedLayers.size(); ++index) { RenderLayer& layer = orderedLayers[index]; const auto* layerInfo = layer.baseImpl->getTypeInfo(); - std::string s1(layerInfo->type); - //std::cout << " -> " << s1 << "\n"; -// if (s1 == "hudhud::gltf-model-layer") { -// std::cout << "Found plugin\n"; -// } const bool layerIsVisible = layer.baseImpl->visibility != style::VisibilityType::None; const bool zoomFitsLayer = layer.supportsZoom(zoomHistory.lastZoom); renderTreeParameters->has3D |= (layerInfo->pass3d == LayerTypeInfo::Pass3D::Required); diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 1d71c8b99084..6d6c6f7025d2 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -35,7 +35,7 @@ LayerRenderData* GeometryTile::LayoutResult::getLayerRenderData(const style::Lay return nullptr; } LayerRenderData& result = it->second; - if (result.layerProperties->baseImpl->getTypeInfo() != layerImpl.getTypeInfo()) { + if (!layerTypeInfoEquals(result.layerProperties->baseImpl->getTypeInfo(), layerImpl.getTypeInfo())) { // Layer data might be outdated, see issue #12432. return nullptr; } From 4e2f4e692226dc136f973024fdb02fdf8440557a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Fri, 25 Jul 2025 10:48:48 -0400 Subject: [PATCH 114/221] Updates --- platform/darwin/app/PluginLayerExample.mm | 6 +++--- platform/darwin/app/PluginLayerTestStyle.json | 7 +++++++ platform/ios/app/MBXViewController.mm | 11 ++++++----- src/mbgl/plugin/plugin_layer_render.cpp | 13 ++++++++++--- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/platform/darwin/app/PluginLayerExample.mm b/platform/darwin/app/PluginLayerExample.mm index 9aa8d60fc88f..16df1dd440da 100644 --- a/platform/darwin/app/PluginLayerExample.mm +++ b/platform/darwin/app/PluginLayerExample.mm @@ -7,7 +7,7 @@ @implementation PluginLayerExample +(MLNPluginLayerCapabilities *)layerCapabilities { MLNPluginLayerCapabilities *tempResult = [[MLNPluginLayerCapabilities alloc] init]; - tempResult.layerID = @"hudhud::gltf-model-layer"; + tempResult.layerID = @"maplibre::filter_features"; tempResult.requiresPass3D = YES; tempResult.supportsReadingTileFeatures = YES; return tempResult; @@ -17,7 +17,7 @@ +(MLNPluginLayerCapabilities *)layerCapabilities { // The overrides -(void)onRenderLayer:(MLNMapView *)mapView renderEncoder:(id)renderEncoder { - // NSLog(@"PluginLayerExample: On Render Layer"); + //NSLog(@"PluginLayerExample: On Render Layer"); } @@ -34,7 +34,7 @@ -(void)onUpdateLayerProperties:(NSDictionary *)layerProperties { } -(void)featureLoaded:(MLNPluginLayerTileFeature *)tileFeature { - // NSLog(@"Tile Feature Properties: %@", tileFeature.featureProperties); + NSLog(@"Tile Feature (id:%@) Properties: %@", tileFeature.featureID, tileFeature.featureProperties); for (NSValue *v in tileFeature.featureCoordinates) { diff --git a/platform/darwin/app/PluginLayerTestStyle.json b/platform/darwin/app/PluginLayerTestStyle.json index 25ce408bd77f..826236d2a135 100644 --- a/platform/darwin/app/PluginLayerTestStyle.json +++ b/platform/darwin/app/PluginLayerTestStyle.json @@ -583,6 +583,13 @@ ] } }, + { "id": "centroid-features", + "type": "maplibre::filter_features", + "source": "maplibre", + "source-layer": "centroids", + "maxzoom": 24, + "minzoom": 1 + }, { "id": "crimea-fill", "type": "fill", diff --git a/platform/ios/app/MBXViewController.mm b/platform/ios/app/MBXViewController.mm index 4c13a767ea51..3e1a02568f11 100644 --- a/platform/ios/app/MBXViewController.mm +++ b/platform/ios/app/MBXViewController.mm @@ -2332,17 +2332,18 @@ - (void)setStyles - - /// Style that does not require an `apiKey` nor any further configuration - [self.styleNames addObject:@"MapLibre Basic"]; - [self.styleURLs addObject:[NSURL URLWithString:@"https://demotiles.maplibre.org/style.json"]]; - /// This is hte same style as above but copied locally and the three instances of the metal plug-in layer added to the style /// Look for "type": "plugin-layer-metal-rendering" in the PluginLayerTestStyle.json for an example of how the layer is defined [self.styleNames addObject:@"MapLibre Basic - Local With Plugin"]; NSURL *url = [[NSBundle mainBundle] URLForResource:@"PluginLayerTestStyle.json" withExtension:nil]; [self.styleURLs addObject:url]; + + /// Style that does not require an `apiKey` nor any further configuration + [self.styleNames addObject:@"MapLibre Basic"]; + [self.styleURLs addObject:[NSURL URLWithString:@"https://demotiles.maplibre.org/style.json"]]; + + /// Add MapLibre Styles if an `apiKey` exists NSString* apiKey = [MLNSettings apiKey]; if (apiKey.length) diff --git a/src/mbgl/plugin/plugin_layer_render.cpp b/src/mbgl/plugin/plugin_layer_render.cpp index 2a3eae53e2bd..e36e6ef2208e 100644 --- a/src/mbgl/plugin/plugin_layer_render.cpp +++ b/src/mbgl/plugin/plugin_layer_render.cpp @@ -16,7 +16,7 @@ // TODO: Remove #include - +// #define C_LOG_TILES 1 #include #include @@ -97,12 +97,14 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis bool removeAllTiles = ((renderTiles == nullptr) || (renderTiles->empty())); // TODO: Remove +#ifdef C_LOG_TILES static int passCount = 0; passCount++; if (removeAllTiles) { std::cout << passCount << ": Remove All Tiles\n"; } - +#endif + // Get list of tiles to remove and then remove them for (auto currentCollection: _featureCollectionByTile) { if (removeAllTiles || !hasRenderTile(currentCollection.first)) { @@ -115,8 +117,10 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis if (pluginLayer._featureCollectionUnloadedFunction) { pluginLayer._featureCollectionUnloadedFunction(featureCollection); } +#ifdef C_LOG_TILES // TODO: Remove this logging std::cout << passCount << ": Removing Feature Collection for Tile: " << (int)tileID.canonical.z << "," << tileID.canonical.x << "," << tileID.canonical.y << "\n"; +#endif _featureCollectionByTile.erase(tileID); } } @@ -133,7 +137,9 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis const auto& tileID = tile.getOverscaledTileID(); if (!hasRenderTile(tileID)) { +#ifdef C_LOG_TILES std::cout << passCount << ": Tile was there and not anymore\n"; +#endif } // TODO: Remove @@ -167,9 +173,10 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis if (pluginLayer._featureCollectionLoadedFunction) { if (featureCollection != nullptr) { pluginLayer._featureCollectionLoadedFunction(featureCollection); - +#ifdef C_LOG_TILES // TODO: Remove logging std::cout << passCount << ": Adding Feature Collection for Tile: " << (int)tileID.canonical.z << "," << tileID.canonical.x << "," << tileID.canonical.y << "\n"; +#endif } } From 20b79859276d4585ae66369264eddbead85a0477 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 25 Jul 2025 14:52:17 +0000 Subject: [PATCH 115/221] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- platform/darwin/app/PluginLayerExample.mm | 16 +- platform/darwin/src/MLNPluginLayer.h | 6 +- platform/darwin/src/MLNPluginLayer.mm | 4 +- platform/ios/app/MBXViewController.mm | 2 +- platform/ios/src/MLNMapView.mm | 60 +++---- src/mbgl/plugin/feature_collection.hpp | 21 ++- src/mbgl/plugin/feature_collection_bucket.cpp | 170 ++++++++---------- src/mbgl/plugin/feature_collection_bucket.hpp | 26 ++- src/mbgl/plugin/plugin_layer.hpp | 7 +- src/mbgl/plugin/plugin_layer_factory.cpp | 17 +- src/mbgl/plugin/plugin_layer_factory.hpp | 2 +- src/mbgl/plugin/plugin_layer_impl.hpp | 8 +- src/mbgl/plugin/plugin_layer_render.cpp | 94 ++++------ src/mbgl/plugin/plugin_layer_render.hpp | 3 +- src/mbgl/tile/geometry_tile_worker.cpp | 6 +- 15 files changed, 199 insertions(+), 243 deletions(-) diff --git a/platform/darwin/app/PluginLayerExample.mm b/platform/darwin/app/PluginLayerExample.mm index 16df1dd440da..13c40d8e3794 100644 --- a/platform/darwin/app/PluginLayerExample.mm +++ b/platform/darwin/app/PluginLayerExample.mm @@ -26,7 +26,7 @@ -(void)onUpdateLayer { } //-(void)onBucketLoaded:(MLNRawBucket *)bucket { -// +// //} -(void)onUpdateLayerProperties:(NSDictionary *)layerProperties { @@ -35,29 +35,29 @@ -(void)onUpdateLayerProperties:(NSDictionary *)layerProperties { -(void)featureLoaded:(MLNPluginLayerTileFeature *)tileFeature { NSLog(@"Tile Feature (id:%@) Properties: %@", tileFeature.featureID, tileFeature.featureProperties); - + for (NSValue *v in tileFeature.featureCoordinates) { - + // NSValue *value = [NSValue valueWithBytes:&c objCType:@encode(CLLocationCoordinate2D)]; // [featureCoordinates addObject:value]; CLLocationCoordinate2D coord; [v getValue:&coord]; - + } } -(void)featureUnloaded:(MLNPluginLayerTileFeature *)tileFeature { // NSLog(@"Tile Features Unloaded: %@", tileFeature.featureProperties); - + } - (void)onFeatureLoaded:(MLNPluginLayerTileFeature *)tileFeature { - + [self featureLoaded:tileFeature]; - + } /// Called when a set of features are loaded from the tile @@ -66,7 +66,7 @@ - (void)onFeatureCollectionLoaded:(MLNPluginLayerTileFeatureCollection *)tileFea for (MLNPluginLayerTileFeature *feature in tileFeatureCollection.features) { [self featureLoaded:feature]; } - + } /// Called when a set of features are unloaded because the tile goes out of scene/etc diff --git a/platform/darwin/src/MLNPluginLayer.h b/platform/darwin/src/MLNPluginLayer.h index 7fb38a34338c..5b3fe06f7cca 100644 --- a/platform/darwin/src/MLNPluginLayer.h +++ b/platform/darwin/src/MLNPluginLayer.h @@ -54,7 +54,7 @@ MLN_EXPORT @interface MLNPluginLayerTileFeatureCollection : NSObject @property NSArray *features; -@property NSString *tileID; // z,x,y +@property NSString *tileID; // z,x,y @end @@ -128,8 +128,8 @@ MLN_EXPORT /// Called when a set of features are loaded from the tile /* - TODO: Think about returning that this layer doesn't care about this feature collection via a bool/etc and then - the underlying layer won't have to track this collection. + TODO: Think about returning that this layer doesn't care about this feature collection via a + bool/etc and then the underlying layer won't have to track this collection. */ - (void)onFeatureCollectionLoaded:(MLNPluginLayerTileFeatureCollection *)tileFeatureCollection; diff --git a/platform/darwin/src/MLNPluginLayer.mm b/platform/darwin/src/MLNPluginLayer.mm index 73327779d8b2..05de4517e1ce 100644 --- a/platform/darwin/src/MLNPluginLayer.mm +++ b/platform/darwin/src/MLNPluginLayer.mm @@ -73,7 +73,7 @@ - (void)onUpdateLayer:(MLNPluginLayerDrawingContext)drawingContext { -(void)onUpdateLayerProperties:(NSDictionary *)layerProperties { // Base class does nothing } - + // If the layer properties indicate that this layer has a the ability to intercept // features, then this method will be called when a feature is loaded - (void)onFeatureLoaded:(MLNPluginLayerTileFeature *)tileFeature { @@ -97,7 +97,7 @@ - (void)didMoveToMapView:(MLNMapView *)mapView { // Base class does nothing } - + @end diff --git a/platform/ios/app/MBXViewController.mm b/platform/ios/app/MBXViewController.mm index 3e1a02568f11..b571f0202a4a 100644 --- a/platform/ios/app/MBXViewController.mm +++ b/platform/ios/app/MBXViewController.mm @@ -2338,7 +2338,7 @@ - (void)setStyles NSURL *url = [[NSBundle mainBundle] URLForResource:@"PluginLayerTestStyle.json" withExtension:nil]; [self.styleURLs addObject:url]; - + /// Style that does not require an `apiKey` nor any further configuration [self.styleNames addObject:@"MapLibre Basic"]; [self.styleURLs addObject:[NSURL URLWithString:@"https://demotiles.maplibre.org/style.json"]]; diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 38faabadb6ba..9e7f43f411dd 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -7654,35 +7654,35 @@ - (void)triggerRepaint } -(MLNPluginLayerTileFeature *)featureFromCore:(std::shared_ptr)feature { - + MLNPluginLayerTileFeature *tempResult = [[MLNPluginLayerTileFeature alloc] init]; - + NSMutableDictionary *tileProperties = [NSMutableDictionary dictionary]; for (auto p: feature->_featureProperties) { NSString *key = [NSString stringWithUTF8String:p.first.c_str()]; NSString *value = [NSString stringWithUTF8String:p.second.c_str()]; [tileProperties setObject:value forKey:key]; } - + tempResult.featureProperties = [NSDictionary dictionaryWithDictionary:tileProperties]; - + NSMutableArray *featureCoordinates = [NSMutableArray array]; for (auto & coordinateCollection: feature->_featureCoordinates) { - + for (auto & coordinate: coordinateCollection._coordinates) { CLLocationCoordinate2D c = CLLocationCoordinate2DMake(coordinate._lat, coordinate._lon); NSValue *value = [NSValue valueWithBytes:&c objCType:@encode(CLLocationCoordinate2D)]; [featureCoordinates addObject:value]; } - + } // TODO: Need to figure out how we're going to handle multiple coordinate groups/etc if ([featureCoordinates count] > 0) { tempResult.featureCoordinates = [NSArray arrayWithArray:featureCoordinates]; } - + tempResult.featureID = [NSString stringWithUTF8String:feature->_featureID.c_str()]; - + return tempResult; } @@ -7714,8 +7714,8 @@ -(void)addPluginLayerType:(Class)pluginLayerClass { if (capabilities.requiresPass3D) { pass3D = mbgl::style::LayerTypeInfo::Pass3D::Required; } - - + + // If we read tile features, then we need to set these things if (capabilities.supportsReadingTileFeatures) { tileKind = mbgl::style::LayerTypeInfo::TileKind::Geometry; @@ -7826,27 +7826,27 @@ -(void)addPluginLayerType:(Class)pluginLayerClass { [weakPlugInLayer onUpdateLayerProperties:properties]; } }); - + // If this layer can read tile features, then setup that lambda if (capabilities.supportsReadingTileFeatures) { pluginLayerImpl->setFeatureLoadedFunction([weakPlugInLayer, weakMapView](const std::shared_ptr feature) { - + @autoreleasepool { MLNPluginLayerTileFeature *tileFeature = [weakMapView featureFromCore:feature]; - + [weakPlugInLayer onFeatureLoaded:tileFeature]; } - + }); - - + + pluginLayerImpl->setFeatureCollectionLoadedFunction([weakPlugInLayer, weakMapView](const std::shared_ptr featureCollection) { - + @autoreleasepool { - + MLNPluginLayerTileFeatureCollection *collection = [[MLNPluginLayerTileFeatureCollection alloc] init]; - + // Add the features NSMutableArray *featureList = [NSMutableArray arrayWithCapacity:featureCollection->_features.size()]; for (auto f: featureCollection->_features) { @@ -7855,21 +7855,21 @@ -(void)addPluginLayerType:(Class)pluginLayerClass { collection.features = [NSArray arrayWithArray:featureList]; collection.tileID = [weakMapView tileIDToString:featureCollection->_featureCollectionTileID]; - + [weakPlugInLayer onFeatureCollectionLoaded:collection]; } - + }); - + pluginLayerImpl->setFeatureCollectionUnloadedFunction([weakPlugInLayer, weakMapView](const std::shared_ptr featureCollection) { - + @autoreleasepool { - + // TODO: Map these collections to local vars and maybe don't keep recreating it - + MLNPluginLayerTileFeatureCollection *collection = [[MLNPluginLayerTileFeatureCollection alloc] init]; - + // Add the features NSMutableArray *featureList = [NSMutableArray arrayWithCapacity:featureCollection->_features.size()]; for (auto f: featureCollection->_features) { @@ -7877,17 +7877,17 @@ -(void)addPluginLayerType:(Class)pluginLayerClass { } collection.features = [NSArray arrayWithArray:featureList]; collection.tileID = [weakMapView tileIDToString:featureCollection->_featureCollectionTileID]; - + [weakPlugInLayer onFeatureCollectionUnloaded:collection]; } - + }); - - + + } }); diff --git a/src/mbgl/plugin/feature_collection.hpp b/src/mbgl/plugin/feature_collection.hpp index 6b170d321e09..8b75ebada98f 100644 --- a/src/mbgl/plugin/feature_collection.hpp +++ b/src/mbgl/plugin/feature_collection.hpp @@ -19,14 +19,14 @@ namespace mbgl { namespace plugin { -//using FillBinders = PaintPropertyBinders; -//using FillLayoutVertex = gfx::Vertex>; +// using FillBinders = PaintPropertyBinders; +// using FillLayoutVertex = gfx::Vertex>; class FeatureCoordinate { public: - FeatureCoordinate(double lat, double lon) : _lat(lat), _lon(lon) { - - } + FeatureCoordinate(double lat, double lon) + : _lat(lat), + _lon(lon) {} double _lat = 0; double _lon = 0; double _tileX = 0; // Tile coord @@ -53,22 +53,21 @@ class Feature { std::map _featureProperties; std::vector _featureCoordinates; std::string _featureID; // Unique id from the data source for this - }; class FeatureCollection { public: - FeatureCollection(OverscaledTileID tileID): _featureCollectionTileID(tileID) {}; + FeatureCollection(OverscaledTileID tileID) + : _featureCollectionTileID(tileID) {}; std::vector> _features; - + // TODO: Open question about this.. should feature collections be tied to tile id? // TODO: Question: Is overscaled the right thing or just canonical? OverscaledTileID _featureCollectionTileID; }; +} // namespace plugin -} - -} +} // namespace mbgl #endif /* feature_collection_hpp */ diff --git a/src/mbgl/plugin/feature_collection_bucket.cpp b/src/mbgl/plugin/feature_collection_bucket.cpp index 4028ae214e38..f4797a2b88f2 100644 --- a/src/mbgl/plugin/feature_collection_bucket.cpp +++ b/src/mbgl/plugin/feature_collection_bucket.cpp @@ -14,44 +14,43 @@ using namespace mbgl; -FeatureCollectionBucket::~FeatureCollectionBucket() { - -} +FeatureCollectionBucket::~FeatureCollectionBucket() {} FeatureCollectionBucket::FeatureCollectionBucket(const BucketParameters& bucketParameters, - const std::vector>& layers): -_tileID(bucketParameters.tileID) { + const std::vector>& layers) + : _tileID(bucketParameters.tileID) { _layers = layers; _featureCollection = std::make_shared(bucketParameters.tileID); } -void geometryToLatLon( - const GeometryCoordinate& coord, - int tileX, int tileY, int zoom, - double& lat, double& lon, - int extent = 8192, - int tileSize = 512 -) { - double px = coord.x / double(extent); - double py = coord.y / double(extent); +void geometryToLatLon(const GeometryCoordinate& coord, + int tileX, + int tileY, + int zoom, + double& lat, + double& lon, + int extent = 8192, + int tileSize = 512) { + double px = coord.x / double(extent); + double py = coord.y / double(extent); - double worldPixelX = (tileX + px) * tileSize; - double worldPixelY = (tileY + py) * tileSize; + double worldPixelX = (tileX + px) * tileSize; + double worldPixelY = (tileY + py) * tileSize; - double worldSize = tileSize * (1 << zoom); + double worldSize = tileSize * (1 << zoom); - double mercX = worldPixelX / worldSize * 2.0 - 1.0; - double mercY = 1.0 - worldPixelY / worldSize * 2.0; + double mercX = worldPixelX / worldSize * 2.0 - 1.0; + double mercY = 1.0 - worldPixelY / worldSize * 2.0; - lon = mercX * 180.0; - lat = 180.0 / M_PI * (2.0 * atan(exp(mercY * M_PI)) - M_PI / 2.0); + lon = mercX * 180.0; + lat = 180.0 / M_PI * (2.0 * atan(exp(mercY * M_PI)) - M_PI / 2.0); } -std::string toString(FeatureIdentifier & v) { - // auto v = toValue(value); - +std::string toString(FeatureIdentifier& v) { + // auto v = toValue(value); + // null_value_t, uint64_t, int64_t, double, std::string> - + std::string tempResult = ""; auto ti = v.which(); if (ti == 0) { @@ -81,49 +80,43 @@ std::string toString(FeatureIdentifier & v) { output.append(std::to_string(*d)); } */ - } void FeatureCollectionBucket::addFeature(const GeometryTileFeature& tileFeature, - const GeometryCollection& geometeryCollection, - const mbgl::ImagePositions& imagePositions, - const PatternLayerMap& patternLayerMap, - std::size_t size, - const CanonicalTileID& tileID) { - + const GeometryCollection& geometeryCollection, + const mbgl::ImagePositions& imagePositions, + const PatternLayerMap& patternLayerMap, + std::size_t size, + const CanonicalTileID& tileID) { std::shared_ptr tempFeature = std::make_shared(); - + auto featureID = tileFeature.getID(); auto featureIDString = toString(featureID); tempFeature->_featureID = featureIDString; - - + switch (tileFeature.getType()) { case FeatureType::Point: - //std::cout << "Adding Point" << "\n"; + // std::cout << "Adding Point" << "\n"; tempFeature->_featureType = plugin::Feature::FeatureType::FeatureTypePoint; break; case FeatureType::Unknown: - //std::cout << "Unknown Type Found\n"; + // std::cout << "Unknown Type Found\n"; break; case FeatureType::LineString: - //std::cout << "LineString Type Found\n"; + // std::cout << "LineString Type Found\n"; tempFeature->_featureType = plugin::Feature::FeatureType::FeatureTypeLine; break; case FeatureType::Polygon: - //std::cout << "Polygon Type Found\n"; + // std::cout << "Polygon Type Found\n"; tempFeature->_featureType = plugin::Feature::FeatureType::FeatureTypePolygon; break; - - } - + auto pm = tileFeature.getProperties(); - for (auto p: pm) { - + for (auto p : pm) { auto name = p.first; mapbox::feature::value value = p.second; - + if (auto iVal = value.getInt()) { std::cout << "Found Int: " << name << ": " << *iVal << "\n"; tempFeature->_featureProperties[name] = std::to_string(*iVal); @@ -132,84 +125,74 @@ void FeatureCollectionBucket::addFeature(const GeometryTileFeature& tileFeature, tempFeature->_featureProperties[name] = std::to_string(*uIVal); } else if (auto s = value.getString()) { - - // std::cout << "Found String: " << name << ": " << *s << "\n"; + // std::cout << "Found String: " << name << ": " << *s << "\n"; tempFeature->_featureProperties[name] = *s; } else if (auto d = value.getDouble()) { - // std::cout << "Found Double: " << name << ": " << *d << "\n"; + // std::cout << "Found Double: " << name << ": " << *d << "\n"; tempFeature->_featureProperties[name] = std::to_string(*d); } else if (auto b = value.getBool()) { - // std::cout << "Found Bool: " << name << ": " << *b << "\n"; + // std::cout << "Found Bool: " << name << ": " << *b << "\n"; tempFeature->_featureProperties[name] = std::to_string(*b); } else if (auto a = value.getArray()) { - // std::cout << "Found Array: " << name << ": " << *b << "\n"; + // std::cout << "Found Array: " << name << ": " << *b << "\n"; tempFeature->_featureProperties[name] = std::to_string(*b); } - - -// DECLARE_VALUE_TYPE_ACCESOR(Array, array_type) -// DECLARE_VALUE_TYPE_ACCESOR(Object, object_type) - + + // DECLARE_VALUE_TYPE_ACCESOR(Array, array_type) + // DECLARE_VALUE_TYPE_ACCESOR(Object, object_type) } - + LatLngBounds b(tileID); - - - + for (const auto& g : geometeryCollection) { // g is GeometryCoordinates plugin::FeatureCoordinateCollection c; for (std::size_t i = 0, len = g.size(); i < len; i++) { const GeometryCoordinate& p1 = g[i]; - + auto d = b.west(); - -// auto c = project( - - -// void geometryToLatLon( -// const GeometryCoordinate& coord, -// int tileX, int tileY, int zoom, -// double& lat, double& lon, -// int extent = 8192, -// int tileSize = 512 + + // auto c = project( + + // void geometryToLatLon( + // const GeometryCoordinate& coord, + // int tileX, int tileY, int zoom, + // double& lat, double& lon, + // int extent = 8192, + // int tileSize = 512 double lat = 0; double lon = 0; geometryToLatLon(p1, tileID.x, tileID.y, tileID.z, lat, lon); - + c._coordinates.push_back(plugin::FeatureCoordinate(lat, lon)); } tempFeature->_featureCoordinates.push_back(c); - } - - for (auto l: _layers) { + + for (auto l : _layers) { auto bi = l->baseImpl; auto bip = bi.get(); - auto pluginLayer = static_cast(bip); + auto pluginLayer = static_cast(bip); if (pluginLayer != nullptr) { if (pluginLayer->_featureLoadedFunction != nullptr) { pluginLayer->_featureLoadedFunction(tempFeature); } - } - // auto pluginLayer = std::dynamic_pointer_cast>(bi); - -// auto pluginLayer = std::dynamic_pointer_cast(l->baseImpl); -// if (pluginLayer != nullptr) { -// if (pluginLayer->_featureLoadedFunction != nullptr) { -// pluginLayer->_featureLoadedFunction(tempFeature); -// } -// } + // auto pluginLayer = std::dynamic_pointer_cast>(bi); + + // auto pluginLayer = std::dynamic_pointer_cast(l->baseImpl); + // if (pluginLayer != nullptr) { + // if (pluginLayer->_featureLoadedFunction != nullptr) { + // pluginLayer->_featureLoadedFunction(tempFeature); + // } + // } } - - + _featureCollection->_features.push_back(tempFeature); - // _features.push_back(tempFeature); - -// std::cout << "Adding Feature Type: " << tileFeature.getType() << "\n"; - + // _features.push_back(tempFeature); + + // std::cout << "Adding Feature Type: " << tileFeature.getType() << "\n"; } bool FeatureCollectionBucket::hasData() const { @@ -225,8 +208,9 @@ float FeatureCollectionBucket::getQueryRadius(const RenderLayer&) const { return 0; } -void FeatureCollectionBucket::update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) { +void FeatureCollectionBucket::update(const FeatureStates&, + const GeometryTileLayer&, + const std::string&, + const ImagePositions&) { std::cout << "FeatureCollectionBucket::update\n"; - } - diff --git a/src/mbgl/plugin/feature_collection_bucket.hpp b/src/mbgl/plugin/feature_collection_bucket.hpp index c78a5a811a39..ec5ae03e7a0a 100644 --- a/src/mbgl/plugin/feature_collection_bucket.hpp +++ b/src/mbgl/plugin/feature_collection_bucket.hpp @@ -12,32 +12,30 @@ #include /* - + Open Questions - - + + * Should we load up a vector of these RawFeatures by tile? * How does that interop with the render layer's update flow * Should the call back from render layer be more of a batch thing at that update stage? * Should there be a callback when a tile or collection of these features go out of scope? * Should the concept of managing arrays of features be something done by the core or just hand off the features to the plug-in layer and let it do it's thing or have the option for both? - + * How do we get to the osm id of features in the stream? Is that tileFeature.getID()? * Is there already a set of classes or a paradigm out there that could be used to represent the feature / feature geometry? * What are the "binders"? - - + + Thoughts * Possibly have ability to keep tile coordinates using some kind flag - - - - */ + */ + namespace mbgl { class BucketParameters; @@ -46,7 +44,7 @@ class RenderFillLayer; class FeatureCollectionBucket final : public Bucket { public: ~FeatureCollectionBucket() override; - //using PossiblyEvaluatedLayoutProperties = style::FillLayoutProperties::PossiblyEvaluated; + // using PossiblyEvaluatedLayoutProperties = style::FillLayoutProperties::PossiblyEvaluated; FeatureCollectionBucket(const BucketParameters&, const std::vector>&); @@ -70,10 +68,10 @@ class FeatureCollectionBucket final : public Bucket { // Array of features std::shared_ptr _featureCollection = nullptr; - //std::vector> _features; - + // std::vector> _features; + std::vector> _layers; - + /* static FillLayoutVertex layoutVertex(Point p) { return FillLayoutVertex{{{p.x, p.y}}}; } diff --git a/src/mbgl/plugin/plugin_layer.hpp b/src/mbgl/plugin/plugin_layer.hpp index 0767491022c5..5e6bb9adb06d 100644 --- a/src/mbgl/plugin/plugin_layer.hpp +++ b/src/mbgl/plugin/plugin_layer.hpp @@ -11,7 +11,6 @@ class RawBucketFeature; namespace style { - class PluginLayer final : public Layer { public: PluginLayer(const std::string& layerID, @@ -33,8 +32,10 @@ class PluginLayer final : public Layer { using OnUpdateLayer = std::function; using OnUpdateLayerProperties = std::function; using OnFeatureLoaded = std::function feature)>; - using OnFeatureCollectionLoaded = std::function featureCollection)>; - using OnFeatureCollectionUnloaded = std::function featureCollection)>; + using OnFeatureCollectionLoaded = + std::function featureCollection)>; + using OnFeatureCollectionUnloaded = + std::function featureCollection)>; void* _platformReference = nullptr; diff --git a/src/mbgl/plugin/plugin_layer_factory.cpp b/src/mbgl/plugin/plugin_layer_factory.cpp index 1354113065e8..a30db5105ee8 100644 --- a/src/mbgl/plugin/plugin_layer_factory.cpp +++ b/src/mbgl/plugin/plugin_layer_factory.cpp @@ -157,12 +157,11 @@ std::unique_ptr PluginLayerFactory::createLayer(const std::string& sourceStr = source.value(); } } - - auto tempResult = std::unique_ptr(new (std::nothrow) - style::PluginLayer(id, sourceStr, _layerTypeInfo, layerProperties - //,*customProperties - )); + auto tempResult = std::unique_ptr(new (std::nothrow) style::PluginLayer( + id, sourceStr, _layerTypeInfo, layerProperties + //,*customProperties + )); if (_onLayerCreated != nullptr) { auto layerRaw = tempResult.get(); @@ -180,10 +179,10 @@ std::unique_ptr PluginLayerFactory::createLayer(const std::string& std::unique_ptr PluginLayerFactory::createBucket( [[maybe_unused]] const BucketParameters& parameters, [[maybe_unused]] const std::vector>& layers) noexcept { - if (_supportsFeatureCollectionBuckets) { - return std::make_unique(parameters, layers); - } - return nullptr; + if (_supportsFeatureCollectionBuckets) { + return std::make_unique(parameters, layers); + } + return nullptr; } std::unique_ptr PluginLayerFactory::createRenderLayer(Immutable impl) noexcept { diff --git a/src/mbgl/plugin/plugin_layer_factory.hpp b/src/mbgl/plugin/plugin_layer_factory.hpp index 7d75b7681c45..e2d3aa4e392b 100644 --- a/src/mbgl/plugin/plugin_layer_factory.hpp +++ b/src/mbgl/plugin/plugin_layer_factory.hpp @@ -25,7 +25,7 @@ class PluginLayerFactory : public LayerFactory { // Set to false, but if the caller wants to support on features loaded, then set this to true bool _supportsFeatureCollectionBuckets = false; - + using OnLayerCreatedEvent = std::function; void setOnLayerCreatedEvent(OnLayerCreatedEvent onLayerCreated) { _onLayerCreated = onLayerCreated; } diff --git a/src/mbgl/plugin/plugin_layer_impl.hpp b/src/mbgl/plugin/plugin_layer_impl.hpp index ee4d3982230f..7b79399ee07b 100644 --- a/src/mbgl/plugin/plugin_layer_impl.hpp +++ b/src/mbgl/plugin/plugin_layer_impl.hpp @@ -102,7 +102,7 @@ class PluginLayer::Impl : public Layer::Impl { void setFeatureLoadedFunction(OnFeatureLoaded featureLoadedFunction) { _featureLoadedFunction = featureLoadedFunction; } - + void setFeatureCollectionLoadedFunction(OnFeatureCollectionLoaded featureCollectionLoadedFunction) { _featureCollectionLoadedFunction = featureCollectionLoadedFunction; } @@ -127,13 +127,13 @@ class PluginLayer::Impl : public Layer::Impl { //! Optional: Called when feature is loaded OnFeatureLoaded _featureLoadedFunction; - + //! Optional: Called when a feature collection is loaded OnFeatureCollectionLoaded _featureCollectionLoadedFunction; - + //! Optional: Called when a feature colleciton is unloaded from the scene (tile goes out of scene/etc) OnFeatureCollectionUnloaded _featureCollectionUnloadedFunction; - + private: LayerTypeInfo _layerTypeInfo; std::string _layerProperties; diff --git a/src/mbgl/plugin/plugin_layer_render.cpp b/src/mbgl/plugin/plugin_layer_render.cpp index e36e6ef2208e..64cd64f547d7 100644 --- a/src/mbgl/plugin/plugin_layer_render.cpp +++ b/src/mbgl/plugin/plugin_layer_render.cpp @@ -90,12 +90,11 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis [[maybe_unused]] const std::shared_ptr& updateParameters, [[maybe_unused]] const RenderTree& renderTree, [[maybe_unused]] UniqueChangeRequestVec& changes) { - - auto pluginLayer = static_cast(*baseImpl); + auto pluginLayer = static_cast(*baseImpl); std::vector removedTiles; bool removeAllTiles = ((renderTiles == nullptr) || (renderTiles->empty())); - + // TODO: Remove #ifdef C_LOG_TILES static int passCount = 0; @@ -104,33 +103,32 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis std::cout << passCount << ": Remove All Tiles\n"; } #endif - + // Get list of tiles to remove and then remove them - for (auto currentCollection: _featureCollectionByTile) { + for (auto currentCollection : _featureCollectionByTile) { if (removeAllTiles || !hasRenderTile(currentCollection.first)) { removedTiles.push_back(currentCollection.first); } } if (removedTiles.size() > 0) { - for (auto tileID: removedTiles) { + for (auto tileID : removedTiles) { auto featureCollection = _featureCollectionByTile[tileID]; if (pluginLayer._featureCollectionUnloadedFunction) { pluginLayer._featureCollectionUnloadedFunction(featureCollection); } #ifdef C_LOG_TILES // TODO: Remove this logging - std::cout << passCount << ": Removing Feature Collection for Tile: " << (int)tileID.canonical.z << "," << tileID.canonical.x << "," << tileID.canonical.y << "\n"; + std::cout << passCount << ": Removing Feature Collection for Tile: " << (int)tileID.canonical.z << "," + << tileID.canonical.x << "," << tileID.canonical.y << "\n"; #endif _featureCollectionByTile.erase(tileID); } } - if (renderTiles) { if (!renderTiles->empty()) { - auto drawPass = RenderPass::Pass3D; - + // If we're reading feature collections, go through // and notify the plugin of any new feature collections for (const RenderTile& tile : *renderTiles) { @@ -141,12 +139,12 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis std::cout << passCount << ": Tile was there and not anymore\n"; #endif } - + // TODO: Remove -// if ((tileID.canonical.x == 1289) && (tileID.canonical.y == 879)) { -// std::cout << "Found tile\n"; -// } - + // if ((tileID.canonical.x == 1289) && (tileID.canonical.y == 879)) { + // std::cout << "Found tile\n"; + // } + const auto* optRenderData = getRenderDataForPass(tile, drawPass); if (!optRenderData || !optRenderData->bucket || !optRenderData->bucket->hasData()) { removeTile(drawPass, tileID); @@ -155,34 +153,35 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis const auto& renderData = *optRenderData; auto& bucket = static_cast(*renderData.bucket); // TODO: Remove - //std::cout << "Found Bucket\n"; + // std::cout << "Found Bucket\n"; auto featureCollection = bucket._featureCollection; if (featureCollection == nullptr) { continue; } - + // See if we already have this tile'a feature collection if (_featureCollectionByTile.contains(tileID)) { continue; } - + _featureCollectionByTile[tileID] = featureCollection; -// static_cast(*baseImpl); -// auto layer = static_cast(*renderData.layerProperties->baseImpl); + // static_cast(*baseImpl); + // auto layer = static_cast(*renderData.layerProperties->baseImpl); if (pluginLayer._featureCollectionLoadedFunction) { if (featureCollection != nullptr) { pluginLayer._featureCollectionLoadedFunction(featureCollection); #ifdef C_LOG_TILES // TODO: Remove logging - std::cout << passCount << ": Adding Feature Collection for Tile: " << (int)tileID.canonical.z << "," << tileID.canonical.x << "," << tileID.canonical.y << "\n"; + std::cout << passCount << ": Adding Feature Collection for Tile: " << (int)tileID.canonical.z + << "," << tileID.canonical.x << "," << tileID.canonical.y << "\n"; #endif - } } - + /* - + const auto prevBucketID = getRenderTileBucketID(tileID); if (prevBucketID != util::SimpleIdentity::Empty && prevBucketID != bucket.getID()) { // This tile was previously set up from a different bucket, drop and re-create any drawables for it. @@ -190,11 +189,8 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis } setRenderTileBucketID(tileID, bucket.getID()); */ - } - } - } /* @@ -222,16 +218,16 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); - + const auto* optRenderData = getRenderDataForPass(tile, drawPass); if (!optRenderData || !optRenderData->bucket || !optRenderData->bucket->hasData()) { removeTile(drawPass, tileID); continue; } - + const auto& renderData = *optRenderData; auto& bucket = static_cast(*renderData.bucket); - + const auto prevBucketID = getRenderTileBucketID(tileID); if (prevBucketID != util::SimpleIdentity::Empty && prevBucketID != bucket.getID()) { // This tile was previously set up from a different bucket, drop and re-create any drawables for it. @@ -241,22 +237,7 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis } */ - - - - - - - - - - - - - - - - + // create layer group if (!layerGroup) { if (auto layerGroup_ = context.createLayerGroup(layerIndex, /*initialCapacity=*/1, getID())) { @@ -300,7 +281,6 @@ void RenderPluginLayer::render(PaintParameters& paintParameters) { } void RenderPluginLayer::prepare(const LayerPrepareParameters& layerParameters) { - // This check is here because base prepare will assert on these and crash if (layerParameters.source != nullptr) { if (layerParameters.source->isEnabled()) { @@ -308,7 +288,6 @@ void RenderPluginLayer::prepare(const LayerPrepareParameters& layerParameters) { } } - if (_updateFunction) { _updateFunction(layerParameters); } @@ -344,20 +323,17 @@ void RenderPluginLayer::evaluate(const PropertyEvaluationParameters& parameters) std::string jsonProperties = pm.propertiesAsJSON(); i->_updateLayerPropertiesFunction(jsonProperties); - - - auto properties = makeMutable(staticImmutableCast(baseImpl)); + + auto properties = makeMutable( + staticImmutableCast(baseImpl)); passes = RenderPass::Pass3D; -// passes = RenderPass::Pass3D; (evaluated.get().constantOr(1.0) > 0 && -// evaluated.get().constantOr(Color::black()).a > 0 && -// evaluated.get().constantOr(1.0) > 0) -// ? RenderPass::Translucent -// : RenderPass::None; + // passes = RenderPass::Pass3D; (evaluated.get().constantOr(1.0) > 0 && + // evaluated.get().constantOr(Color::black()).a > 0 && + // evaluated.get().constantOr(1.0) > 0) + // ? RenderPass::Translucent + // : RenderPass::None; properties->renderPasses = mbgl::underlying_type(passes); evaluatedProperties = std::move(properties); - - - } bool RenderPluginLayer::hasTransition() const { diff --git a/src/mbgl/plugin/plugin_layer_render.hpp b/src/mbgl/plugin/plugin_layer_render.hpp index 847aea6003f8..f7ccdc70d8c8 100644 --- a/src/mbgl/plugin/plugin_layer_render.hpp +++ b/src/mbgl/plugin/plugin_layer_render.hpp @@ -68,9 +68,8 @@ class RenderPluginLayer final : public RenderLayer { style::PluginLayer::OnUpdateLayer _updateFunction = nullptr; style::PluginLayer::OnUpdateLayerProperties _updateLayerPropertiesFunction = nullptr; - + std::map> _featureCollectionByTile; - }; } // namespace mbgl diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp index 874494cd94a5..5ea111730f0f 100644 --- a/src/mbgl/tile/geometry_tile_worker.cpp +++ b/src/mbgl/tile/geometry_tile_worker.cpp @@ -398,11 +398,11 @@ void GeometryTileWorker::parse() { for (auto layer : *layers) { auto lk = layoutKey(*layer->baseImpl); - //std::cout << "LK: " << lk << "\n"; + // std::cout << "LK: " << lk << "\n"; if (lk.find("parking_space1") != std::string::npos) { - // std::cout << " Found PLugin\n"; + // std::cout << " Found PLugin\n"; } else { - // continue; + // continue; } groupMap[lk].push_back(std::move(layer)); } From de3897a98299bc7f1e9a69907aefbb2aa27127f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Fri, 25 Jul 2025 10:57:30 -0400 Subject: [PATCH 116/221] Reverting some logging --- src/mbgl/tile/geometry_tile_worker.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp index 874494cd94a5..73353873630d 100644 --- a/src/mbgl/tile/geometry_tile_worker.cpp +++ b/src/mbgl/tile/geometry_tile_worker.cpp @@ -397,14 +397,7 @@ void GeometryTileWorker::parse() { groupMap.reserve(layers->size()); for (auto layer : *layers) { - auto lk = layoutKey(*layer->baseImpl); - //std::cout << "LK: " << lk << "\n"; - if (lk.find("parking_space1") != std::string::npos) { - // std::cout << " Found PLugin\n"; - } else { - // continue; - } - groupMap[lk].push_back(std::move(layer)); + groupMap[layoutKey(*layer->baseImpl)].push_back(std::move(layer)); } for (auto& pair : groupMap) { From 7f3ab5f2a6cd26ef3c241623095c68ad61b38b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Fri, 25 Jul 2025 10:59:10 -0400 Subject: [PATCH 117/221] Removed unused include --- src/mbgl/tile/geometry_tile_worker.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp index 73353873630d..4935bc5f3382 100644 --- a/src/mbgl/tile/geometry_tile_worker.cpp +++ b/src/mbgl/tile/geometry_tile_worker.cpp @@ -24,7 +24,6 @@ #include #include -#include namespace mbgl { From c8cc54474cf78b9db1ae3fe75d157ebe153d1c67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Fri, 25 Jul 2025 10:59:49 -0400 Subject: [PATCH 118/221] Removed unused header --- src/mbgl/renderer/render_orchestrator.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index 9805979f524a..8f6e3abf0419 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -29,8 +29,6 @@ #include #include -#include - namespace mbgl { using namespace style; From 345861445fde7c2fa5000ef12c3cf89765db9bdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Fri, 25 Jul 2025 13:31:40 -0400 Subject: [PATCH 119/221] Initial commit of style filters --- bazel/core.bzl | 2 + include/mbgl/style/style.hpp | 4 ++ platform/BUILD.bazel | 2 + platform/darwin/BUILD.bazel | 2 + platform/darwin/app/StyleFilterExample.h | 16 ++++++ platform/darwin/app/StyleFilterExample.mm | 60 ++++++++++++++++++++ platform/darwin/bazel/files.bzl | 6 +- platform/darwin/src/MLNStyleFilter.h | 12 ++++ platform/darwin/src/MLNStyleFilter.mm | 23 ++++++++ platform/darwin/src/MLNStyleFilter_Private.h | 14 +++++ platform/ios/app/MBXViewController.mm | 2 + platform/ios/src/MLNMapView.h | 6 ++ platform/ios/src/MLNMapView.mm | 55 ++++++++++++++++++ src/mbgl/plugin/plugin_style_filter.cpp | 14 +++++ src/mbgl/plugin/plugin_style_filter.hpp | 23 ++++++++ src/mbgl/style/style.cpp | 8 +++ src/mbgl/style/style_impl.cpp | 22 ++++++- src/mbgl/style/style_impl.hpp | 7 +++ 18 files changed, 275 insertions(+), 3 deletions(-) create mode 100644 platform/darwin/app/StyleFilterExample.h create mode 100644 platform/darwin/app/StyleFilterExample.mm create mode 100644 platform/darwin/src/MLNStyleFilter.h create mode 100644 platform/darwin/src/MLNStyleFilter.mm create mode 100644 platform/darwin/src/MLNStyleFilter_Private.h create mode 100644 src/mbgl/plugin/plugin_style_filter.cpp create mode 100644 src/mbgl/plugin/plugin_style_filter.hpp diff --git a/bazel/core.bzl b/bazel/core.bzl index b27bbd8d925b..f79b5e36f6da 100644 --- a/bazel/core.bzl +++ b/bazel/core.bzl @@ -4,6 +4,7 @@ MLN_LAYER_PLUGIN_HEADERS = [ "src/mbgl/plugin/plugin_layer_impl.hpp", "src/mbgl/plugin/plugin_layer_render.hpp", "src/mbgl/plugin/plugin_layer_properties.hpp", + "src/mbgl/plugin/plugin_style_filter.hpp", ] MLN_LAYER_PLUGIN_SOURCE = [ @@ -12,6 +13,7 @@ MLN_LAYER_PLUGIN_SOURCE = [ "src/mbgl/plugin/plugin_layer_impl.cpp", "src/mbgl/plugin/plugin_layer_render.cpp", "src/mbgl/plugin/plugin_layer_properties.cpp", + "src/mbgl/plugin/plugin_style_filter.cpp", ] MLN_PUBLIC_GENERATED_STYLE_HEADERS = [ diff --git a/include/mbgl/style/style.hpp b/include/mbgl/style/style.hpp index 0d2d45719158..b143c5738c8d 100644 --- a/include/mbgl/style/style.hpp +++ b/include/mbgl/style/style.hpp @@ -20,6 +20,7 @@ namespace style { class Light; class Source; class Layer; +class PluginStyleFilter; class Style { public: @@ -71,6 +72,9 @@ class Style { void addLayer(std::unique_ptr, const std::optional& beforeLayerID = std::nullopt); std::unique_ptr removeLayer(const std::string& layerID); + // Add style parsing filter + void addStyleFilter(std::shared_ptr); + // Private implementation class Impl; const std::unique_ptr impl; diff --git a/platform/BUILD.bazel b/platform/BUILD.bazel index f39d31d1ee8e..bb89fd40fd6a 100644 --- a/platform/BUILD.bazel +++ b/platform/BUILD.bazel @@ -268,6 +268,8 @@ objc_library( srcs = [ "//platform/darwin:app/PluginLayerExample.h", "//platform/darwin:app/PluginLayerExample.mm", + "//platform/darwin:app/StyleFilterExample.h", + "//platform/darwin:app/StyleFilterExample.mm", "//platform/darwin:app/PluginLayerExampleMetalRendering.h", "//platform/darwin:app/PluginLayerExampleMetalRendering.mm", "//platform/darwin:app/CustomStyleLayerExample.h", diff --git a/platform/darwin/BUILD.bazel b/platform/darwin/BUILD.bazel index dcc0a8bcbac4..641f94f0aca1 100644 --- a/platform/darwin/BUILD.bazel +++ b/platform/darwin/BUILD.bazel @@ -301,6 +301,8 @@ exports_files( "app/PluginLayerTestStyle.json", "app/PluginLayerExample.h", "app/PluginLayerExample.mm", + "app/StyleFilterExample.h", + "app/StyleFilterExample.mm", "app/PluginLayerExampleMetalRendering.h", "app/PluginLayerExampleMetalRendering.mm", "test/amsterdam.geojson", diff --git a/platform/darwin/app/StyleFilterExample.h b/platform/darwin/app/StyleFilterExample.h new file mode 100644 index 000000000000..47cfe9f6c4e2 --- /dev/null +++ b/platform/darwin/app/StyleFilterExample.h @@ -0,0 +1,16 @@ +// +// StyleFilterExample.h +// MapLibre +// +// Created by Malcolm Toon on 7/25/25. +// + +#import "MLNStyleFilter.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface StyleFilterExample : MLNStyleFilter + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/app/StyleFilterExample.mm b/platform/darwin/app/StyleFilterExample.mm new file mode 100644 index 000000000000..ab6955136775 --- /dev/null +++ b/platform/darwin/app/StyleFilterExample.mm @@ -0,0 +1,60 @@ +#import "StyleFilterExample.h" + +@implementation StyleFilterExample + +// This will filter the data passed in +-(NSData *)filterData:(NSData *)data { + // Don't call super + + // This example will remove any layer that has "metal-rendering-layer" in the id + + // Parse the JSON: Make the containers mutable + NSError *error = nil; + NSMutableDictionary *styleDictionary = [NSJSONSerialization JSONObjectWithData:data + options:NSJSONReadingMutableContainers + error:&error]; + + NSData *tempResult = data; + if (styleDictionary) { + + // Get the layer array + NSMutableArray *layerArray = [styleDictionary objectForKey:@"layers"]; + + // Create an array to hold which objects to remove since we can't remove them in the loop + NSMutableArray *removedLayers = [NSMutableArray array]; + + // Loop the layers and look for any layers that have the search string in them + for (NSMutableDictionary *layer in layerArray) { + NSString *layerID = [layer objectForKey:@"id"]; + + // If we find the layers we're looking for, add them to the list of layers to remove + if ([layerID containsString:@"metal-rendering-layer"]) { + [removedLayers addObject:layer]; + } + } + + // Go through and remove any layers that were found + for (NSMutableDictionary *l in removedLayers) { + [layerArray removeObject:l]; + } + + // Re-create the JSON, this time the layers we filtered out won't be there + NSData *filteredStyleJSON = [NSJSONSerialization dataWithJSONObject:styleDictionary + options:0 + error:&error]; + + // If the JSON write is successful, then set the output to the new json style + if (filteredStyleJSON) { + tempResult = filteredStyleJSON; + } + + } + + // Return the data + return tempResult; + +} + + + +@end diff --git a/platform/darwin/bazel/files.bzl b/platform/darwin/bazel/files.bzl index 560189cd69c0..da71263cf5d5 100644 --- a/platform/darwin/bazel/files.bzl +++ b/platform/darwin/bazel/files.bzl @@ -108,6 +108,8 @@ MLN_DARWIN_OBJC_HEADERS = [ "src/NSValue+MLNAdditions.h", "src/MLNPluginLayer.h", "src/MLNPluginStyleLayer.h", + "src/MLNStyleFilter.h", + "src/MLNStyleFilter_Private.h", ] MLN_DARWIN_OBJCPP_HEADERS = [ @@ -222,8 +224,8 @@ MLN_DARWIN_PUBLIC_OBJCPP_SOURCE = [ "src/NSPredicate+MLNAdditions.mm", "src/NSValue+MLNStyleAttributeAdditions.mm", "src/MLNPluginLayer.mm", - "src/MLNPluginStyleLayer.mm" - + "src/MLNPluginStyleLayer.mm", + "src/MLNStyleFilter.mm", ] MLN_DARWIN_PUBLIC_OBJCPP_CUSTOM_DRAWABLE_SOURCE = [ "src/MLNCustomDrawableStyleLayer_Private.h", diff --git a/platform/darwin/src/MLNStyleFilter.h b/platform/darwin/src/MLNStyleFilter.h new file mode 100644 index 000000000000..066d329c8469 --- /dev/null +++ b/platform/darwin/src/MLNStyleFilter.h @@ -0,0 +1,12 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MLNStyleFilter : NSObject + +// This will filter the data passed in +-(NSData *)filterData:(NSData *)data; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MLNStyleFilter.mm b/platform/darwin/src/MLNStyleFilter.mm new file mode 100644 index 000000000000..31c6b0f6e937 --- /dev/null +++ b/platform/darwin/src/MLNStyleFilter.mm @@ -0,0 +1,23 @@ +#import "MLNStyleFilter.h" +#include + +@interface MLNStyleFilter () { + std::shared_ptr _coreFilter; +} + +@end + +@implementation MLNStyleFilter + +-(NSData *)filterData:(NSData *)data { + // Base class does nothing but return the same data passed in + return data; +} + +// Private +-(void)setFilter:(std::shared_ptr)filter { + _coreFilter = filter; +} + + +@end diff --git a/platform/darwin/src/MLNStyleFilter_Private.h b/platform/darwin/src/MLNStyleFilter_Private.h new file mode 100644 index 000000000000..f27864868d55 --- /dev/null +++ b/platform/darwin/src/MLNStyleFilter_Private.h @@ -0,0 +1,14 @@ + +#ifndef MLNStyleFilter_Private_h +#define MLNStyleFilter_Private_h + +#import "MLNStyleFilter.h" +#include + +@interface MLNStyleFilter(Private) + +-(void)setFilter:(std::shared_ptr)filter; + +@end + +#endif /* MLNStyleFilter_Private_h */ diff --git a/platform/ios/app/MBXViewController.mm b/platform/ios/app/MBXViewController.mm index 4c13a767ea51..6b68eb906bd4 100644 --- a/platform/ios/app/MBXViewController.mm +++ b/platform/ios/app/MBXViewController.mm @@ -27,6 +27,7 @@ #import "PluginLayerExample.h" #import "PluginLayerExampleMetalRendering.h" #import "MLNPluginStyleLayer.h" +#import "StyleFilterExample.h" static const CLLocationCoordinate2D WorldTourDestinations[] = { { .latitude = 38.8999418, .longitude = -77.033996 }, @@ -281,6 +282,7 @@ -(void)addPluginLayers { [self.mapView addPluginLayerType:[PluginLayerExample class]]; [self.mapView addPluginLayerType:[PluginLayerExampleMetalRendering class]]; + [self.mapView addStyleFilter:[[StyleFilterExample alloc] init]]; } diff --git a/platform/ios/src/MLNMapView.h b/platform/ios/src/MLNMapView.h index 1e800fafe188..decd8f9c12be 100644 --- a/platform/ios/src/MLNMapView.h +++ b/platform/ios/src/MLNMapView.h @@ -20,6 +20,7 @@ NS_ASSUME_NONNULL_BEGIN @class MLNScaleBar; @class MLNShape; @class MLNPluginLayer; +@class MLNStyleFilter; @protocol MLNMapViewDelegate; @protocol MLNAnnotation; @@ -2276,6 +2277,11 @@ vertically on the map. */ - (void)addPluginLayerType:(Class)pluginLayerClass; +/** + Adds a style filter to the map view + */ +-(void)addStyleFilter:(MLNStyleFilter *)styleFilter; + @end NS_ASSUME_NONNULL_END diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 23313088fa14..0c1d1753c264 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -82,6 +83,8 @@ #import "MLNPluginLayer.h" #import "MLNStyleLayerManager.h" #include "MLNPluginStyleLayer_Private.h" +#include "MLNStyleFilter.h" +#include "MLNStyleFilter_Private.h" #include #include @@ -455,6 +458,9 @@ @interface MLNMapView () (); + coreStyleFilter->_filterStyleFunction = [styleFilter](const mbgl::Response &response) -> const mbgl::Response { + + mbgl::Response tempResult; + + @autoreleasepool { + NSData *sourceData = [NSData dataWithBytesNoCopy:(void *)response.data->data() + length:response.data->size() + freeWhenDone:NO]; + NSData *filteredData = [styleFilter filterData:sourceData]; + if (response.error) { + tempResult.error = std::make_unique(response.error->reason, + response.error->message, + response.error->retryAfter); + } + tempResult.noContent = response.noContent; + tempResult.notModified = response.notModified; + tempResult.mustRevalidate = response.mustRevalidate; + tempResult.modified = response.modified; + tempResult.expires = response.expires; + tempResult.etag = response.etag; + + // Set the response data + tempResult.data = + std::make_shared((const char*)[filteredData bytes], [filteredData length]); + + + } + return tempResult; + }; + + // Set the ivar + [styleFilter setFilter:coreStyleFilter]; + + _mbglMap->getStyle().addStyleFilter(coreStyleFilter); + +} + + - (NSArray*)getActionJournalLogFiles { const auto& actionJournal = _mbglMap->getActionJournal(); diff --git a/src/mbgl/plugin/plugin_style_filter.cpp b/src/mbgl/plugin/plugin_style_filter.cpp new file mode 100644 index 000000000000..f30f7697fee2 --- /dev/null +++ b/src/mbgl/plugin/plugin_style_filter.cpp @@ -0,0 +1,14 @@ +#include + +using namespace mbgl::style; + +// This method +const mbgl::Response PluginStyleFilter::FilterResponse(const Response& res) { + + if (_filterStyleFunction) { + auto tempResult = _filterStyleFunction(res); + return tempResult; + } + return res; + +} diff --git a/src/mbgl/plugin/plugin_style_filter.hpp b/src/mbgl/plugin/plugin_style_filter.hpp new file mode 100644 index 000000000000..2cfd8ab26b6c --- /dev/null +++ b/src/mbgl/plugin/plugin_style_filter.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include + + +namespace mbgl { + +namespace style { + +class PluginStyleFilter { +public: + + using OnFilterStyle = std::function; + + OnFilterStyle _filterStyleFunction; + + // This method + const Response FilterResponse(const Response& res); +}; + + +} +} diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index 4f8723ead10a..bba0362b5704 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -177,5 +177,13 @@ std::unique_ptr Style::removeLayer(const std::string& id) { return impl->removeLayer(id); } +// Add style parsing filter +void Style::addStyleFilter(std::shared_ptr filter) { + impl->mutated = true; + return impl->addStyleFilter(filter); + +} + + } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/style_impl.cpp b/src/mbgl/style/style_impl.cpp index b42deb21c152..850774a1e9cb 100644 --- a/src/mbgl/style/style_impl.cpp +++ b/src/mbgl/style/style_impl.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include namespace mbgl { @@ -74,11 +75,24 @@ void Style::Impl::loadURL(const std::string& url_) { } else if (res.notModified || res.noContent) { return; } else { - parse(*res.data); + filterThenParse(res); } }); } +void Style::Impl::filterThenParse(const Response& res) { + + Response tempResult = res; + if (_styleFilters.size() > 0) { + for (auto filter: _styleFilters) { + tempResult = filter->FilterResponse(tempResult); + } + } + parse(*tempResult.data); +// parse(*res.data); + +} + void Style::Impl::parse(const std::string& json_) { Parser parser; @@ -233,6 +247,12 @@ std::unique_ptr Style::Impl::removeLayer(const std::string& id) { return layer; } +// Add style parsing filter +void Style::Impl::addStyleFilter(std::shared_ptr filter) { + _styleFilters.push_back(filter); +} + + void Style::Impl::setLight(std::unique_ptr light_) { light = std::move(light_); light->setObserver(this); diff --git a/src/mbgl/style/style_impl.hpp b/src/mbgl/style/style_impl.hpp index e9ab3abc5654..9effde9d926b 100644 --- a/src/mbgl/style/style_impl.hpp +++ b/src/mbgl/style/style_impl.hpp @@ -28,6 +28,7 @@ namespace mbgl { class FileSource; class AsyncRequest; class SpriteLoader; +class Response; namespace style { @@ -66,6 +67,10 @@ class Style::Impl : public SpriteLoaderObserver, Layer* addLayer(std::unique_ptr, const std::optional& beforeLayerID = std::nullopt); std::unique_ptr removeLayer(const std::string& layerID); + // Add style parsing filter + void addStyleFilter(std::shared_ptr); + void filterThenParse(const Response& res); + std::string getName() const; CameraOptions getDefaultCamera() const; @@ -95,6 +100,8 @@ class Style::Impl : public SpriteLoaderObserver, private: void parse(const std::string&); + std::vector> _styleFilters; + std::shared_ptr fileSource; std::string url; From f4d1ef4112c329a2cb536cf4ffaba3b8dcabbad5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 25 Jul 2025 17:33:50 +0000 Subject: [PATCH 120/221] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- include/mbgl/style/style.hpp | 2 +- platform/darwin/app/StyleFilterExample.mm | 26 ++++++++++---------- platform/darwin/src/MLNStyleFilter.h | 2 +- platform/darwin/src/MLNStyleFilter_Private.h | 6 ++--- platform/ios/src/MLNMapView.h | 2 +- platform/ios/src/MLNMapView.mm | 12 ++++----- src/mbgl/plugin/plugin_style_filter.cpp | 2 -- src/mbgl/plugin/plugin_style_filter.hpp | 11 +++------ src/mbgl/style/style.cpp | 2 -- src/mbgl/style/style_impl.cpp | 7 ++---- src/mbgl/style/style_impl.hpp | 2 +- 11 files changed, 32 insertions(+), 42 deletions(-) diff --git a/include/mbgl/style/style.hpp b/include/mbgl/style/style.hpp index b143c5738c8d..f3e359c1b8b5 100644 --- a/include/mbgl/style/style.hpp +++ b/include/mbgl/style/style.hpp @@ -74,7 +74,7 @@ class Style { // Add style parsing filter void addStyleFilter(std::shared_ptr); - + // Private implementation class Impl; const std::unique_ptr impl; diff --git a/platform/darwin/app/StyleFilterExample.mm b/platform/darwin/app/StyleFilterExample.mm index ab6955136775..730e36b75f3d 100644 --- a/platform/darwin/app/StyleFilterExample.mm +++ b/platform/darwin/app/StyleFilterExample.mm @@ -5,54 +5,54 @@ @implementation StyleFilterExample // This will filter the data passed in -(NSData *)filterData:(NSData *)data { // Don't call super - + // This example will remove any layer that has "metal-rendering-layer" in the id - + // Parse the JSON: Make the containers mutable NSError *error = nil; NSMutableDictionary *styleDictionary = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error]; - + NSData *tempResult = data; if (styleDictionary) { - + // Get the layer array NSMutableArray *layerArray = [styleDictionary objectForKey:@"layers"]; - + // Create an array to hold which objects to remove since we can't remove them in the loop NSMutableArray *removedLayers = [NSMutableArray array]; - + // Loop the layers and look for any layers that have the search string in them for (NSMutableDictionary *layer in layerArray) { NSString *layerID = [layer objectForKey:@"id"]; - + // If we find the layers we're looking for, add them to the list of layers to remove if ([layerID containsString:@"metal-rendering-layer"]) { [removedLayers addObject:layer]; } } - + // Go through and remove any layers that were found for (NSMutableDictionary *l in removedLayers) { [layerArray removeObject:l]; } - + // Re-create the JSON, this time the layers we filtered out won't be there NSData *filteredStyleJSON = [NSJSONSerialization dataWithJSONObject:styleDictionary options:0 error:&error]; - + // If the JSON write is successful, then set the output to the new json style if (filteredStyleJSON) { tempResult = filteredStyleJSON; } - + } - + // Return the data return tempResult; - + } diff --git a/platform/darwin/src/MLNStyleFilter.h b/platform/darwin/src/MLNStyleFilter.h index 066d329c8469..d9a242ed6394 100644 --- a/platform/darwin/src/MLNStyleFilter.h +++ b/platform/darwin/src/MLNStyleFilter.h @@ -5,7 +5,7 @@ NS_ASSUME_NONNULL_BEGIN @interface MLNStyleFilter : NSObject // This will filter the data passed in --(NSData *)filterData:(NSData *)data; +- (NSData *)filterData:(NSData *)data; @end diff --git a/platform/darwin/src/MLNStyleFilter_Private.h b/platform/darwin/src/MLNStyleFilter_Private.h index f27864868d55..749cefcc7fd9 100644 --- a/platform/darwin/src/MLNStyleFilter_Private.h +++ b/platform/darwin/src/MLNStyleFilter_Private.h @@ -2,12 +2,12 @@ #ifndef MLNStyleFilter_Private_h #define MLNStyleFilter_Private_h -#import "MLNStyleFilter.h" #include +#import "MLNStyleFilter.h" -@interface MLNStyleFilter(Private) +@interface MLNStyleFilter (Private) --(void)setFilter:(std::shared_ptr)filter; +- (void)setFilter:(std::shared_ptr)filter; @end diff --git a/platform/ios/src/MLNMapView.h b/platform/ios/src/MLNMapView.h index decd8f9c12be..1e33c471fd93 100644 --- a/platform/ios/src/MLNMapView.h +++ b/platform/ios/src/MLNMapView.h @@ -2280,7 +2280,7 @@ vertically on the map. /** Adds a style filter to the map view */ --(void)addStyleFilter:(MLNStyleFilter *)styleFilter; +- (void)addStyleFilter:(MLNStyleFilter *)styleFilter; @end diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 0c1d1753c264..925e29f2a2f6 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -7811,15 +7811,15 @@ -(void)addPluginLayerType:(Class)pluginLayerClass { Adds a style filter to the map view */ -(void)addStyleFilter:(MLNStyleFilter *)styleFilter { - + if (!self.styleFilters) { self.styleFilters = [NSMutableArray array]; } [self.styleFilters addObject:styleFilter]; - + auto coreStyleFilter = std::make_shared(); coreStyleFilter->_filterStyleFunction = [styleFilter](const mbgl::Response &response) -> const mbgl::Response { - + mbgl::Response tempResult; @autoreleasepool { @@ -7847,12 +7847,12 @@ -(void)addStyleFilter:(MLNStyleFilter *)styleFilter { } return tempResult; }; - + // Set the ivar [styleFilter setFilter:coreStyleFilter]; - + _mbglMap->getStyle().addStyleFilter(coreStyleFilter); - + } diff --git a/src/mbgl/plugin/plugin_style_filter.cpp b/src/mbgl/plugin/plugin_style_filter.cpp index f30f7697fee2..a0908f492f72 100644 --- a/src/mbgl/plugin/plugin_style_filter.cpp +++ b/src/mbgl/plugin/plugin_style_filter.cpp @@ -4,11 +4,9 @@ using namespace mbgl::style; // This method const mbgl::Response PluginStyleFilter::FilterResponse(const Response& res) { - if (_filterStyleFunction) { auto tempResult = _filterStyleFunction(res); return tempResult; } return res; - } diff --git a/src/mbgl/plugin/plugin_style_filter.hpp b/src/mbgl/plugin/plugin_style_filter.hpp index 2cfd8ab26b6c..3527f64cbba8 100644 --- a/src/mbgl/plugin/plugin_style_filter.hpp +++ b/src/mbgl/plugin/plugin_style_filter.hpp @@ -2,22 +2,19 @@ #include - namespace mbgl { namespace style { class PluginStyleFilter { public: - - using OnFilterStyle = std::function; + using OnFilterStyle = std::function; OnFilterStyle _filterStyleFunction; - + // This method const Response FilterResponse(const Response& res); }; - -} -} +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index bba0362b5704..0caa94860549 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -181,9 +181,7 @@ std::unique_ptr Style::removeLayer(const std::string& id) { void Style::addStyleFilter(std::shared_ptr filter) { impl->mutated = true; return impl->addStyleFilter(filter); - } - } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/style_impl.cpp b/src/mbgl/style/style_impl.cpp index 850774a1e9cb..64082cf84cbb 100644 --- a/src/mbgl/style/style_impl.cpp +++ b/src/mbgl/style/style_impl.cpp @@ -81,16 +81,14 @@ void Style::Impl::loadURL(const std::string& url_) { } void Style::Impl::filterThenParse(const Response& res) { - Response tempResult = res; if (_styleFilters.size() > 0) { - for (auto filter: _styleFilters) { + for (auto filter : _styleFilters) { tempResult = filter->FilterResponse(tempResult); } } parse(*tempResult.data); -// parse(*res.data); - + // parse(*res.data); } void Style::Impl::parse(const std::string& json_) { @@ -252,7 +250,6 @@ void Style::Impl::addStyleFilter(std::shared_ptr _styleFilters.push_back(filter); } - void Style::Impl::setLight(std::unique_ptr light_) { light = std::move(light_); light->setObserver(this); diff --git a/src/mbgl/style/style_impl.hpp b/src/mbgl/style/style_impl.hpp index 9effde9d926b..3a518ce866ce 100644 --- a/src/mbgl/style/style_impl.hpp +++ b/src/mbgl/style/style_impl.hpp @@ -101,7 +101,7 @@ class Style::Impl : public SpriteLoaderObserver, void parse(const std::string&); std::vector> _styleFilters; - + std::shared_ptr fileSource; std::string url; From 58f352e0b548f89b3a39a7e4609bb8be14309687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Fri, 25 Jul 2025 13:38:50 -0400 Subject: [PATCH 121/221] Little bit of cleanup --- platform/darwin/app/StyleFilterExample.h | 7 ------- src/mbgl/style/style_impl.cpp | 15 +++++++++------ 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/platform/darwin/app/StyleFilterExample.h b/platform/darwin/app/StyleFilterExample.h index 47cfe9f6c4e2..ea694e6d4c3e 100644 --- a/platform/darwin/app/StyleFilterExample.h +++ b/platform/darwin/app/StyleFilterExample.h @@ -1,10 +1,3 @@ -// -// StyleFilterExample.h -// MapLibre -// -// Created by Malcolm Toon on 7/25/25. -// - #import "MLNStyleFilter.h" NS_ASSUME_NONNULL_BEGIN diff --git a/src/mbgl/style/style_impl.cpp b/src/mbgl/style/style_impl.cpp index 850774a1e9cb..e5571dda17ab 100644 --- a/src/mbgl/style/style_impl.cpp +++ b/src/mbgl/style/style_impl.cpp @@ -82,15 +82,18 @@ void Style::Impl::loadURL(const std::string& url_) { void Style::Impl::filterThenParse(const Response& res) { + if (_styleFilters.size() == 0) { + parse(*res.data); + return; + } + + // Otherwise, go through the chain of filters Response tempResult = res; - if (_styleFilters.size() > 0) { - for (auto filter: _styleFilters) { - tempResult = filter->FilterResponse(tempResult); - } + for (auto filter: _styleFilters) { + tempResult = filter->FilterResponse(tempResult); } parse(*tempResult.data); -// parse(*res.data); - + } void Style::Impl::parse(const std::string& json_) { From c817bff64f417426c685dba381206b4345997a51 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 25 Jul 2025 17:41:51 +0000 Subject: [PATCH 122/221] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/mbgl/style/style_impl.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/mbgl/style/style_impl.cpp b/src/mbgl/style/style_impl.cpp index e6432eeba6b5..16c699e4ece6 100644 --- a/src/mbgl/style/style_impl.cpp +++ b/src/mbgl/style/style_impl.cpp @@ -81,19 +81,17 @@ void Style::Impl::loadURL(const std::string& url_) { } void Style::Impl::filterThenParse(const Response& res) { - if (_styleFilters.size() == 0) { parse(*res.data); return; } - + // Otherwise, go through the chain of filters Response tempResult = res; - for (auto filter: _styleFilters) { + for (auto filter : _styleFilters) { tempResult = filter->FilterResponse(tempResult); } parse(*tempResult.data); - } void Style::Impl::parse(const std::string& json_) { From 4a540217e8e1c9ad65b97508f5e52109daf3597e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Fri, 25 Jul 2025 13:47:23 -0400 Subject: [PATCH 123/221] Added feature collections to cmake --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f24a62dc5d4..0713f3c78bb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -977,6 +977,10 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_properties.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_impl.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_factory.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/feature_collection.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/feature_collection.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/feature_collection_bucket.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/feature_collection_bucket.cpp ) From 987a384a2c7ccc145b505d929f69c199c7959edf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Fri, 25 Jul 2025 13:58:13 -0400 Subject: [PATCH 124/221] Removing array type for now --- src/mbgl/plugin/feature_collection_bucket.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mbgl/plugin/feature_collection_bucket.cpp b/src/mbgl/plugin/feature_collection_bucket.cpp index f4797a2b88f2..eb002d98f9c0 100644 --- a/src/mbgl/plugin/feature_collection_bucket.cpp +++ b/src/mbgl/plugin/feature_collection_bucket.cpp @@ -134,9 +134,9 @@ void FeatureCollectionBucket::addFeature(const GeometryTileFeature& tileFeature, } else if (auto b = value.getBool()) { // std::cout << "Found Bool: " << name << ": " << *b << "\n"; tempFeature->_featureProperties[name] = std::to_string(*b); - } else if (auto a = value.getArray()) { - // std::cout << "Found Array: " << name << ": " << *b << "\n"; - tempFeature->_featureProperties[name] = std::to_string(*b); +// } else if (auto a = value.getArray()) { +// // std::cout << "Found Array: " << name << ": " << *b << "\n"; +// tempFeature->_featureProperties[name] = std::to_string(*b); } // DECLARE_VALUE_TYPE_ACCESOR(Array, array_type) From 37f8e673c105b2853652a994fbb601d1265cb708 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 25 Jul 2025 17:58:44 +0000 Subject: [PATCH 125/221] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/mbgl/plugin/feature_collection_bucket.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mbgl/plugin/feature_collection_bucket.cpp b/src/mbgl/plugin/feature_collection_bucket.cpp index eb002d98f9c0..4abc7a1d5e6d 100644 --- a/src/mbgl/plugin/feature_collection_bucket.cpp +++ b/src/mbgl/plugin/feature_collection_bucket.cpp @@ -134,9 +134,9 @@ void FeatureCollectionBucket::addFeature(const GeometryTileFeature& tileFeature, } else if (auto b = value.getBool()) { // std::cout << "Found Bool: " << name << ": " << *b << "\n"; tempFeature->_featureProperties[name] = std::to_string(*b); -// } else if (auto a = value.getArray()) { -// // std::cout << "Found Array: " << name << ": " << *b << "\n"; -// tempFeature->_featureProperties[name] = std::to_string(*b); + // } else if (auto a = value.getArray()) { + // // std::cout << "Found Array: " << name << ": " << *b << "\n"; + // tempFeature->_featureProperties[name] = std::to_string(*b); } // DECLARE_VALUE_TYPE_ACCESOR(Array, array_type) From 8654fc28fead118c4d09934754289e911a37929f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sat, 26 Jul 2025 00:07:32 -0400 Subject: [PATCH 126/221] Cleanp --- platform/darwin/app/PluginLayerExample.mm | 33 ++++++--- platform/darwin/app/PluginLayerTestStyle.json | 2 +- src/mbgl/plugin/feature_collection.cpp | 7 -- src/mbgl/plugin/feature_collection.hpp | 14 +--- src/mbgl/plugin/feature_collection_bucket.cpp | 69 +------------------ src/mbgl/plugin/feature_collection_bucket.hpp | 62 +---------------- 6 files changed, 28 insertions(+), 159 deletions(-) diff --git a/platform/darwin/app/PluginLayerExample.mm b/platform/darwin/app/PluginLayerExample.mm index 13c40d8e3794..18ab587bf03b 100644 --- a/platform/darwin/app/PluginLayerExample.mm +++ b/platform/darwin/app/PluginLayerExample.mm @@ -1,5 +1,14 @@ #import "PluginLayerExample.h" +@interface PluginLayerExample () { + +} + +@property BOOL logFeatures; + +@end + + @implementation PluginLayerExample @@ -14,6 +23,13 @@ +(MLNPluginLayerCapabilities *)layerCapabilities { } +-(id)init { + if (self = [super init]) { + self.logFeatures = NO; + } + return self; +} + // The overrides -(void)onRenderLayer:(MLNMapView *)mapView renderEncoder:(id)renderEncoder { @@ -25,27 +41,26 @@ -(void)onUpdateLayer { } -//-(void)onBucketLoaded:(MLNRawBucket *)bucket { -// -//} - -(void)onUpdateLayerProperties:(NSDictionary *)layerProperties { // NSLog(@"Layer Properties: %@", layerProperties); } -(void)featureLoaded:(MLNPluginLayerTileFeature *)tileFeature { - NSLog(@"Tile Feature (id:%@) Properties: %@", tileFeature.featureID, tileFeature.featureProperties); + + // Writing a single string since the tile loading is multithreaded and the output can get interwoven + NSMutableString *outputStr = [NSMutableString string]; + [outputStr appendFormat:@"Tile Feature (id:%@) Properties: %@\n", tileFeature.featureID, tileFeature.featureProperties]; for (NSValue *v in tileFeature.featureCoordinates) { - -// NSValue *value = [NSValue valueWithBytes:&c objCType:@encode(CLLocationCoordinate2D)]; -// [featureCoordinates addObject:value]; - CLLocationCoordinate2D coord; [v getValue:&coord]; + + [outputStr appendFormat:@" -> (%f, %f) \n", coord.latitude, coord.longitude]; } + + NSLog(@"Feature: %@", outputStr); } -(void)featureUnloaded:(MLNPluginLayerTileFeature *)tileFeature { diff --git a/platform/darwin/app/PluginLayerTestStyle.json b/platform/darwin/app/PluginLayerTestStyle.json index 826236d2a135..b650177ef0f7 100644 --- a/platform/darwin/app/PluginLayerTestStyle.json +++ b/platform/darwin/app/PluginLayerTestStyle.json @@ -586,7 +586,7 @@ { "id": "centroid-features", "type": "maplibre::filter_features", "source": "maplibre", - "source-layer": "centroids", + "source-layer": "countries", "maxzoom": 24, "minzoom": 1 }, diff --git a/src/mbgl/plugin/feature_collection.cpp b/src/mbgl/plugin/feature_collection.cpp index c5d067494a8a..46d2cdf7e994 100644 --- a/src/mbgl/plugin/feature_collection.cpp +++ b/src/mbgl/plugin/feature_collection.cpp @@ -1,8 +1 @@ -// -// feature_collection.cpp -// App -// -// Created by Malcolm Toon on 7/15/25. -// - #include "feature_collection.hpp" diff --git a/src/mbgl/plugin/feature_collection.hpp b/src/mbgl/plugin/feature_collection.hpp index 8b75ebada98f..bf3b4382d1de 100644 --- a/src/mbgl/plugin/feature_collection.hpp +++ b/src/mbgl/plugin/feature_collection.hpp @@ -1,12 +1,4 @@ -// -// feature_collection.hpp -// App -// -// Created by Malcolm Toon on 7/15/25. -// - -#ifndef feature_collection_hpp -#define feature_collection_hpp +#pragma once #include @@ -19,9 +11,6 @@ namespace mbgl { namespace plugin { -// using FillBinders = PaintPropertyBinders; -// using FillLayoutVertex = gfx::Vertex>; - class FeatureCoordinate { public: FeatureCoordinate(double lat, double lon) @@ -70,4 +59,3 @@ class FeatureCollection { } // namespace mbgl -#endif /* feature_collection_hpp */ diff --git a/src/mbgl/plugin/feature_collection_bucket.cpp b/src/mbgl/plugin/feature_collection_bucket.cpp index 4abc7a1d5e6d..eec24af37c63 100644 --- a/src/mbgl/plugin/feature_collection_bucket.cpp +++ b/src/mbgl/plugin/feature_collection_bucket.cpp @@ -1,17 +1,8 @@ -// -// raw_bucket.cpp -// App -// -// Created by Malcolm Toon on 7/3/25. -// - #include #include #include #include -#include - using namespace mbgl; FeatureCollectionBucket::~FeatureCollectionBucket() {} @@ -47,10 +38,6 @@ void geometryToLatLon(const GeometryCoordinate& coord, } std::string toString(FeatureIdentifier& v) { - // auto v = toValue(value); - - // null_value_t, uint64_t, int64_t, double, std::string> - std::string tempResult = ""; auto ti = v.which(); if (ti == 0) { @@ -63,23 +50,6 @@ std::string toString(FeatureIdentifier& v) { tempResult = v.get(); } return tempResult; - /* - if (auto iVal = v.value().getInt()) { - std::string tempResult = std::to_string(*iVal); - output.append(tempResult); - } else if (auto uIVal = v.value().getUint()) { - std::string tempResult = std::to_string(*uIVal); - output.append(tempResult); - - } else if (auto s = v.value().getString()) { - output.append("\""); - output.append(s->c_str()); - output.append("\""); - - } else if (auto d = v.value().getDouble()) { - output.append(std::to_string(*d)); - } - */ } void FeatureCollectionBucket::addFeature(const GeometryTileFeature& tileFeature, @@ -96,18 +66,14 @@ void FeatureCollectionBucket::addFeature(const GeometryTileFeature& tileFeature, switch (tileFeature.getType()) { case FeatureType::Point: - // std::cout << "Adding Point" << "\n"; tempFeature->_featureType = plugin::Feature::FeatureType::FeatureTypePoint; break; case FeatureType::Unknown: - // std::cout << "Unknown Type Found\n"; break; case FeatureType::LineString: - // std::cout << "LineString Type Found\n"; tempFeature->_featureType = plugin::Feature::FeatureType::FeatureTypeLine; break; case FeatureType::Polygon: - // std::cout << "Polygon Type Found\n"; tempFeature->_featureType = plugin::Feature::FeatureType::FeatureTypePolygon; break; } @@ -118,29 +84,20 @@ void FeatureCollectionBucket::addFeature(const GeometryTileFeature& tileFeature, mapbox::feature::value value = p.second; if (auto iVal = value.getInt()) { - std::cout << "Found Int: " << name << ": " << *iVal << "\n"; tempFeature->_featureProperties[name] = std::to_string(*iVal); } else if (auto uIVal = value.getUint()) { - std::cout << "Found UInt: " << name << ": " << *uIVal << "\n"; tempFeature->_featureProperties[name] = std::to_string(*uIVal); - } else if (auto s = value.getString()) { - // std::cout << "Found String: " << name << ": " << *s << "\n"; tempFeature->_featureProperties[name] = *s; - } else if (auto d = value.getDouble()) { - // std::cout << "Found Double: " << name << ": " << *d << "\n"; tempFeature->_featureProperties[name] = std::to_string(*d); } else if (auto b = value.getBool()) { - // std::cout << "Found Bool: " << name << ": " << *b << "\n"; tempFeature->_featureProperties[name] = std::to_string(*b); + // TODO: Add array type // } else if (auto a = value.getArray()) { - // // std::cout << "Found Array: " << name << ": " << *b << "\n"; // tempFeature->_featureProperties[name] = std::to_string(*b); } - // DECLARE_VALUE_TYPE_ACCESOR(Array, array_type) - // DECLARE_VALUE_TYPE_ACCESOR(Object, object_type) } LatLngBounds b(tileID); @@ -150,21 +107,10 @@ void FeatureCollectionBucket::addFeature(const GeometryTileFeature& tileFeature, plugin::FeatureCoordinateCollection c; for (std::size_t i = 0, len = g.size(); i < len; i++) { const GeometryCoordinate& p1 = g[i]; - auto d = b.west(); - - // auto c = project( - - // void geometryToLatLon( - // const GeometryCoordinate& coord, - // int tileX, int tileY, int zoom, - // double& lat, double& lon, - // int extent = 8192, - // int tileSize = 512 double lat = 0; double lon = 0; geometryToLatLon(p1, tileID.x, tileID.y, tileID.z, lat, lon); - c._coordinates.push_back(plugin::FeatureCoordinate(lat, lon)); } tempFeature->_featureCoordinates.push_back(c); @@ -179,20 +125,9 @@ void FeatureCollectionBucket::addFeature(const GeometryTileFeature& tileFeature, pluginLayer->_featureLoadedFunction(tempFeature); } } - // auto pluginLayer = std::dynamic_pointer_cast>(bi); - - // auto pluginLayer = std::dynamic_pointer_cast(l->baseImpl); - // if (pluginLayer != nullptr) { - // if (pluginLayer->_featureLoadedFunction != nullptr) { - // pluginLayer->_featureLoadedFunction(tempFeature); - // } - // } } _featureCollection->_features.push_back(tempFeature); - // _features.push_back(tempFeature); - - // std::cout << "Adding Feature Type: " << tileFeature.getType() << "\n"; } bool FeatureCollectionBucket::hasData() const { @@ -200,7 +135,6 @@ bool FeatureCollectionBucket::hasData() const { } void FeatureCollectionBucket::upload(gfx::UploadPass&) { - std::cout << "FeatureCollectionBucket::upload\n"; uploaded = true; } @@ -212,5 +146,4 @@ void FeatureCollectionBucket::update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) { - std::cout << "FeatureCollectionBucket::update\n"; } diff --git a/src/mbgl/plugin/feature_collection_bucket.hpp b/src/mbgl/plugin/feature_collection_bucket.hpp index ec5ae03e7a0a..4f6c6768ba81 100644 --- a/src/mbgl/plugin/feature_collection_bucket.hpp +++ b/src/mbgl/plugin/feature_collection_bucket.hpp @@ -11,31 +11,6 @@ #include -/* - - Open Questions - - - * Should we load up a vector of these RawFeatures by tile? - * How does that interop with the render layer's update flow - * Should the call back from render layer be more of a batch thing at that update stage? - * Should there be a callback when a tile or collection of these features go out of scope? - * Should the concept of managing arrays of features be something done by the core or just - hand off the features to the plug-in layer and let it do it's thing or have the option for both? - - * How do we get to the osm id of features in the stream? Is that tileFeature.getID()? - * Is there already a set of classes or a paradigm out there that could be used to represent the - feature / feature geometry? - * What are the "binders"? - - - Thoughts - * Possibly have ability to keep tile coordinates using some kind flag - - - - */ - namespace mbgl { class BucketParameters; @@ -66,45 +41,10 @@ class FeatureCollectionBucket final : public Bucket { // The tile ID OverscaledTileID _tileID; - // Array of features + // Feature collection is an list of features std::shared_ptr _featureCollection = nullptr; - // std::vector> _features; - std::vector> _layers; - /* - static FillLayoutVertex layoutVertex(Point p) { return FillLayoutVertex{{{p.x, p.y}}}; } - -#if MLN_TRIANGULATE_FILL_OUTLINES - using LineVertexVector = gfx::VertexVector; - const std::shared_ptr sharedLineVertices = std::make_shared(); - LineVertexVector& lineVertices = *sharedLineVertices; - - using LineIndexVector = gfx::IndexVector; - const std::shared_ptr sharedLineIndexes = std::make_shared(); - LineIndexVector& lineIndexes = *sharedLineIndexes; - - SegmentVector lineSegments; -#endif // MLN_TRIANGULATE_FILL_OUTLINES - - using BasicLineIndexVector = gfx::IndexVector; - const std::shared_ptr sharedBasicLineIndexes = std::make_shared(); - BasicLineIndexVector& basicLines = *sharedBasicLineIndexes; - - SegmentVector basicLineSegments; - - using VertexVector = gfx::VertexVector; - const std::shared_ptr sharedVertices = std::make_shared(); - VertexVector& vertices = *sharedVertices; - - using TriangleIndexVector = gfx::IndexVector; - const std::shared_ptr sharedTriangles = std::make_shared(); - TriangleIndexVector& triangles = *sharedTriangles; - - SegmentVector triangleSegments; - - std::map paintPropertyBinders; - */ }; } // namespace mbgl From 535927b1bac2eff3abb786acc34749790aa9a3ad Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 26 Jul 2025 04:08:38 +0000 Subject: [PATCH 127/221] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- platform/darwin/app/PluginLayerExample.mm | 8 ++++---- src/mbgl/plugin/feature_collection.hpp | 1 - src/mbgl/plugin/feature_collection_bucket.cpp | 6 ++---- src/mbgl/plugin/feature_collection_bucket.hpp | 1 - 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/platform/darwin/app/PluginLayerExample.mm b/platform/darwin/app/PluginLayerExample.mm index 18ab587bf03b..92d7056a0f19 100644 --- a/platform/darwin/app/PluginLayerExample.mm +++ b/platform/darwin/app/PluginLayerExample.mm @@ -1,7 +1,7 @@ #import "PluginLayerExample.h" @interface PluginLayerExample () { - + } @property BOOL logFeatures; @@ -46,7 +46,7 @@ -(void)onUpdateLayerProperties:(NSDictionary *)layerProperties { } -(void)featureLoaded:(MLNPluginLayerTileFeature *)tileFeature { - + // Writing a single string since the tile loading is multithreaded and the output can get interwoven NSMutableString *outputStr = [NSMutableString string]; [outputStr appendFormat:@"Tile Feature (id:%@) Properties: %@\n", tileFeature.featureID, tileFeature.featureProperties]; @@ -55,11 +55,11 @@ -(void)featureLoaded:(MLNPluginLayerTileFeature *)tileFeature { CLLocationCoordinate2D coord; [v getValue:&coord]; - + [outputStr appendFormat:@" -> (%f, %f) \n", coord.latitude, coord.longitude]; } - + NSLog(@"Feature: %@", outputStr); } diff --git a/src/mbgl/plugin/feature_collection.hpp b/src/mbgl/plugin/feature_collection.hpp index bf3b4382d1de..5ea0c639e571 100644 --- a/src/mbgl/plugin/feature_collection.hpp +++ b/src/mbgl/plugin/feature_collection.hpp @@ -58,4 +58,3 @@ class FeatureCollection { } // namespace plugin } // namespace mbgl - diff --git a/src/mbgl/plugin/feature_collection_bucket.cpp b/src/mbgl/plugin/feature_collection_bucket.cpp index eec24af37c63..9ef46fd84df8 100644 --- a/src/mbgl/plugin/feature_collection_bucket.cpp +++ b/src/mbgl/plugin/feature_collection_bucket.cpp @@ -93,11 +93,10 @@ void FeatureCollectionBucket::addFeature(const GeometryTileFeature& tileFeature, tempFeature->_featureProperties[name] = std::to_string(*d); } else if (auto b = value.getBool()) { tempFeature->_featureProperties[name] = std::to_string(*b); - // TODO: Add array type + // TODO: Add array type // } else if (auto a = value.getArray()) { // tempFeature->_featureProperties[name] = std::to_string(*b); } - } LatLngBounds b(tileID); @@ -145,5 +144,4 @@ float FeatureCollectionBucket::getQueryRadius(const RenderLayer&) const { void FeatureCollectionBucket::update(const FeatureStates&, const GeometryTileLayer&, const std::string&, - const ImagePositions&) { -} + const ImagePositions&) {} diff --git a/src/mbgl/plugin/feature_collection_bucket.hpp b/src/mbgl/plugin/feature_collection_bucket.hpp index 4f6c6768ba81..ccb28d35d018 100644 --- a/src/mbgl/plugin/feature_collection_bucket.hpp +++ b/src/mbgl/plugin/feature_collection_bucket.hpp @@ -44,7 +44,6 @@ class FeatureCollectionBucket final : public Bucket { // Feature collection is an list of features std::shared_ptr _featureCollection = nullptr; std::vector> _layers; - }; } // namespace mbgl From faeb360db26d6995a8c50fa0d2c657df86f97f1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sat, 26 Jul 2025 00:29:59 -0400 Subject: [PATCH 128/221] Changed to filter the loadJSON path as well --- platform/ios/src/MLNMapView.mm | 25 +++++-------------------- src/mbgl/plugin/plugin_style_filter.cpp | 4 ++-- src/mbgl/plugin/plugin_style_filter.hpp | 4 ++-- src/mbgl/style/style_impl.cpp | 16 +++++++++------- src/mbgl/style/style_impl.hpp | 2 +- 5 files changed, 19 insertions(+), 32 deletions(-) diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 925e29f2a2f6..fa072faec42e 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -7818,31 +7818,16 @@ -(void)addStyleFilter:(MLNStyleFilter *)styleFilter { [self.styleFilters addObject:styleFilter]; auto coreStyleFilter = std::make_shared(); - coreStyleFilter->_filterStyleFunction = [styleFilter](const mbgl::Response &response) -> const mbgl::Response { + coreStyleFilter->_filterStyleFunction = [styleFilter](const std::string &filterData) -> const std::string { - mbgl::Response tempResult; + std::string tempResult; @autoreleasepool { - NSData *sourceData = [NSData dataWithBytesNoCopy:(void *)response.data->data() - length:response.data->size() + NSData *sourceData = [NSData dataWithBytesNoCopy:(void *)filterData.data() + length:filterData.size() freeWhenDone:NO]; NSData *filteredData = [styleFilter filterData:sourceData]; - if (response.error) { - tempResult.error = std::make_unique(response.error->reason, - response.error->message, - response.error->retryAfter); - } - tempResult.noContent = response.noContent; - tempResult.notModified = response.notModified; - tempResult.mustRevalidate = response.mustRevalidate; - tempResult.modified = response.modified; - tempResult.expires = response.expires; - tempResult.etag = response.etag; - - // Set the response data - tempResult.data = - std::make_shared((const char*)[filteredData bytes], [filteredData length]); - + tempResult = std::string((const char*)[filteredData bytes], [filteredData length]); } return tempResult; diff --git a/src/mbgl/plugin/plugin_style_filter.cpp b/src/mbgl/plugin/plugin_style_filter.cpp index a0908f492f72..546de4f2c7aa 100644 --- a/src/mbgl/plugin/plugin_style_filter.cpp +++ b/src/mbgl/plugin/plugin_style_filter.cpp @@ -2,8 +2,8 @@ using namespace mbgl::style; -// This method -const mbgl::Response PluginStyleFilter::FilterResponse(const Response& res) { +// This method will call the lambda if it exists +const std::string PluginStyleFilter::filterResponse(const std::string& res) { if (_filterStyleFunction) { auto tempResult = _filterStyleFunction(res); return tempResult; diff --git a/src/mbgl/plugin/plugin_style_filter.hpp b/src/mbgl/plugin/plugin_style_filter.hpp index 3527f64cbba8..9d12703fbf99 100644 --- a/src/mbgl/plugin/plugin_style_filter.hpp +++ b/src/mbgl/plugin/plugin_style_filter.hpp @@ -8,12 +8,12 @@ namespace style { class PluginStyleFilter { public: - using OnFilterStyle = std::function; + using OnFilterStyle = std::function; OnFilterStyle _filterStyleFunction; // This method - const Response FilterResponse(const Response& res); + const std::string filterResponse(const std::string& styleData); }; } // namespace style diff --git a/src/mbgl/style/style_impl.cpp b/src/mbgl/style/style_impl.cpp index 16c699e4ece6..b42eaa9a5d49 100644 --- a/src/mbgl/style/style_impl.cpp +++ b/src/mbgl/style/style_impl.cpp @@ -45,7 +45,7 @@ void Style::Impl::loadJSON(const std::string& json_) { observer->onStyleLoading(); url.clear(); - parse(json_); + filterThenParse(json_); } void Style::Impl::loadURL(const std::string& url_) { @@ -75,25 +75,27 @@ void Style::Impl::loadURL(const std::string& url_) { } else if (res.notModified || res.noContent) { return; } else { - filterThenParse(res); + filterThenParse(*res.data); } }); } -void Style::Impl::filterThenParse(const Response& res) { + +void Style::Impl::filterThenParse(const std::string& styleData) { if (_styleFilters.size() == 0) { - parse(*res.data); + parse(styleData); return; } // Otherwise, go through the chain of filters - Response tempResult = res; + std::string filteredStyle = styleData; for (auto filter : _styleFilters) { - tempResult = filter->FilterResponse(tempResult); + filteredStyle = filter->filterResponse(filteredStyle); } - parse(*tempResult.data); + parse(filteredStyle); } + void Style::Impl::parse(const std::string& json_) { Parser parser; diff --git a/src/mbgl/style/style_impl.hpp b/src/mbgl/style/style_impl.hpp index 3a518ce866ce..ef4877a4f6c4 100644 --- a/src/mbgl/style/style_impl.hpp +++ b/src/mbgl/style/style_impl.hpp @@ -69,7 +69,7 @@ class Style::Impl : public SpriteLoaderObserver, // Add style parsing filter void addStyleFilter(std::shared_ptr); - void filterThenParse(const Response& res); + void filterThenParse(const std::string& styleData); std::string getName() const; CameraOptions getDefaultCamera() const; From 9337cf1de85fe32c017a01830a35c0ffdf7b9075 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 26 Jul 2025 04:30:30 +0000 Subject: [PATCH 129/221] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/mbgl/style/style_impl.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mbgl/style/style_impl.cpp b/src/mbgl/style/style_impl.cpp index b42eaa9a5d49..fb09eb396315 100644 --- a/src/mbgl/style/style_impl.cpp +++ b/src/mbgl/style/style_impl.cpp @@ -80,7 +80,6 @@ void Style::Impl::loadURL(const std::string& url_) { }); } - void Style::Impl::filterThenParse(const std::string& styleData) { if (_styleFilters.size() == 0) { parse(styleData); @@ -95,7 +94,6 @@ void Style::Impl::filterThenParse(const std::string& styleData) { parse(filteredStyle); } - void Style::Impl::parse(const std::string& json_) { Parser parser; From b10ecb07b9061ac86a27414692c61cb8d4b407d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sat, 26 Jul 2025 00:35:04 -0400 Subject: [PATCH 130/221] Minor cleanup --- src/mbgl/style/style_impl.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mbgl/style/style_impl.hpp b/src/mbgl/style/style_impl.hpp index ef4877a4f6c4..7a203b7074d7 100644 --- a/src/mbgl/style/style_impl.hpp +++ b/src/mbgl/style/style_impl.hpp @@ -28,7 +28,6 @@ namespace mbgl { class FileSource; class AsyncRequest; class SpriteLoader; -class Response; namespace style { @@ -69,7 +68,6 @@ class Style::Impl : public SpriteLoaderObserver, // Add style parsing filter void addStyleFilter(std::shared_ptr); - void filterThenParse(const std::string& styleData); std::string getName() const; CameraOptions getDefaultCamera() const; @@ -98,6 +96,7 @@ class Style::Impl : public SpriteLoaderObserver, bool loaded = false; private: + void filterThenParse(const std::string& styleData); void parse(const std::string&); std::vector> _styleFilters; From 432f16f4f42471123dd99825e9e424c22b6ded3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sat, 26 Jul 2025 00:44:50 -0400 Subject: [PATCH 131/221] Cleanup cruft --- src/mbgl/plugin/feature_collection.hpp | 3 - src/mbgl/plugin/plugin_layer_render.cpp | 95 ------------------------- 2 files changed, 98 deletions(-) diff --git a/src/mbgl/plugin/feature_collection.hpp b/src/mbgl/plugin/feature_collection.hpp index 5ea0c639e571..a4199a110747 100644 --- a/src/mbgl/plugin/feature_collection.hpp +++ b/src/mbgl/plugin/feature_collection.hpp @@ -49,9 +49,6 @@ class FeatureCollection { FeatureCollection(OverscaledTileID tileID) : _featureCollectionTileID(tileID) {}; std::vector> _features; - - // TODO: Open question about this.. should feature collections be tied to tile id? - // TODO: Question: Is overscaled the right thing or just canonical? OverscaledTileID _featureCollectionTileID; }; diff --git a/src/mbgl/plugin/plugin_layer_render.cpp b/src/mbgl/plugin/plugin_layer_render.cpp index 64cd64f547d7..8b57e8d071eb 100644 --- a/src/mbgl/plugin/plugin_layer_render.cpp +++ b/src/mbgl/plugin/plugin_layer_render.cpp @@ -13,11 +13,6 @@ #include #include #include - -// TODO: Remove -#include -// #define C_LOG_TILES 1 - #include #include @@ -95,15 +90,6 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis std::vector removedTiles; bool removeAllTiles = ((renderTiles == nullptr) || (renderTiles->empty())); - // TODO: Remove -#ifdef C_LOG_TILES - static int passCount = 0; - passCount++; - if (removeAllTiles) { - std::cout << passCount << ": Remove All Tiles\n"; - } -#endif - // Get list of tiles to remove and then remove them for (auto currentCollection : _featureCollectionByTile) { if (removeAllTiles || !hasRenderTile(currentCollection.first)) { @@ -116,11 +102,6 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis if (pluginLayer._featureCollectionUnloadedFunction) { pluginLayer._featureCollectionUnloadedFunction(featureCollection); } -#ifdef C_LOG_TILES - // TODO: Remove this logging - std::cout << passCount << ": Removing Feature Collection for Tile: " << (int)tileID.canonical.z << "," - << tileID.canonical.x << "," << tileID.canonical.y << "\n"; -#endif _featureCollectionByTile.erase(tileID); } } @@ -135,16 +116,8 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis const auto& tileID = tile.getOverscaledTileID(); if (!hasRenderTile(tileID)) { -#ifdef C_LOG_TILES - std::cout << passCount << ": Tile was there and not anymore\n"; -#endif } - // TODO: Remove - // if ((tileID.canonical.x == 1289) && (tileID.canonical.y == 879)) { - // std::cout << "Found tile\n"; - // } - const auto* optRenderData = getRenderDataForPass(tile, drawPass); if (!optRenderData || !optRenderData->bucket || !optRenderData->bucket->hasData()) { removeTile(drawPass, tileID); @@ -152,8 +125,6 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis } const auto& renderData = *optRenderData; auto& bucket = static_cast(*renderData.bucket); - // TODO: Remove - // std::cout << "Found Bucket\n"; auto featureCollection = bucket._featureCollection; if (featureCollection == nullptr) { continue; @@ -172,72 +143,12 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis if (pluginLayer._featureCollectionLoadedFunction) { if (featureCollection != nullptr) { pluginLayer._featureCollectionLoadedFunction(featureCollection); -#ifdef C_LOG_TILES - // TODO: Remove logging - std::cout << passCount << ": Adding Feature Collection for Tile: " << (int)tileID.canonical.z - << "," << tileID.canonical.x << "," << tileID.canonical.y << "\n"; -#endif } } - - /* - - const auto prevBucketID = getRenderTileBucketID(tileID); - if (prevBucketID != util::SimpleIdentity::Empty && prevBucketID != bucket.getID()) { - // This tile was previously set up from a different bucket, drop and re-create any drawables for it. - removeTile(drawPass, tileID); - } - setRenderTileBucketID(tileID, bucket.getID()); - */ } } } - /* - if (!renderTiles || renderTiles->empty() || passes == RenderPass::None) { -// removeAllDrawables(); - return; - } - - // Set up a layer group - if (!layerGroup) { - if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, - 64, // initialCapacity= - getID())) { - setLayerGroup(std::move(layerGroup_), changes); - } else { - return; - } - } - - auto* tileLayerGroup = static_cast(layerGroup.get()); - -// const auto& evaluated = static_cast(*evaluatedProperties).evaluated; - - constexpr auto drawPass = RenderPass::Translucent; - - for (const RenderTile& tile : *renderTiles) { - const auto& tileID = tile.getOverscaledTileID(); - - const auto* optRenderData = getRenderDataForPass(tile, drawPass); - if (!optRenderData || !optRenderData->bucket || !optRenderData->bucket->hasData()) { - removeTile(drawPass, tileID); - continue; - } - - const auto& renderData = *optRenderData; - auto& bucket = static_cast(*renderData.bucket); - - const auto prevBucketID = getRenderTileBucketID(tileID); - if (prevBucketID != util::SimpleIdentity::Empty && prevBucketID != bucket.getID()) { - // This tile was previously set up from a different bucket, drop and re-create any drawables for it. - removeTile(drawPass, tileID); - } - setRenderTileBucketID(tileID, bucket.getID()); - } - - */ - // create layer group if (!layerGroup) { if (auto layerGroup_ = context.createLayerGroup(layerIndex, /*initialCapacity=*/1, getID())) { @@ -321,17 +232,11 @@ void RenderPluginLayer::evaluate(const PropertyEvaluationParameters& parameters) } std::string jsonProperties = pm.propertiesAsJSON(); - i->_updateLayerPropertiesFunction(jsonProperties); auto properties = makeMutable( staticImmutableCast(baseImpl)); passes = RenderPass::Pass3D; - // passes = RenderPass::Pass3D; (evaluated.get().constantOr(1.0) > 0 && - // evaluated.get().constantOr(Color::black()).a > 0 && - // evaluated.get().constantOr(1.0) > 0) - // ? RenderPass::Translucent - // : RenderPass::None; properties->renderPasses = mbgl::underlying_type(passes); evaluatedProperties = std::move(properties); } From 4413910bc629454efd2b900aa606653616f1ff47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sat, 26 Jul 2025 00:52:42 -0400 Subject: [PATCH 132/221] Added style filter to cmake list --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f24a62dc5d4..6b5235795c08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -972,11 +972,13 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_properties.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_impl.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_factory.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_style_filter.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_render.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_properties.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_impl.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_factory.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_style_filter.cpp ) From 2c0c768602d35fc6ca091c1992e8afaeddd9c8d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sat, 26 Jul 2025 00:58:50 -0400 Subject: [PATCH 133/221] Added header to fix build error --- src/mbgl/plugin/plugin_style_filter.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mbgl/plugin/plugin_style_filter.hpp b/src/mbgl/plugin/plugin_style_filter.hpp index 9d12703fbf99..985c0ea59fe9 100644 --- a/src/mbgl/plugin/plugin_style_filter.hpp +++ b/src/mbgl/plugin/plugin_style_filter.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include namespace mbgl { From b6a59e3a6307fc5a4340bf452792920c9d3899e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sat, 26 Jul 2025 13:14:10 -0400 Subject: [PATCH 134/221] Initial commit of adding support for custom protocols --- bazel/core.bzl | 1 + include/mbgl/storage/file_source.hpp | 3 +- include/mbgl/storage/file_source_manager.hpp | 6 + platform/BUILD.bazel | 2 + platform/darwin/BUILD.bazel | 2 + platform/darwin/app/PluginProtocolExample.h | 9 ++ platform/darwin/app/PluginProtocolExample.mm | 23 +++ platform/darwin/bazel/files.bzl | 4 +- .../darwin/src/MLNPluginProtocolHandler.h | 25 +++ .../darwin/src/MLNPluginProtocolHandler.mm | 23 +++ platform/default/BUILD.bazel | 1 + .../src/mbgl/storage/main_resource_loader.cpp | 114 +++++++------ .../src/mbgl/storage/plugin_file_source.cpp | 153 ++++++++++++++++++ platform/ios/app/MBXViewController.mm | 9 +- platform/ios/src/MLNMapView.h | 5 + platform/ios/src/MLNMapView.mm | 71 +++++++- src/mbgl/plugin/plugin_file_source.hpp | 52 ++++++ src/mbgl/storage/file_source_manager.cpp | 35 ++-- 18 files changed, 477 insertions(+), 61 deletions(-) create mode 100644 platform/darwin/app/PluginProtocolExample.h create mode 100644 platform/darwin/app/PluginProtocolExample.mm create mode 100644 platform/darwin/src/MLNPluginProtocolHandler.h create mode 100644 platform/darwin/src/MLNPluginProtocolHandler.mm create mode 100644 platform/default/src/mbgl/storage/plugin_file_source.cpp create mode 100644 src/mbgl/plugin/plugin_file_source.hpp diff --git a/bazel/core.bzl b/bazel/core.bzl index b27bbd8d925b..58b35f7aa3ee 100644 --- a/bazel/core.bzl +++ b/bazel/core.bzl @@ -4,6 +4,7 @@ MLN_LAYER_PLUGIN_HEADERS = [ "src/mbgl/plugin/plugin_layer_impl.hpp", "src/mbgl/plugin/plugin_layer_render.hpp", "src/mbgl/plugin/plugin_layer_properties.hpp", + "src/mbgl/plugin/plugin_file_source.hpp", ] MLN_LAYER_PLUGIN_SOURCE = [ diff --git a/include/mbgl/storage/file_source.hpp b/include/mbgl/storage/file_source.hpp index 6a70154df417..13626bf13103 100644 --- a/include/mbgl/storage/file_source.hpp +++ b/include/mbgl/storage/file_source.hpp @@ -26,9 +26,10 @@ enum FileSourceType : uint8_t { Network, Mbtiles, Pmtiles, - ResourceLoader ///< %Resource loader acts as a proxy and has logic + ResourceLoader, ///< %Resource loader acts as a proxy and has logic /// for request delegation to Asset, Cache, and other /// file sources. + Custom // These are the plugin file resource types }; // TODO: Rename to ResourceProvider to avoid confusion with diff --git a/include/mbgl/storage/file_source_manager.hpp b/include/mbgl/storage/file_source_manager.hpp index b6ef59c09b35..78d80464768f 100644 --- a/include/mbgl/storage/file_source_manager.hpp +++ b/include/mbgl/storage/file_source_manager.hpp @@ -43,6 +43,12 @@ class FileSourceManager { // a FileSourceType invocation has no effect. virtual FileSourceFactory unRegisterFileSourceFactory(FileSourceType) noexcept; + // Registers a custom file source + virtual void registerCustomFileSource(std::shared_ptr) noexcept; + + // Returns an array of custom file sources + virtual std::vector> getCustomFileSources() noexcept; + protected: FileSourceManager(); class Impl; diff --git a/platform/BUILD.bazel b/platform/BUILD.bazel index f39d31d1ee8e..ff7ccb6c5f68 100644 --- a/platform/BUILD.bazel +++ b/platform/BUILD.bazel @@ -268,6 +268,8 @@ objc_library( srcs = [ "//platform/darwin:app/PluginLayerExample.h", "//platform/darwin:app/PluginLayerExample.mm", + "//platform/darwin:app/PluginProtocolExample.h", + "//platform/darwin:app/PluginProtocolExample.mm", "//platform/darwin:app/PluginLayerExampleMetalRendering.h", "//platform/darwin:app/PluginLayerExampleMetalRendering.mm", "//platform/darwin:app/CustomStyleLayerExample.h", diff --git a/platform/darwin/BUILD.bazel b/platform/darwin/BUILD.bazel index dcc0a8bcbac4..4b28e1e0994e 100644 --- a/platform/darwin/BUILD.bazel +++ b/platform/darwin/BUILD.bazel @@ -303,6 +303,8 @@ exports_files( "app/PluginLayerExample.mm", "app/PluginLayerExampleMetalRendering.h", "app/PluginLayerExampleMetalRendering.mm", + "app/PluginProtocolExample.h", + "app/PluginProtocolExample.mm", "test/amsterdam.geojson", "test/MLNSDKTestHelpers.swift", "app/CustomStyleLayerExample.h", diff --git a/platform/darwin/app/PluginProtocolExample.h b/platform/darwin/app/PluginProtocolExample.h new file mode 100644 index 000000000000..63cf0fee0d99 --- /dev/null +++ b/platform/darwin/app/PluginProtocolExample.h @@ -0,0 +1,9 @@ +#import "MLNPluginProtocolHandler.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface PluginProtocolExample : MLNPluginProtocolHandler + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/app/PluginProtocolExample.mm b/platform/darwin/app/PluginProtocolExample.mm new file mode 100644 index 000000000000..676b21ffb77b --- /dev/null +++ b/platform/darwin/app/PluginProtocolExample.mm @@ -0,0 +1,23 @@ +#import "PluginProtocolExample.h" + +@implementation PluginProtocolExample + +-(BOOL)canRequestResource:(MLNPluginProtocolHandlerResource *)resource { + if ([resource.resourceURL containsString:@"pluginProtocol"]) { + return YES; + } + return NO; +} + +-(MLNPluginProtocolHandlerResponse *)requestResource:(MLNPluginProtocolHandlerResource *)resource { + + NSData *data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"PluginLayerTestStyle.json" ofType:nil]]; + + MLNPluginProtocolHandlerResponse *response = [[MLNPluginProtocolHandlerResponse alloc] init]; + response.data = data; + return response; + +} + + +@end diff --git a/platform/darwin/bazel/files.bzl b/platform/darwin/bazel/files.bzl index 560189cd69c0..7af769a63ab1 100644 --- a/platform/darwin/bazel/files.bzl +++ b/platform/darwin/bazel/files.bzl @@ -108,6 +108,7 @@ MLN_DARWIN_OBJC_HEADERS = [ "src/NSValue+MLNAdditions.h", "src/MLNPluginLayer.h", "src/MLNPluginStyleLayer.h", + "src/MLNPluginProtocolHandler.h" ] MLN_DARWIN_OBJCPP_HEADERS = [ @@ -222,7 +223,8 @@ MLN_DARWIN_PUBLIC_OBJCPP_SOURCE = [ "src/NSPredicate+MLNAdditions.mm", "src/NSValue+MLNStyleAttributeAdditions.mm", "src/MLNPluginLayer.mm", - "src/MLNPluginStyleLayer.mm" + "src/MLNPluginStyleLayer.mm", + "src/MLNPluginProtocolHandler.mm" ] MLN_DARWIN_PUBLIC_OBJCPP_CUSTOM_DRAWABLE_SOURCE = [ diff --git a/platform/darwin/src/MLNPluginProtocolHandler.h b/platform/darwin/src/MLNPluginProtocolHandler.h new file mode 100644 index 000000000000..469076e15c1c --- /dev/null +++ b/platform/darwin/src/MLNPluginProtocolHandler.h @@ -0,0 +1,25 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MLNPluginProtocolHandlerResource : NSObject + +@property NSString *resourceURL; + +@end + +@interface MLNPluginProtocolHandlerResponse : NSObject + +@property NSData *data; + +@end + +@interface MLNPluginProtocolHandler : NSObject + +-(BOOL)canRequestResource:(MLNPluginProtocolHandlerResource *)resource; + +-(MLNPluginProtocolHandlerResponse *)requestResource:(MLNPluginProtocolHandlerResource *)resource; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MLNPluginProtocolHandler.mm b/platform/darwin/src/MLNPluginProtocolHandler.mm new file mode 100644 index 000000000000..0f7700a5bba2 --- /dev/null +++ b/platform/darwin/src/MLNPluginProtocolHandler.mm @@ -0,0 +1,23 @@ +#import "MLNPluginProtocolHandler.h" + +@implementation MLNPluginProtocolHandler + +-(BOOL)canRequestResource:(MLNPluginProtocolHandlerResource *)resource { + // Base class returns false + return NO; +} + +-(MLNPluginProtocolHandlerResponse *)requestResource:(MLNPluginProtocolHandlerResource *)resource { + // Base class does nothing + return nil; +} + + +@end + +@implementation MLNPluginProtocolHandlerResource +@end + + +@implementation MLNPluginProtocolHandlerResponse +@end diff --git a/platform/default/BUILD.bazel b/platform/default/BUILD.bazel index e22c12db9526..7dbb1bb097ef 100644 --- a/platform/default/BUILD.bazel +++ b/platform/default/BUILD.bazel @@ -58,6 +58,7 @@ cc_library( "src/mbgl/storage/offline_database.cpp", "src/mbgl/storage/offline_download.cpp", "src/mbgl/storage/online_file_source.cpp", + "src/mbgl/storage/plugin_file_source.cpp", "src/mbgl/storage/pmtiles_file_source.cpp", "src/mbgl/storage/sqlite3.cpp", "src/mbgl/text/bidi.cpp", diff --git a/platform/default/src/mbgl/storage/main_resource_loader.cpp b/platform/default/src/mbgl/storage/main_resource_loader.cpp index 2f523f1e8d2e..a477c815718c 100644 --- a/platform/default/src/mbgl/storage/main_resource_loader.cpp +++ b/platform/default/src/mbgl/storage/main_resource_loader.cpp @@ -65,54 +65,67 @@ class MainResourceLoaderThread { // the sources were able to request a resource. const std::size_t tasksSize = tasks.size(); - // Waterfall resource request processing and return early once resource was requested. - if (assetFileSource && assetFileSource->canRequest(resource)) { - // Asset request - tasks[req] = assetFileSource->request(resource, callback); - } else if (mbtilesFileSource && mbtilesFileSource->canRequest(resource)) { - // Local file request - tasks[req] = mbtilesFileSource->request(resource, callback); - } else if (pmtilesFileSource && pmtilesFileSource->canRequest(resource)) { - // Local file request - tasks[req] = pmtilesFileSource->request(resource, callback); - } else if (localFileSource && localFileSource->canRequest(resource)) { - // Local file request - tasks[req] = localFileSource->request(resource, callback); - } else if (databaseFileSource && databaseFileSource->canRequest(resource)) { - // Try cache only request if needed. - if (resource.loadingMethod == Resource::LoadingMethod::CacheOnly) { - tasks[req] = databaseFileSource->request(resource, callback); - } else { - // Cache request with fallback to network with cache control - tasks[req] = databaseFileSource->request(resource, [=, this](const Response& response) { - Resource res = resource; - - // Resource is in the cache - if (!response.noContent) { - if (response.isUsable()) { - callback(response); - // Set the priority of existing resource to low if it's expired but usable. - res.setPriority(Resource::Priority::Low); - } else { - // Set prior data only if it was not returned to - // the requester. Once we get 304 response from - // the network, we will forward response to the - // requester. - res.priorData = response.data; - } - - // Copy response fields for cache control request - res.priorModified = response.modified; - res.priorExpires = response.expires; - res.priorEtag = response.etag; - } + // Go through custom handlers + bool requestHandledByCustomHandler = false; + auto fm = FileSourceManager::get(); + for (auto customFileSource: fm->getCustomFileSources()) { + if (customFileSource->canRequest(resource)) { + tasks[req] = customFileSource->request(resource, callback); + requestHandledByCustomHandler = true; + break; + } + } - tasks[req] = requestFromNetwork(res, std::move(tasks[req])); - }); + if (!requestHandledByCustomHandler) { + // Waterfall resource request processing and return early once resource was requested. + if (assetFileSource && assetFileSource->canRequest(resource)) { + // Asset request + tasks[req] = assetFileSource->request(resource, callback); + } else if (mbtilesFileSource && mbtilesFileSource->canRequest(resource)) { + // Local file request + tasks[req] = mbtilesFileSource->request(resource, callback); + } else if (pmtilesFileSource && pmtilesFileSource->canRequest(resource)) { + // Local file request + tasks[req] = pmtilesFileSource->request(resource, callback); + } else if (localFileSource && localFileSource->canRequest(resource)) { + // Local file request + tasks[req] = localFileSource->request(resource, callback); + } else if (databaseFileSource && databaseFileSource->canRequest(resource)) { + // Try cache only request if needed. + if (resource.loadingMethod == Resource::LoadingMethod::CacheOnly) { + tasks[req] = databaseFileSource->request(resource, callback); + } else { + // Cache request with fallback to network with cache control + tasks[req] = databaseFileSource->request(resource, [=, this](const Response& response) { + Resource res = resource; + + // Resource is in the cache + if (!response.noContent) { + if (response.isUsable()) { + callback(response); + // Set the priority of existing resource to low if it's expired but usable. + res.setPriority(Resource::Priority::Low); + } else { + // Set prior data only if it was not returned to + // the requester. Once we get 304 response from + // the network, we will forward response to the + // requester. + res.priorData = response.data; + } + + // Copy response fields for cache control request + res.priorModified = response.modified; + res.priorExpires = response.expires; + res.priorEtag = response.etag; + } + + tasks[req] = requestFromNetwork(res, std::move(tasks[req])); + }); + } + } else if (auto networkReq = requestFromNetwork(resource, nullptr)) { + // Get from the online file source + tasks[req] = std::move(networkReq); } - } else if (auto networkReq = requestFromNetwork(resource, nullptr)) { - // Get from the online file source - tasks[req] = std::move(networkReq); } // If no new tasks were added, notify client that request cannot be processed. @@ -180,6 +193,15 @@ class MainResourceLoader::Impl { } bool canRequest(const Resource& resource) const { + + // Check the custom file sources + auto fm = FileSourceManager::get(); + for (auto customFileSource: fm->getCustomFileSources()) { + if (customFileSource->canRequest(resource)) { + return true; + } + } + return (assetFileSource && assetFileSource->canRequest(resource)) || (localFileSource && localFileSource->canRequest(resource)) || (databaseFileSource && databaseFileSource->canRequest(resource)) || diff --git a/platform/default/src/mbgl/storage/plugin_file_source.cpp b/platform/default/src/mbgl/storage/plugin_file_source.cpp new file mode 100644 index 000000000000..74cd141e8f23 --- /dev/null +++ b/platform/default/src/mbgl/storage/plugin_file_source.cpp @@ -0,0 +1,153 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +void PluginFileSource::setProtocolPrefix(const std::string &protocolPrefix) { + +} + + + +class PluginFileSource::Impl { +public: + explicit Impl(const ActorRef&, const ResourceOptions& resourceOptions_, const ClientOptions& clientOptions_) + : resourceOptions(resourceOptions_.clone()), + clientOptions(clientOptions_.clone()) {} + + OnRequestResource _requestFunction; + void setOnRequestResourceFunction(OnRequestResource requestFunction) { + _requestFunction = requestFunction; + } + + void request(const Resource& resource, const ActorRef& req) { + +// if (_onCanRequestResourceFunction) { +// if (!_onCanRequestResourceFunction(resource)) { +// Response response; +// response.error = std::make_unique(Response::Error::Reason::Other, "This plugin protocol handler cannot service this resource"); +// req.invoke(&FileSourceRequest::setResponse, response); +// return; +// } +// } + +// if (!acceptsURL(resource.url)) { +// Response response; +// response.error = std::make_unique(Response::Error::Reason::Other, "Invalid file URL"); +// req.invoke(&FileSourceRequest::setResponse, response); +// return; +// } + +// void requestLocalFile(const std::string& path, +// const ActorRef& req, +// const std::optional>& dataRange) { + + Response response; + if (_requestFunction) { + response = _requestFunction(resource); + } else { + response.error = std::make_unique(Response::Error::Reason::Other, + std::string("Custom Protocol Handler Not Configured Correctly")); + } + req.invoke(&FileSourceRequest::setResponse, response); + + } + + void setResourceOptions(ResourceOptions options) { + std::lock_guard lock(resourceOptionsMutex); + resourceOptions = options; + } + + ResourceOptions getResourceOptions() { + std::lock_guard lock(resourceOptionsMutex); + return resourceOptions.clone(); + } + + void setClientOptions(ClientOptions options) { + std::lock_guard lock(clientOptionsMutex); + clientOptions = options; + } + + ClientOptions getClientOptions() { + std::lock_guard lock(clientOptionsMutex); + return clientOptions.clone(); + } + +private: + mutable std::mutex resourceOptionsMutex; + mutable std::mutex clientOptionsMutex; + ResourceOptions resourceOptions; + ClientOptions clientOptions; +}; + +void PluginFileSource::setOnCanRequestFunction(OnCanRequestResource requestFunction) { + _onCanRequestResourceFunction = requestFunction; +// impl.get()->actor().invoke(&Impl::setOnCanRequestFunction, requestFunction); +} + +void PluginFileSource::setOnRequestResourceFunction(OnRequestResource requestFunction) { + impl.get()->actor().invoke(&Impl::setOnRequestResourceFunction, requestFunction); +} + + +PluginFileSource::PluginFileSource(const ResourceOptions& resourceOptions, const ClientOptions& clientOptions) + : impl(std::make_unique>( + util::makeThreadPrioritySetter(platform::EXPERIMENTAL_THREAD_PRIORITY_FILE), + "LocalFileSource", + resourceOptions.clone(), + clientOptions.clone())) {} + +PluginFileSource::~PluginFileSource() = default; + +std::unique_ptr PluginFileSource::request(const Resource& resource, Callback callback) { + auto req = std::make_unique(std::move(callback)); + + impl->actor().invoke(&Impl::request, resource, req->actor()); + + return req; +} + +bool PluginFileSource::canRequest(const Resource& resource) const { + if (_onCanRequestResourceFunction) { + return _onCanRequestResourceFunction(resource); + } + return false; +} + +void PluginFileSource::pause() { + impl->pause(); +} + +void PluginFileSource::resume() { + impl->resume(); +} + +void PluginFileSource::setResourceOptions(ResourceOptions options) { + impl->actor().invoke(&Impl::setResourceOptions, options.clone()); +} + +ResourceOptions PluginFileSource::getResourceOptions() { + return impl->actor().ask(&Impl::getResourceOptions).get(); +} + +void PluginFileSource::setClientOptions(ClientOptions options) { + impl->actor().invoke(&Impl::setClientOptions, options.clone()); +} + +ClientOptions PluginFileSource::getClientOptions() { + return impl->actor().ask(&Impl::getClientOptions).get(); +} + +} // namespace mbgl diff --git a/platform/ios/app/MBXViewController.mm b/platform/ios/app/MBXViewController.mm index 4c13a767ea51..7093c19c65d2 100644 --- a/platform/ios/app/MBXViewController.mm +++ b/platform/ios/app/MBXViewController.mm @@ -27,6 +27,7 @@ #import "PluginLayerExample.h" #import "PluginLayerExampleMetalRendering.h" #import "MLNPluginStyleLayer.h" +#import "PluginProtocolExample.h" static const CLLocationCoordinate2D WorldTourDestinations[] = { { .latitude = 38.8999418, .longitude = -77.033996 }, @@ -281,7 +282,8 @@ -(void)addPluginLayers { [self.mapView addPluginLayerType:[PluginLayerExample class]]; [self.mapView addPluginLayerType:[PluginLayerExampleMetalRendering class]]; - + [self.mapView addPluginProtocolHandler:[PluginProtocolExample class]]; + } - (void)viewDidLoad @@ -2331,6 +2333,11 @@ - (void)setStyles self.styleURLs = [NSMutableArray array]; + /// This is hte same style as above but copied locally and the three instances of the metal plug-in layer added to the style + /// Look for "type": "plugin-layer-metal-rendering" in the PluginLayerTestStyle.json for an example of how the layer is defined + [self.styleNames addObject:@"MapLibre Basic - Local With Plugin Loader"]; + NSURL *pluginstyleurl = [NSURL URLWithString:@"pluginProtocol://PluginLayerTestStyle.json"]; + [self.styleURLs addObject:pluginstyleurl]; /// Style that does not require an `apiKey` nor any further configuration diff --git a/platform/ios/src/MLNMapView.h b/platform/ios/src/MLNMapView.h index 1e800fafe188..e308ba4964ba 100644 --- a/platform/ios/src/MLNMapView.h +++ b/platform/ios/src/MLNMapView.h @@ -2276,6 +2276,11 @@ vertically on the map. */ - (void)addPluginLayerType:(Class)pluginLayerClass; +/** + Adds a plug-in protocol handler that is external to this library + */ +- (void)addPluginProtocolHandler:(Class)pluginProtocolHandlerClass; + @end NS_ASSUME_NONNULL_END diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 23313088fa14..6ad9a3582041 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -30,9 +30,11 @@ #include #include #include +#include #include #include #include +#include #import "Mapbox.h" #import "MLNShape_Private.h" @@ -80,6 +82,7 @@ #import "MLNActionJournalOptions_Private.h" #import "MLNMapProjection.h" #import "MLNPluginLayer.h" +#import "MLNPluginProtocolHandler.h" #import "MLNStyleLayerManager.h" #include "MLNPluginStyleLayer_Private.h" @@ -452,8 +455,9 @@ @interface MLNMapView () pluginSource = std::make_shared(resourceOptions, clientOptions); + pluginSource->setOnRequestResourceFunction([weakHandler, weakSelf](const mbgl::Resource &resource) -> mbgl::Response { + mbgl::Response tempResult; + + __strong MLNPluginProtocolHandler *strongHandler = weakHandler; + if (strongHandler) { + + MLNPluginProtocolHandlerResource *res = [weakSelf resourceFromCoreResource:resource]; + MLNPluginProtocolHandlerResponse *response = [strongHandler requestResource:res]; + if (response.data) { + tempResult.data = std::make_shared((const char*)[response.data bytes], + [response.data length]); + } + } + + return tempResult; + + }); + + pluginSource->setOnCanRequestFunction([weakHandler, weakSelf](const mbgl::Resource &resource) -> bool{ + @autoreleasepool { + __strong MLNPluginProtocolHandler *strongHandler = weakHandler; + if (!strongHandler) { + return false; + } + + MLNPluginProtocolHandlerResource *res = [weakSelf resourceFromCoreResource:resource]; + BOOL tempResult = [strongHandler canRequestResource:res]; + + return tempResult; + + } + }); + + auto fileSourceManager = mbgl::FileSourceManager::get(); + fileSourceManager->registerCustomFileSource(pluginSource); + +} + + + - (NSArray*)getActionJournalLogFiles { const auto& actionJournal = _mbglMap->getActionJournal(); diff --git a/src/mbgl/plugin/plugin_file_source.hpp b/src/mbgl/plugin/plugin_file_source.hpp new file mode 100644 index 000000000000..6e78175257cb --- /dev/null +++ b/src/mbgl/plugin/plugin_file_source.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include +#include +#include + +namespace mbgl { + +namespace util { +template +class Thread; +} // namespace util + +class PluginFileSourceRequest { + +}; + +class PluginFileSourceResponse { + +}; + +class PluginFileSource : public FileSource { +public: + PluginFileSource(const ResourceOptions& resourceOptions, const ClientOptions& clientOptions); + ~PluginFileSource() override; + + using OnCanRequestResource = std::function; + using OnRequestResource = std::function; + + void setOnCanRequestFunction(OnCanRequestResource requestFunction); + void setOnRequestResourceFunction(OnRequestResource requestFunction); + + std::unique_ptr request(const Resource&, Callback) override; + bool canRequest(const Resource&) const override; + void pause() override; + void resume() override; + + void setProtocolPrefix(const std::string &); + + void setResourceOptions(ResourceOptions) override; + ResourceOptions getResourceOptions() override; + + void setClientOptions(ClientOptions) override; + ClientOptions getClientOptions() override; + +private: + OnCanRequestResource _onCanRequestResourceFunction; + class Impl; + std::unique_ptr> impl; +}; + +} // namespace mbgl diff --git a/src/mbgl/storage/file_source_manager.cpp b/src/mbgl/storage/file_source_manager.cpp index 2e21443b82a6..3f97de6d65cd 100644 --- a/src/mbgl/storage/file_source_manager.cpp +++ b/src/mbgl/storage/file_source_manager.cpp @@ -13,10 +13,10 @@ namespace mbgl { struct FileSourceInfo { FileSourceInfo(FileSourceType type_, std::string id_, std::weak_ptr fileSource_) - : type(type_), - id(std::move(id_)), - fileSource(std::move(fileSource_)) {} - + : type(type_), + id(std::move(id_)), + fileSource(std::move(fileSource_)) {} + FileSourceType type; std::string id; std::weak_ptr fileSource; @@ -27,10 +27,11 @@ class FileSourceManager::Impl { std::list fileSources; std::map fileSourceFactories; std::recursive_mutex mutex; + std::vector> customFileSources; }; FileSourceManager::FileSourceManager() - : impl(std::make_unique()) {} +: impl(std::make_unique()) {} FileSourceManager::~FileSourceManager() = default; @@ -38,17 +39,17 @@ std::shared_ptr FileSourceManager::getFileSource(FileSourceType type const ResourceOptions& resourceOptions, const ClientOptions& clientOptions) noexcept { std::lock_guard lock(impl->mutex); - + // Remove released file sources. for (auto it = impl->fileSources.begin(); it != impl->fileSources.end();) { it = it->fileSource.expired() ? impl->fileSources.erase(it) : ++it; } - + const auto context = reinterpret_cast(resourceOptions.platformContext()); std::string baseURL = resourceOptions.tileServerOptions().baseURL(); std::string id = baseURL + '|' + resourceOptions.apiKey() + '|' + resourceOptions.cachePath() + '|' + - util::toString(context); - + util::toString(context); + std::shared_ptr fileSource; auto fileSourceIt = std::find_if(impl->fileSources.begin(), impl->fileSources.end(), [type, &id](const auto& info) { return info.type == type && info.id == id; @@ -56,7 +57,7 @@ std::shared_ptr FileSourceManager::getFileSource(FileSourceType type if (fileSourceIt != impl->fileSources.end()) { fileSource = fileSourceIt->fileSource.lock(); } - + if (!fileSource) { auto it = impl->fileSourceFactories.find(type); if (it != impl->fileSourceFactories.end()) { @@ -65,7 +66,7 @@ std::shared_ptr FileSourceManager::getFileSource(FileSourceType type impl->fileSources.emplace_back(type, std::move(id), fileSource); } } - + return fileSource; } @@ -86,4 +87,16 @@ FileSourceManager::FileSourceFactory FileSourceManager::unRegisterFileSourceFact return factory; } +// Registers a custom file source factory +void FileSourceManager::registerCustomFileSource(std::shared_ptr fileSource) noexcept { + impl->customFileSources.push_back(fileSource); +} + +// Returns an array of custom file sources +std::vector> FileSourceManager::getCustomFileSources() noexcept { + return impl->customFileSources; +} + + + } // namespace mbgl From 73ca452bc8a89116c8089aa61508016656d8b9b3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 26 Jul 2025 17:22:03 +0000 Subject: [PATCH 135/221] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- include/mbgl/storage/file_source_manager.hpp | 2 +- platform/darwin/app/PluginProtocolExample.mm | 6 +- .../darwin/src/MLNPluginProtocolHandler.h | 4 +- .../src/mbgl/storage/main_resource_loader.cpp | 13 ++-- .../src/mbgl/storage/plugin_file_source.cpp | 75 ++++++++----------- platform/ios/app/MBXViewController.mm | 2 +- platform/ios/src/MLNMapView.mm | 30 ++++---- src/mbgl/plugin/plugin_file_source.hpp | 18 ++--- src/mbgl/storage/file_source_manager.cpp | 24 +++--- 9 files changed, 79 insertions(+), 95 deletions(-) diff --git a/include/mbgl/storage/file_source_manager.hpp b/include/mbgl/storage/file_source_manager.hpp index 78d80464768f..f6fe523e4260 100644 --- a/include/mbgl/storage/file_source_manager.hpp +++ b/include/mbgl/storage/file_source_manager.hpp @@ -48,7 +48,7 @@ class FileSourceManager { // Returns an array of custom file sources virtual std::vector> getCustomFileSources() noexcept; - + protected: FileSourceManager(); class Impl; diff --git a/platform/darwin/app/PluginProtocolExample.mm b/platform/darwin/app/PluginProtocolExample.mm index 676b21ffb77b..8915f9b514a6 100644 --- a/platform/darwin/app/PluginProtocolExample.mm +++ b/platform/darwin/app/PluginProtocolExample.mm @@ -10,13 +10,13 @@ -(BOOL)canRequestResource:(MLNPluginProtocolHandlerResource *)resource { } -(MLNPluginProtocolHandlerResponse *)requestResource:(MLNPluginProtocolHandlerResource *)resource { - + NSData *data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"PluginLayerTestStyle.json" ofType:nil]]; - + MLNPluginProtocolHandlerResponse *response = [[MLNPluginProtocolHandlerResponse alloc] init]; response.data = data; return response; - + } diff --git a/platform/darwin/src/MLNPluginProtocolHandler.h b/platform/darwin/src/MLNPluginProtocolHandler.h index 469076e15c1c..2d1714f31193 100644 --- a/platform/darwin/src/MLNPluginProtocolHandler.h +++ b/platform/darwin/src/MLNPluginProtocolHandler.h @@ -16,9 +16,9 @@ NS_ASSUME_NONNULL_BEGIN @interface MLNPluginProtocolHandler : NSObject --(BOOL)canRequestResource:(MLNPluginProtocolHandlerResource *)resource; +- (BOOL)canRequestResource:(MLNPluginProtocolHandlerResource *)resource; --(MLNPluginProtocolHandlerResponse *)requestResource:(MLNPluginProtocolHandlerResource *)resource; +- (MLNPluginProtocolHandlerResponse *)requestResource:(MLNPluginProtocolHandlerResource *)resource; @end diff --git a/platform/default/src/mbgl/storage/main_resource_loader.cpp b/platform/default/src/mbgl/storage/main_resource_loader.cpp index a477c815718c..208c109e5fe8 100644 --- a/platform/default/src/mbgl/storage/main_resource_loader.cpp +++ b/platform/default/src/mbgl/storage/main_resource_loader.cpp @@ -68,7 +68,7 @@ class MainResourceLoaderThread { // Go through custom handlers bool requestHandledByCustomHandler = false; auto fm = FileSourceManager::get(); - for (auto customFileSource: fm->getCustomFileSources()) { + for (auto customFileSource : fm->getCustomFileSources()) { if (customFileSource->canRequest(resource)) { tasks[req] = customFileSource->request(resource, callback); requestHandledByCustomHandler = true; @@ -98,7 +98,7 @@ class MainResourceLoaderThread { // Cache request with fallback to network with cache control tasks[req] = databaseFileSource->request(resource, [=, this](const Response& response) { Resource res = resource; - + // Resource is in the cache if (!response.noContent) { if (response.isUsable()) { @@ -112,13 +112,13 @@ class MainResourceLoaderThread { // requester. res.priorData = response.data; } - + // Copy response fields for cache control request res.priorModified = response.modified; res.priorExpires = response.expires; res.priorEtag = response.etag; } - + tasks[req] = requestFromNetwork(res, std::move(tasks[req])); }); } @@ -193,15 +193,14 @@ class MainResourceLoader::Impl { } bool canRequest(const Resource& resource) const { - // Check the custom file sources auto fm = FileSourceManager::get(); - for (auto customFileSource: fm->getCustomFileSources()) { + for (auto customFileSource : fm->getCustomFileSources()) { if (customFileSource->canRequest(resource)) { return true; } } - + return (assetFileSource && assetFileSource->canRequest(resource)) || (localFileSource && localFileSource->canRequest(resource)) || (databaseFileSource && databaseFileSource->canRequest(resource)) || diff --git a/platform/default/src/mbgl/storage/plugin_file_source.cpp b/platform/default/src/mbgl/storage/plugin_file_source.cpp index 74cd141e8f23..ca93611f3e49 100644 --- a/platform/default/src/mbgl/storage/plugin_file_source.cpp +++ b/platform/default/src/mbgl/storage/plugin_file_source.cpp @@ -15,54 +15,46 @@ namespace mbgl { -void PluginFileSource::setProtocolPrefix(const std::string &protocolPrefix) { - -} - - +void PluginFileSource::setProtocolPrefix(const std::string& protocolPrefix) {} class PluginFileSource::Impl { public: explicit Impl(const ActorRef&, const ResourceOptions& resourceOptions_, const ClientOptions& clientOptions_) : resourceOptions(resourceOptions_.clone()), clientOptions(clientOptions_.clone()) {} - + OnRequestResource _requestFunction; - void setOnRequestResourceFunction(OnRequestResource requestFunction) { - _requestFunction = requestFunction; - } - - void request(const Resource& resource, const ActorRef& req) { - -// if (_onCanRequestResourceFunction) { -// if (!_onCanRequestResourceFunction(resource)) { -// Response response; -// response.error = std::make_unique(Response::Error::Reason::Other, "This plugin protocol handler cannot service this resource"); -// req.invoke(&FileSourceRequest::setResponse, response); -// return; -// } -// } - -// if (!acceptsURL(resource.url)) { -// Response response; -// response.error = std::make_unique(Response::Error::Reason::Other, "Invalid file URL"); -// req.invoke(&FileSourceRequest::setResponse, response); -// return; -// } - -// void requestLocalFile(const std::string& path, -// const ActorRef& req, -// const std::optional>& dataRange) { - - Response response; - if (_requestFunction) { - response = _requestFunction(resource); - } else { - response.error = std::make_unique(Response::Error::Reason::Other, - std::string("Custom Protocol Handler Not Configured Correctly")); - } - req.invoke(&FileSourceRequest::setResponse, response); + void setOnRequestResourceFunction(OnRequestResource requestFunction) { _requestFunction = requestFunction; } + void request(const Resource& resource, const ActorRef& req) { + // if (_onCanRequestResourceFunction) { + // if (!_onCanRequestResourceFunction(resource)) { + // Response response; + // response.error = std::make_unique(Response::Error::Reason::Other, "This + // plugin protocol handler cannot service this resource"); + // req.invoke(&FileSourceRequest::setResponse, response); + // return; + // } + // } + + // if (!acceptsURL(resource.url)) { + // Response response; + // response.error = std::make_unique(Response::Error::Reason::Other, "Invalid file + // URL"); req.invoke(&FileSourceRequest::setResponse, response); return; + // } + + // void requestLocalFile(const std::string& path, + // const ActorRef& req, + // const std::optional>& dataRange) { + + Response response; + if (_requestFunction) { + response = _requestFunction(resource); + } else { + response.error = std::make_unique( + Response::Error::Reason::Other, std::string("Custom Protocol Handler Not Configured Correctly")); + } + req.invoke(&FileSourceRequest::setResponse, response); } void setResourceOptions(ResourceOptions options) { @@ -94,14 +86,13 @@ class PluginFileSource::Impl { void PluginFileSource::setOnCanRequestFunction(OnCanRequestResource requestFunction) { _onCanRequestResourceFunction = requestFunction; -// impl.get()->actor().invoke(&Impl::setOnCanRequestFunction, requestFunction); + // impl.get()->actor().invoke(&Impl::setOnCanRequestFunction, requestFunction); } void PluginFileSource::setOnRequestResourceFunction(OnRequestResource requestFunction) { impl.get()->actor().invoke(&Impl::setOnRequestResourceFunction, requestFunction); } - PluginFileSource::PluginFileSource(const ResourceOptions& resourceOptions, const ClientOptions& clientOptions) : impl(std::make_unique>( util::makeThreadPrioritySetter(platform::EXPERIMENTAL_THREAD_PRIORITY_FILE), diff --git a/platform/ios/app/MBXViewController.mm b/platform/ios/app/MBXViewController.mm index 7093c19c65d2..c42f066b1614 100644 --- a/platform/ios/app/MBXViewController.mm +++ b/platform/ios/app/MBXViewController.mm @@ -283,7 +283,7 @@ -(void)addPluginLayers { [self.mapView addPluginLayerType:[PluginLayerExample class]]; [self.mapView addPluginLayerType:[PluginLayerExampleMetalRendering class]]; [self.mapView addPluginProtocolHandler:[PluginProtocolExample class]]; - + } - (void)viewDidLoad diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 6ad9a3582041..569312dc3ece 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -7806,16 +7806,16 @@ -(void)addPluginLayerType:(Class)pluginLayerClass { } - (MLNPluginProtocolHandlerResource *)resourceFromCoreResource:(const mbgl::Resource &)resource { - + MLNPluginProtocolHandlerResource *tempResult = [[MLNPluginProtocolHandlerResource alloc] init]; tempResult.resourceURL = [NSString stringWithUTF8String:resource.url.c_str()]; return tempResult; - + } - (void)addPluginProtocolHandler:(Class)pluginProtocolHandlerClass { - - + + MLNPluginProtocolHandler *handler = [[pluginProtocolHandlerClass alloc] init]; if (!self.pluginProtocols) { self.pluginProtocols = [NSMutableArray array]; @@ -7824,18 +7824,18 @@ - (void)addPluginProtocolHandler:(Class)pluginProtocolHandlerClass { mbgl::ResourceOptions resourceOptions; mbgl::ClientOptions clientOptions; - + // Use weak here so there isn't a retain cycle __weak MLNPluginProtocolHandler *weakHandler = handler; __weak MLNMapView *weakSelf = self; - + std::shared_ptr pluginSource = std::make_shared(resourceOptions, clientOptions); pluginSource->setOnRequestResourceFunction([weakHandler, weakSelf](const mbgl::Resource &resource) -> mbgl::Response { mbgl::Response tempResult; - + __strong MLNPluginProtocolHandler *strongHandler = weakHandler; if (strongHandler) { - + MLNPluginProtocolHandlerResource *res = [weakSelf resourceFromCoreResource:resource]; MLNPluginProtocolHandlerResponse *response = [strongHandler requestResource:res]; if (response.data) { @@ -7843,29 +7843,29 @@ - (void)addPluginProtocolHandler:(Class)pluginProtocolHandlerClass { [response.data length]); } } - + return tempResult; - + }); - + pluginSource->setOnCanRequestFunction([weakHandler, weakSelf](const mbgl::Resource &resource) -> bool{ @autoreleasepool { __strong MLNPluginProtocolHandler *strongHandler = weakHandler; if (!strongHandler) { return false; } - + MLNPluginProtocolHandlerResource *res = [weakSelf resourceFromCoreResource:resource]; BOOL tempResult = [strongHandler canRequestResource:res]; return tempResult; - + } }); - + auto fileSourceManager = mbgl::FileSourceManager::get(); fileSourceManager->registerCustomFileSource(pluginSource); - + } diff --git a/src/mbgl/plugin/plugin_file_source.hpp b/src/mbgl/plugin/plugin_file_source.hpp index 6e78175257cb..7f6acc686156 100644 --- a/src/mbgl/plugin/plugin_file_source.hpp +++ b/src/mbgl/plugin/plugin_file_source.hpp @@ -11,32 +11,28 @@ template class Thread; } // namespace util -class PluginFileSourceRequest { - -}; +class PluginFileSourceRequest {}; -class PluginFileSourceResponse { - -}; +class PluginFileSourceResponse {}; class PluginFileSource : public FileSource { public: - PluginFileSource(const ResourceOptions& resourceOptions, const ClientOptions& clientOptions); + PluginFileSource(const ResourceOptions &resourceOptions, const ClientOptions &clientOptions); ~PluginFileSource() override; using OnCanRequestResource = std::function; - using OnRequestResource = std::function; + using OnRequestResource = std::function; void setOnCanRequestFunction(OnCanRequestResource requestFunction); void setOnRequestResourceFunction(OnRequestResource requestFunction); - std::unique_ptr request(const Resource&, Callback) override; - bool canRequest(const Resource&) const override; + std::unique_ptr request(const Resource &, Callback) override; + bool canRequest(const Resource &) const override; void pause() override; void resume() override; void setProtocolPrefix(const std::string &); - + void setResourceOptions(ResourceOptions) override; ResourceOptions getResourceOptions() override; diff --git a/src/mbgl/storage/file_source_manager.cpp b/src/mbgl/storage/file_source_manager.cpp index 3f97de6d65cd..f9876b156753 100644 --- a/src/mbgl/storage/file_source_manager.cpp +++ b/src/mbgl/storage/file_source_manager.cpp @@ -13,10 +13,10 @@ namespace mbgl { struct FileSourceInfo { FileSourceInfo(FileSourceType type_, std::string id_, std::weak_ptr fileSource_) - : type(type_), - id(std::move(id_)), - fileSource(std::move(fileSource_)) {} - + : type(type_), + id(std::move(id_)), + fileSource(std::move(fileSource_)) {} + FileSourceType type; std::string id; std::weak_ptr fileSource; @@ -31,7 +31,7 @@ class FileSourceManager::Impl { }; FileSourceManager::FileSourceManager() -: impl(std::make_unique()) {} + : impl(std::make_unique()) {} FileSourceManager::~FileSourceManager() = default; @@ -39,17 +39,17 @@ std::shared_ptr FileSourceManager::getFileSource(FileSourceType type const ResourceOptions& resourceOptions, const ClientOptions& clientOptions) noexcept { std::lock_guard lock(impl->mutex); - + // Remove released file sources. for (auto it = impl->fileSources.begin(); it != impl->fileSources.end();) { it = it->fileSource.expired() ? impl->fileSources.erase(it) : ++it; } - + const auto context = reinterpret_cast(resourceOptions.platformContext()); std::string baseURL = resourceOptions.tileServerOptions().baseURL(); std::string id = baseURL + '|' + resourceOptions.apiKey() + '|' + resourceOptions.cachePath() + '|' + - util::toString(context); - + util::toString(context); + std::shared_ptr fileSource; auto fileSourceIt = std::find_if(impl->fileSources.begin(), impl->fileSources.end(), [type, &id](const auto& info) { return info.type == type && info.id == id; @@ -57,7 +57,7 @@ std::shared_ptr FileSourceManager::getFileSource(FileSourceType type if (fileSourceIt != impl->fileSources.end()) { fileSource = fileSourceIt->fileSource.lock(); } - + if (!fileSource) { auto it = impl->fileSourceFactories.find(type); if (it != impl->fileSourceFactories.end()) { @@ -66,7 +66,7 @@ std::shared_ptr FileSourceManager::getFileSource(FileSourceType type impl->fileSources.emplace_back(type, std::move(id), fileSource); } } - + return fileSource; } @@ -97,6 +97,4 @@ std::vector> FileSourceManager::getCustomFileSources return impl->customFileSources; } - - } // namespace mbgl From 9f9f84c1c7a6b15e22655d22eca811bb2335f9c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sun, 27 Jul 2025 14:59:48 -0400 Subject: [PATCH 136/221] Cleanup --- .../src/mbgl/storage/plugin_file_source.cpp | 21 ------------------- platform/ios/app/MBXViewController.mm | 15 ++++++------- platform/ios/src/MLNMapView.mm | 3 +++ 3 files changed, 9 insertions(+), 30 deletions(-) diff --git a/platform/default/src/mbgl/storage/plugin_file_source.cpp b/platform/default/src/mbgl/storage/plugin_file_source.cpp index ca93611f3e49..0e0fa0b79b1c 100644 --- a/platform/default/src/mbgl/storage/plugin_file_source.cpp +++ b/platform/default/src/mbgl/storage/plugin_file_source.cpp @@ -27,26 +27,6 @@ class PluginFileSource::Impl { void setOnRequestResourceFunction(OnRequestResource requestFunction) { _requestFunction = requestFunction; } void request(const Resource& resource, const ActorRef& req) { - // if (_onCanRequestResourceFunction) { - // if (!_onCanRequestResourceFunction(resource)) { - // Response response; - // response.error = std::make_unique(Response::Error::Reason::Other, "This - // plugin protocol handler cannot service this resource"); - // req.invoke(&FileSourceRequest::setResponse, response); - // return; - // } - // } - - // if (!acceptsURL(resource.url)) { - // Response response; - // response.error = std::make_unique(Response::Error::Reason::Other, "Invalid file - // URL"); req.invoke(&FileSourceRequest::setResponse, response); return; - // } - - // void requestLocalFile(const std::string& path, - // const ActorRef& req, - // const std::optional>& dataRange) { - Response response; if (_requestFunction) { response = _requestFunction(resource); @@ -86,7 +66,6 @@ class PluginFileSource::Impl { void PluginFileSource::setOnCanRequestFunction(OnCanRequestResource requestFunction) { _onCanRequestResourceFunction = requestFunction; - // impl.get()->actor().invoke(&Impl::setOnCanRequestFunction, requestFunction); } void PluginFileSource::setOnRequestResourceFunction(OnRequestResource requestFunction) { diff --git a/platform/ios/app/MBXViewController.mm b/platform/ios/app/MBXViewController.mm index c42f066b1614..0bda8caffa1d 100644 --- a/platform/ios/app/MBXViewController.mm +++ b/platform/ios/app/MBXViewController.mm @@ -2332,24 +2332,21 @@ - (void)setStyles self.styleNames = [NSMutableArray array]; self.styleURLs = [NSMutableArray array]; - - /// This is hte same style as above but copied locally and the three instances of the metal plug-in layer added to the style - /// Look for "type": "plugin-layer-metal-rendering" in the PluginLayerTestStyle.json for an example of how the layer is defined - [self.styleNames addObject:@"MapLibre Basic - Local With Plugin Loader"]; - NSURL *pluginstyleurl = [NSURL URLWithString:@"pluginProtocol://PluginLayerTestStyle.json"]; - [self.styleURLs addObject:pluginstyleurl]; - - /// Style that does not require an `apiKey` nor any further configuration [self.styleNames addObject:@"MapLibre Basic"]; [self.styleURLs addObject:[NSURL URLWithString:@"https://demotiles.maplibre.org/style.json"]]; - /// This is hte same style as above but copied locally and the three instances of the metal plug-in layer added to the style + /// This is the same style as above but copied locally and the three instances of the metal plug-in layer added to the style /// Look for "type": "plugin-layer-metal-rendering" in the PluginLayerTestStyle.json for an example of how the layer is defined [self.styleNames addObject:@"MapLibre Basic - Local With Plugin"]; NSURL *url = [[NSBundle mainBundle] URLForResource:@"PluginLayerTestStyle.json" withExtension:nil]; [self.styleURLs addObject:url]; + /// This is the same style as above, but using the plugin protocol to actually load the style + [self.styleNames addObject:@"MapLibre Basic - Local With Plugin Loader"]; + NSURL *pluginstyleurl = [NSURL URLWithString:@"pluginProtocol://PluginLayerTestStyle.json"]; + [self.styleURLs addObject:pluginstyleurl]; + /// Add MapLibre Styles if an `apiKey` exists NSString* apiKey = [MLNSettings apiKey]; if (apiKey.length) diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 569312dc3ece..8516639a94a6 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -7822,7 +7822,10 @@ - (void)addPluginProtocolHandler:(Class)pluginProtocolHandlerClass { } [self.pluginProtocols addObject:handler]; + // TODO: Unclear if any of these options are needed for plugins mbgl::ResourceOptions resourceOptions; + + // TODO: Unclear if any of the properties on clientOptions need to be set mbgl::ClientOptions clientOptions; // Use weak here so there isn't a retain cycle From b7f85bbf67d3428093cd4d4de6f7c8dee1c1bf23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sun, 27 Jul 2025 15:18:56 -0400 Subject: [PATCH 137/221] Adding more properties to the platform request --- .../darwin/src/MLNPluginProtocolHandler.h | 37 +++++++++++ .../darwin/src/MLNPluginProtocolHandler.mm | 3 + platform/ios/src/MLNMapView.mm | 66 +++++++++++++++++++ 3 files changed, 106 insertions(+) diff --git a/platform/darwin/src/MLNPluginProtocolHandler.h b/platform/darwin/src/MLNPluginProtocolHandler.h index 2d1714f31193..dcdee5ee7af7 100644 --- a/platform/darwin/src/MLNPluginProtocolHandler.h +++ b/platform/darwin/src/MLNPluginProtocolHandler.h @@ -2,10 +2,47 @@ NS_ASSUME_NONNULL_BEGIN +typedef enum { + MLNPluginProtocolHandlerResourceKindUnknown, + MLNPluginProtocolHandlerResourceKindStyle, + MLNPluginProtocolHandlerResourceKindSource, + MLNPluginProtocolHandlerResourceKindTile, + MLNPluginProtocolHandlerResourceKindGlyphs, + MLNPluginProtocolHandlerResourceKindSpriteImage, + MLNPluginProtocolHandlerResourceKindSpriteJSON, + MLNPluginProtocolHandlerResourceKindImage +} MLNPluginProtocolHandlerResourceKind; + +typedef enum { + MLNPluginProtocolHandlerResourceLoadingMethodUnknown, + MLNPluginProtocolHandlerResourceLoadingMethodCacheOnly, + MLNPluginProtocolHandlerResourceLoadingMethodNetworkOnly, + MLNPluginProtocolHandlerResourceLoadingMethodAll +} MLNPluginProtocolHandlerResourceLoadingMethod; + +// TODO: Might make sense to add this to it's own file +@interface MLNTileData : NSObject + +// Optional Tile Data +@property NSString *tileURLTemplate; +@property int tilePixelRatio; +@property int tileX; +@property int tileY; +@property int tileZoom; + +@end + @interface MLNPluginProtocolHandlerResource : NSObject +@property MLNPluginProtocolHandlerResourceKind resourceKind; + +@property MLNPluginProtocolHandlerResourceLoadingMethod loadingMethod; + @property NSString *resourceURL; +// This is optional +@property MLNTileData * __nullable tileData; + @end @interface MLNPluginProtocolHandlerResponse : NSObject diff --git a/platform/darwin/src/MLNPluginProtocolHandler.mm b/platform/darwin/src/MLNPluginProtocolHandler.mm index 0f7700a5bba2..a68409d104dc 100644 --- a/platform/darwin/src/MLNPluginProtocolHandler.mm +++ b/platform/darwin/src/MLNPluginProtocolHandler.mm @@ -21,3 +21,6 @@ @implementation MLNPluginProtocolHandlerResource @implementation MLNPluginProtocolHandlerResponse @end + +@implementation MLNTileData +@end diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 8516639a94a6..bf82becdf56d 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -7808,7 +7808,71 @@ -(void)addPluginLayerType:(Class)pluginLayerClass { - (MLNPluginProtocolHandlerResource *)resourceFromCoreResource:(const mbgl::Resource &)resource { MLNPluginProtocolHandlerResource *tempResult = [[MLNPluginProtocolHandlerResource alloc] init]; + + // The URL of the request tempResult.resourceURL = [NSString stringWithUTF8String:resource.url.c_str()]; + + // The kind of request + switch (resource.kind) { + case mbgl::Resource::Kind::Style: + tempResult.resourceKind = MLNPluginProtocolHandlerResourceKindStyle; + break; + case mbgl::Resource::Kind::Source: + tempResult.resourceKind = MLNPluginProtocolHandlerResourceKindSource; + break; + case mbgl::Resource::Kind::Tile: + tempResult.resourceKind = MLNPluginProtocolHandlerResourceKindTile; + break; + case mbgl::Resource::Kind::Glyphs: + tempResult.resourceKind = MLNPluginProtocolHandlerResourceKindGlyphs; + break; + case mbgl::Resource::Kind::SpriteImage: + tempResult.resourceKind = MLNPluginProtocolHandlerResourceKindSpriteImage; + break; + case mbgl::Resource::Kind::Image: + tempResult.resourceKind = MLNPluginProtocolHandlerResourceKindImage; + break; + case mbgl::Resource::Kind::SpriteJSON: + tempResult.resourceKind = MLNPluginProtocolHandlerResourceKindSpriteJSON; + break; + default: + tempResult.resourceKind = MLNPluginProtocolHandlerResourceKindUnknown; + break; + } + + // The loading method + if (resource.loadingMethod == mbgl::Resource::LoadingMethod::CacheOnly) { + tempResult.loadingMethod = MLNPluginProtocolHandlerResourceLoadingMethodCacheOnly; + } else if (resource.loadingMethod == mbgl::Resource::LoadingMethod::NetworkOnly) { + tempResult.loadingMethod = MLNPluginProtocolHandlerResourceLoadingMethodNetworkOnly; + } else if (resource.loadingMethod == mbgl::Resource::LoadingMethod::All) { + tempResult.loadingMethod = MLNPluginProtocolHandlerResourceLoadingMethodAll; + } + + if (resource.tileData) { + auto td = *resource.tileData; + MLNTileData *tileData = [[MLNTileData alloc] init]; + tileData.tileURLTemplate = [NSString stringWithUTF8String:td.urlTemplate.c_str()]; + tileData.tilePixelRatio = td.pixelRatio; + tileData.tileX = td.x; + tileData.tileY = td.y; + tileData.tileZoom = td.z; + tempResult.tileData = tileData; + } + + // TODO: Figure out which other properties from resource should be passed along here +/* + Usage usage{Usage::Online}; + Priority priority{Priority::Regular}; + std::optional> dataRange = std::nullopt; + std::optional priorModified = std::nullopt; + std::optional priorExpires = std::nullopt; + std::optional priorEtag = std::nullopt; + std::shared_ptr priorData; + Duration minimumUpdateInterval{Duration::zero()}; + StoragePolicy storagePolicy{StoragePolicy::Permanent}; + */ + return tempResult; } @@ -7840,6 +7904,8 @@ - (void)addPluginProtocolHandler:(Class)pluginProtocolHandlerClass { if (strongHandler) { MLNPluginProtocolHandlerResource *res = [weakSelf resourceFromCoreResource:resource]; + + // TODO: Figure out what other fields in response need to be passed back from requestResource MLNPluginProtocolHandlerResponse *response = [strongHandler requestResource:res]; if (response.data) { tempResult.data = std::make_shared((const char*)[response.data bytes], From 1ab94b51347ed46ae9c65de374feed94fadefa40 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 27 Jul 2025 19:19:59 +0000 Subject: [PATCH 138/221] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../darwin/src/MLNPluginProtocolHandler.h | 26 +++++++++---------- platform/ios/src/MLNMapView.mm | 16 ++++++------ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/platform/darwin/src/MLNPluginProtocolHandler.h b/platform/darwin/src/MLNPluginProtocolHandler.h index dcdee5ee7af7..ef88a9889b35 100644 --- a/platform/darwin/src/MLNPluginProtocolHandler.h +++ b/platform/darwin/src/MLNPluginProtocolHandler.h @@ -3,21 +3,21 @@ NS_ASSUME_NONNULL_BEGIN typedef enum { - MLNPluginProtocolHandlerResourceKindUnknown, - MLNPluginProtocolHandlerResourceKindStyle, - MLNPluginProtocolHandlerResourceKindSource, - MLNPluginProtocolHandlerResourceKindTile, - MLNPluginProtocolHandlerResourceKindGlyphs, - MLNPluginProtocolHandlerResourceKindSpriteImage, - MLNPluginProtocolHandlerResourceKindSpriteJSON, - MLNPluginProtocolHandlerResourceKindImage + MLNPluginProtocolHandlerResourceKindUnknown, + MLNPluginProtocolHandlerResourceKindStyle, + MLNPluginProtocolHandlerResourceKindSource, + MLNPluginProtocolHandlerResourceKindTile, + MLNPluginProtocolHandlerResourceKindGlyphs, + MLNPluginProtocolHandlerResourceKindSpriteImage, + MLNPluginProtocolHandlerResourceKindSpriteJSON, + MLNPluginProtocolHandlerResourceKindImage } MLNPluginProtocolHandlerResourceKind; typedef enum { - MLNPluginProtocolHandlerResourceLoadingMethodUnknown, - MLNPluginProtocolHandlerResourceLoadingMethodCacheOnly, - MLNPluginProtocolHandlerResourceLoadingMethodNetworkOnly, - MLNPluginProtocolHandlerResourceLoadingMethodAll + MLNPluginProtocolHandlerResourceLoadingMethodUnknown, + MLNPluginProtocolHandlerResourceLoadingMethodCacheOnly, + MLNPluginProtocolHandlerResourceLoadingMethodNetworkOnly, + MLNPluginProtocolHandlerResourceLoadingMethodAll } MLNPluginProtocolHandlerResourceLoadingMethod; // TODO: Might make sense to add this to it's own file @@ -41,7 +41,7 @@ typedef enum { @property NSString *resourceURL; // This is optional -@property MLNTileData * __nullable tileData; +@property MLNTileData *__nullable tileData; @end diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index bf82becdf56d..d104dac69d48 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -7808,10 +7808,10 @@ -(void)addPluginLayerType:(Class)pluginLayerClass { - (MLNPluginProtocolHandlerResource *)resourceFromCoreResource:(const mbgl::Resource &)resource { MLNPluginProtocolHandlerResource *tempResult = [[MLNPluginProtocolHandlerResource alloc] init]; - + // The URL of the request tempResult.resourceURL = [NSString stringWithUTF8String:resource.url.c_str()]; - + // The kind of request switch (resource.kind) { case mbgl::Resource::Kind::Style: @@ -7839,7 +7839,7 @@ - (MLNPluginProtocolHandlerResource *)resourceFromCoreResource:(const mbgl::Reso tempResult.resourceKind = MLNPluginProtocolHandlerResourceKindUnknown; break; } - + // The loading method if (resource.loadingMethod == mbgl::Resource::LoadingMethod::CacheOnly) { tempResult.loadingMethod = MLNPluginProtocolHandlerResourceLoadingMethodCacheOnly; @@ -7848,7 +7848,7 @@ - (MLNPluginProtocolHandlerResource *)resourceFromCoreResource:(const mbgl::Reso } else if (resource.loadingMethod == mbgl::Resource::LoadingMethod::All) { tempResult.loadingMethod = MLNPluginProtocolHandlerResourceLoadingMethodAll; } - + if (resource.tileData) { auto td = *resource.tileData; MLNTileData *tileData = [[MLNTileData alloc] init]; @@ -7859,7 +7859,7 @@ - (MLNPluginProtocolHandlerResource *)resourceFromCoreResource:(const mbgl::Reso tileData.tileZoom = td.z; tempResult.tileData = tileData; } - + // TODO: Figure out which other properties from resource should be passed along here /* Usage usage{Usage::Online}; @@ -7872,7 +7872,7 @@ - (MLNPluginProtocolHandlerResource *)resourceFromCoreResource:(const mbgl::Reso Duration minimumUpdateInterval{Duration::zero()}; StoragePolicy storagePolicy{StoragePolicy::Permanent}; */ - + return tempResult; } @@ -7888,7 +7888,7 @@ - (void)addPluginProtocolHandler:(Class)pluginProtocolHandlerClass { // TODO: Unclear if any of these options are needed for plugins mbgl::ResourceOptions resourceOptions; - + // TODO: Unclear if any of the properties on clientOptions need to be set mbgl::ClientOptions clientOptions; @@ -7904,7 +7904,7 @@ - (void)addPluginProtocolHandler:(Class)pluginProtocolHandlerClass { if (strongHandler) { MLNPluginProtocolHandlerResource *res = [weakSelf resourceFromCoreResource:resource]; - + // TODO: Figure out what other fields in response need to be passed back from requestResource MLNPluginProtocolHandlerResponse *response = [strongHandler requestResource:res]; if (response.data) { From bd0ced973387d9d42848cd3d1a3016f37b2e525c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sun, 27 Jul 2025 15:32:56 -0400 Subject: [PATCH 139/221] Cmake update --- platform/darwin/darwin.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/darwin/darwin.cmake b/platform/darwin/darwin.cmake index 4217aa752bd5..3b959cbbea64 100644 --- a/platform/darwin/darwin.cmake +++ b/platform/darwin/darwin.cmake @@ -164,6 +164,7 @@ add_library( "${CMAKE_CURRENT_LIST_DIR}/app/CustomStyleLayerExample.m" "${CMAKE_CURRENT_LIST_DIR}/app/PluginLayerExample.mm" "${CMAKE_CURRENT_LIST_DIR}/app/PluginLayerExampleMetalRendering.mm" + "${CMAKE_CURRENT_LIST_DIR}/app/StyleFilterExample.mm" ) target_link_libraries( From fb99190e12e93e5ec0529c123a0f6fdfdb83aa0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sun, 27 Jul 2025 16:16:10 -0400 Subject: [PATCH 140/221] Fix for swift app compile --- platform/darwin/bazel/files.bzl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/darwin/bazel/files.bzl b/platform/darwin/bazel/files.bzl index da71263cf5d5..2ce988a44ce7 100644 --- a/platform/darwin/bazel/files.bzl +++ b/platform/darwin/bazel/files.bzl @@ -108,8 +108,7 @@ MLN_DARWIN_OBJC_HEADERS = [ "src/NSValue+MLNAdditions.h", "src/MLNPluginLayer.h", "src/MLNPluginStyleLayer.h", - "src/MLNStyleFilter.h", - "src/MLNStyleFilter_Private.h", + "src/MLNStyleFilter.h" ] MLN_DARWIN_OBJCPP_HEADERS = [ From e126973cc58bc39a1de6d7a4fb7f1987fb15689e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sun, 27 Jul 2025 16:22:10 -0400 Subject: [PATCH 141/221] Updates for cmake --- CMakeLists.txt | 1 + platform/darwin/darwin.cmake | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f24a62dc5d4..c4ee1164e549 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -977,6 +977,7 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_properties.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_impl.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_factory.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_file_source.hpp ) diff --git a/platform/darwin/darwin.cmake b/platform/darwin/darwin.cmake index 4217aa752bd5..656fecb9bf3a 100644 --- a/platform/darwin/darwin.cmake +++ b/platform/darwin/darwin.cmake @@ -63,6 +63,7 @@ target_sources( ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/storage/offline_database.cpp ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/storage/offline_download.cpp ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/storage/online_file_source.cpp + ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/storage/plugin_file_source.cpp ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/storage/$,pmtiles_file_source.cpp,pmtiles_file_source_stub.cpp> ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/storage/sqlite3.cpp ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/text/bidi.cpp @@ -164,6 +165,7 @@ add_library( "${CMAKE_CURRENT_LIST_DIR}/app/CustomStyleLayerExample.m" "${CMAKE_CURRENT_LIST_DIR}/app/PluginLayerExample.mm" "${CMAKE_CURRENT_LIST_DIR}/app/PluginLayerExampleMetalRendering.mm" + "${CMAKE_CURRENT_LIST_DIR}/app/PluginProtocolExample.mm" ) target_link_libraries( From 1fa1a0e5bd77833a65c02b359f1585d3bd9f3a65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sun, 27 Jul 2025 16:25:42 -0400 Subject: [PATCH 142/221] Added header back in the right place this time --- platform/darwin/bazel/files.bzl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/darwin/bazel/files.bzl b/platform/darwin/bazel/files.bzl index 2ce988a44ce7..d069ef97f8a3 100644 --- a/platform/darwin/bazel/files.bzl +++ b/platform/darwin/bazel/files.bzl @@ -166,8 +166,8 @@ MLN_DARWIN_PRIVATE_HEADERS = [ "src/MLNVectorTileSource_Private.h", "src/NSExpression+MLNPrivateAdditions.h", "src/NSPredicate+MLNPrivateAdditions.h", - "src/MLNPluginStyleLayer_Private.h" - + "src/MLNPluginStyleLayer_Private.h", + "src/MLNStyleFilter_Private.h" ] MLN_DARWIN_PUBLIC_OBJCPP_SOURCE = [ From 10c8c0df979a3115aa7e076937e9ed45f6d4e30e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Mon, 28 Jul 2025 00:06:19 -0400 Subject: [PATCH 143/221] Fix compiler error --- src/mbgl/plugin/feature_collection_bucket.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/mbgl/plugin/feature_collection_bucket.cpp b/src/mbgl/plugin/feature_collection_bucket.cpp index 9ef46fd84df8..0cd7eabc218a 100644 --- a/src/mbgl/plugin/feature_collection_bucket.cpp +++ b/src/mbgl/plugin/feature_collection_bucket.cpp @@ -54,9 +54,9 @@ std::string toString(FeatureIdentifier& v) { void FeatureCollectionBucket::addFeature(const GeometryTileFeature& tileFeature, const GeometryCollection& geometeryCollection, - const mbgl::ImagePositions& imagePositions, - const PatternLayerMap& patternLayerMap, - std::size_t size, + [[maybe_unused]] const mbgl::ImagePositions& imagePositions, + [[maybe_unused]] const PatternLayerMap& patternLayerMap, + [[maybe_unused]] std::size_t size, const CanonicalTileID& tileID) { std::shared_ptr tempFeature = std::make_shared(); @@ -106,7 +106,6 @@ void FeatureCollectionBucket::addFeature(const GeometryTileFeature& tileFeature, plugin::FeatureCoordinateCollection c; for (std::size_t i = 0, len = g.size(); i < len; i++) { const GeometryCoordinate& p1 = g[i]; - auto d = b.west(); double lat = 0; double lon = 0; geometryToLatLon(p1, tileID.x, tileID.y, tileID.z, lat, lon); From 87b27bce975800adfb93f0e09a4c6681c3d57de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Mon, 28 Jul 2025 00:13:36 -0400 Subject: [PATCH 144/221] More compiler errors --- src/mbgl/plugin/feature_collection.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mbgl/plugin/feature_collection.hpp b/src/mbgl/plugin/feature_collection.hpp index a4199a110747..1653ff512f99 100644 --- a/src/mbgl/plugin/feature_collection.hpp +++ b/src/mbgl/plugin/feature_collection.hpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace mbgl { From d6a7000b4516c9f9dbe4e3e75cf5ed2e74cec34f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Mon, 28 Jul 2025 00:15:37 -0400 Subject: [PATCH 145/221] Re-ordered headers --- src/mbgl/plugin/feature_collection.hpp | 5 ++--- src/mbgl/plugin/feature_collection_bucket.cpp | 4 ++-- src/mbgl/plugin/feature_collection_bucket.hpp | 8 ++++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/mbgl/plugin/feature_collection.hpp b/src/mbgl/plugin/feature_collection.hpp index 1653ff512f99..3ea9b5c70b5a 100644 --- a/src/mbgl/plugin/feature_collection.hpp +++ b/src/mbgl/plugin/feature_collection.hpp @@ -2,11 +2,10 @@ #include -#include -#include -#include #include #include +#include +#include namespace mbgl { diff --git a/src/mbgl/plugin/feature_collection_bucket.cpp b/src/mbgl/plugin/feature_collection_bucket.cpp index 0cd7eabc218a..05cdf268c4b6 100644 --- a/src/mbgl/plugin/feature_collection_bucket.cpp +++ b/src/mbgl/plugin/feature_collection_bucket.cpp @@ -1,7 +1,7 @@ -#include +#include #include #include -#include +#include using namespace mbgl; diff --git a/src/mbgl/plugin/feature_collection_bucket.hpp b/src/mbgl/plugin/feature_collection_bucket.hpp index ccb28d35d018..fc5499488822 100644 --- a/src/mbgl/plugin/feature_collection_bucket.hpp +++ b/src/mbgl/plugin/feature_collection_bucket.hpp @@ -1,13 +1,13 @@ #pragma once -#include -#include -#include #include #include +#include +#include +#include #include #include -#include +#include #include From 5ba266c398006250ada782d78b0539a066b5657a Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Mon, 28 Jul 2025 12:19:31 +0300 Subject: [PATCH 146/221] fix set content inset to call the correct function --- platform/ios/VERSION | 2 +- platform/ios/src/MLNMapView.mm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/ios/VERSION b/platform/ios/VERSION index 83aa95a7ad49..89b71fa94204 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.17.3 +6.17.4 diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index b3b3839d67c0..5c5d52418d5f 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -6354,7 +6354,7 @@ - (void)locationManager:(__unused id)manager didUpdateLocati - (void)didUpdateLocationWithUserTrackingAnimated:(BOOL)animated completionHandler:(nullable void (^)(void))completion { - [self didUpdateLocationWithUserTrackingAnimated:animated completionHandler:completion]; + [self didUpdateLocationWithUserTrackingDuration:animated ? MLNUserLocationAnimationDuration : 0 completionHandler:completion]; } - (void)didUpdateLocationWithUserTrackingDuration:(NSTimeInterval)duration completionHandler:(nullable void (^)(void))completion From f24f86c3d231125bdfdd41ccadc5243f1d1252e5 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 24 Jul 2025 10:19:16 +0300 Subject: [PATCH 147/221] expose frustum offset to internal API and modify projection matrix to use it --- include/mbgl/map/map.hpp | 3 +++ include/mbgl/map/map_options.hpp | 4 ++++ src/mbgl/map/map.cpp | 11 +++++++++++ src/mbgl/map/map_options.cpp | 7 +++++++ src/mbgl/map/transform.cpp | 9 +++++++++ src/mbgl/map/transform.hpp | 6 ++++++ src/mbgl/map/transform_state.cpp | 15 ++++++++++++++- src/mbgl/map/transform_state.hpp | 4 ++++ 8 files changed, 58 insertions(+), 1 deletion(-) diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index c83976ec6af1..07c523db59e8 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -107,6 +108,8 @@ class Map : private util::noncopyable { void setConstrainMode(ConstrainMode); void setViewportMode(ViewportMode); void setSize(Size); + void setFrustumOffset(const EdgeInsets&); + EdgeInsets getFrustumOffset(); MapOptions getMapOptions() const; // Projection Mode diff --git a/include/mbgl/map/map_options.hpp b/include/mbgl/map/map_options.hpp index 12a6b874f9e0..30a143468375 100644 --- a/include/mbgl/map/map_options.hpp +++ b/include/mbgl/map/map_options.hpp @@ -111,6 +111,10 @@ class MapOptions final { */ MapOptions& withSize(Size size_); + MapOptions& withFrustumOffset(const EdgeInsets& frustuOffset_); + + MapOptions& withFrustumOffset(const EdgeInsets& frustuOffset_); + /** * @brief Gets the previously set size. * diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 26d9a36d9014..8ad07b9bad25 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -377,6 +378,15 @@ void Map::setSize(const Size size) { impl->onUpdate(); } +void Map::setFrustumOffset(const EdgeInsets& frustumOffset) { + impl->transform->setFrustumOffset(frustumOffset); + impl->onUpdate(); +} + +EdgeInsets Map::getFrustumOffset() { + return impl->transform->getFrustumOffset(); +} + void Map::setNorthOrientation(NorthOrientation orientation) { impl->transform->setNorthOrientation(orientation); impl->onUpdate(); @@ -400,6 +410,7 @@ MapOptions Map::getMapOptions() const { .withCrossSourceCollisions(impl->crossSourceCollisions) .withNorthOrientation(impl->transform->getNorthOrientation()) .withSize(impl->transform->getState().getSize()) + .withFrustumOffset(impl->transform->getState().getFrustumOffset()) .withPixelRatio(impl->pixelRatio)); } diff --git a/src/mbgl/map/map_options.cpp b/src/mbgl/map/map_options.cpp index 656d09a65069..ffbdaeea5d1a 100644 --- a/src/mbgl/map/map_options.cpp +++ b/src/mbgl/map/map_options.cpp @@ -1,4 +1,5 @@ #include +#include namespace mbgl { @@ -10,6 +11,7 @@ class MapOptions::Impl { NorthOrientation orientation = NorthOrientation::Upwards; bool crossSourceCollisions = true; Size size = {64, 64}; + EdgeInsets frustumOffset = {0.f, 0.f, 0.f, 0.f}; float pixelRatio = 1.0; }; @@ -69,6 +71,11 @@ MapOptions& MapOptions::withSize(Size size_) { return *this; } +MapOptions& MapOptions::withFrustumOffset(const EdgeInsets& frustumOffset_) { + impl_->frustumOffset = frustumOffset_; + return *this; +} + Size MapOptions::size() const { return impl_->size; } diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index 0f16553cc268..5a6fe4a7f65b 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -429,6 +430,14 @@ void Transform::setMaxPitch(const double maxPitch) { state.setMaxPitch(util::deg2rad(maxPitch)); } +void Transform::setFrustumOffset(const EdgeInsets& frustumOffset) { + state.setFrustumOffset(frustumOffset); +} + +EdgeInsets Transform::getFrustumOffset() { + return state.getFrustumOffset(); +} + // MARK: - Bearing void Transform::rotateBy(const ScreenCoordinate& first, diff --git a/src/mbgl/map/transform.hpp b/src/mbgl/map/transform.hpp index d051584a807e..e9b0bab53fc0 100644 --- a/src/mbgl/map/transform.hpp +++ b/src/mbgl/map/transform.hpp @@ -83,6 +83,12 @@ class Transform { void setMinPitch(double); void setMaxPitch(double); + void setFrustumOffset(const EdgeInsets&); + EdgeInsets getFrustumOffset(); + + void setFrustumOffset(const EdgeInsets&); + EdgeInsets getFrustumOffset(); + // Zoom /** Returns the zoom level. */ diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp index 773b7d843f6a..8b9a425be9d2 100644 --- a/src/mbgl/map/transform_state.cpp +++ b/src/mbgl/map/transform_state.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -120,7 +121,8 @@ void TransformState::getProjMatrix(mat4& projMatrix, uint16_t nearZ, bool aligne // (the distance between[width/2, height/2] and [width/2 + 1, height/2]) // See https://github.com/mapbox/mapbox-gl-native/pull/15195 for details. // See TransformState::fov description: fov = 2 * arctan((height / 2) / (height * 1.5)). - const double tanFovAboveCenter = (size.height * 0.5 + offset.y) / (size.height * 1.5); + const double tanFovAboveCenter = + ((size.height - frustumOffset.top()) * 0.5 + (offset.y - (frustumOffset.top() / 2))) / (size.height * 1.5); const double tanMultiple = tanFovAboveCenter * std::tan(getPitch()); assert(tanMultiple < 1); // Calculate z distance of the farthest fragment that should be rendered. @@ -372,6 +374,17 @@ void TransformState::setSize(const Size& size_) { } } +EdgeInsets TransformState::getFrustumOffset() const { + return frustumOffset; +} + +void TransformState::setFrustumOffset(const EdgeInsets& frustumOffset_) { + if (frustumOffset != frustumOffset_) { + frustumOffset = frustumOffset_; + requestMatricesUpdate = true; + } +} + // MARK: - North Orientation NorthOrientation TransformState::getNorthOrientation() const { diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp index ae4ce86efd5b..5322a1e24370 100644 --- a/src/mbgl/map/transform_state.hpp +++ b/src/mbgl/map/transform_state.hpp @@ -118,6 +118,9 @@ class TransformState { Size getSize() const; void setSize(const Size& size_); + EdgeInsets getFrustumOffset() const; + void setFrustumOffset(const EdgeInsets& frustumOffset_); + // North Orientation NorthOrientation getNorthOrientation() const; double getNorthOrientationAngle() const; @@ -246,6 +249,7 @@ class TransformState { // logical dimensions Size size; + EdgeInsets frustumOffset; mat4 coordinatePointMatrix(const mat4& projMatrix) const; mat4 getPixelMatrix() const; From decae8ce012e1e1c9465625a849d431db6d8dd15 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 24 Jul 2025 10:31:00 +0300 Subject: [PATCH 148/221] expose frustumoffset to ios and add scissor test to the metal drawable --- include/mbgl/mtl/render_pass.hpp | 2 ++ platform/ios/src/MLNMapView.h | 2 ++ platform/ios/src/MLNMapView.mm | 10 ++++++++++ src/mbgl/mtl/drawable.cpp | 8 ++++++++ src/mbgl/mtl/render_pass.cpp | 9 +++++++++ 5 files changed, 31 insertions(+) diff --git a/include/mbgl/mtl/render_pass.hpp b/include/mbgl/mtl/render_pass.hpp index c7a94821b183..799ae92a7ce9 100644 --- a/include/mbgl/mtl/render_pass.hpp +++ b/include/mbgl/mtl/render_pass.hpp @@ -62,6 +62,7 @@ class RenderPass final : public gfx::RenderPass { void setCullMode(const MTL::CullMode); void setFrontFacingWinding(const MTL::Winding); + void setScissorRect(const MTL::ScissorRect); private: void pushDebugGroup(const char* name) override; @@ -92,6 +93,7 @@ class RenderPass final : public gfx::RenderPass { MTL::CullMode currentCullMode = MTL::CullModeNone; MTL::Winding currentWinding = MTL::WindingClockwise; + MTL::ScissorRect currentRect; }; } // namespace mtl diff --git a/platform/ios/src/MLNMapView.h b/platform/ios/src/MLNMapView.h index a78bf0833e74..197c8c8c6baa 100644 --- a/platform/ios/src/MLNMapView.h +++ b/platform/ios/src/MLNMapView.h @@ -508,6 +508,8 @@ MLN_EXPORT */ @property (nonatomic, assign) double tileLodZoomShift; +@property (nonatomic, assign) UIEdgeInsets frustumOffset; + // MARK: Displaying the User’s Location /** diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 5c5d52418d5f..310df9a9b90f 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -3310,6 +3310,16 @@ -(double)tileLodZoomShift return _mbglMap->getTileLodZoomShift(); } +-(void)setFrustumOffset:(UIEdgeInsets)frustomOffset +{ + _mbglMap->setFrustumOffset(MLNEdgeInsetsFromNSEdgeInsets(frustomOffset)); +} + +-(UIEdgeInsets)frustumOffset +{ + return NSEdgeInsetsFromMLNEdgeInsets(_mbglMap->getFrustumOffset()); +} + // MARK: - Accessibility - - (NSString *)accessibilityValue diff --git a/src/mbgl/mtl/drawable.cpp b/src/mbgl/mtl/drawable.cpp index f41d84d5c8c2..62ee3dbacc53 100644 --- a/src/mbgl/mtl/drawable.cpp +++ b/src/mbgl/mtl/drawable.cpp @@ -214,6 +214,14 @@ void Drawable::draw(PaintParameters& parameters) const { const auto& cullMode = getCullFaceMode(); renderPass.setCullMode(cullMode.enabled ? mapCullMode(cullMode.side) : MTL::CullModeNone); renderPass.setFrontFacingWinding(mapWindingMode(cullMode.winding)); + EdgeInsets offset = parameters.state.getFrustumOffset(); + Size size = parameters.state.getSize(); + double pixelRatio = parameters.pixelRatio; + MTL::ScissorRect rect = {static_cast(offset.left() * pixelRatio), + static_cast(offset.top() * pixelRatio), + static_cast((size.width - (offset.left() + offset.right())) * pixelRatio), + static_cast((size.height - (offset.top() + offset.bottom())) * pixelRatio)}; + renderPass.setScissorRect(rect); if (!impl->pipelineState) { impl->pipelineState = shaderMTL.getRenderPipelineState( diff --git a/src/mbgl/mtl/render_pass.cpp b/src/mbgl/mtl/render_pass.cpp index c9690dd0c1e8..c38a18bbd6a8 100644 --- a/src/mbgl/mtl/render_pass.cpp +++ b/src/mbgl/mtl/render_pass.cpp @@ -78,6 +78,7 @@ void RenderPass::resetState() { currentCullMode = MTL::CullModeNone; currentWinding = MTL::WindingClockwise; + currentRect = {0, 0, 0, 0}; } namespace { @@ -215,5 +216,13 @@ void RenderPass::setFrontFacingWinding(const MTL::Winding winding) { } } +void RenderPass::setScissorRect(const MTL::ScissorRect rect) { + if (rect.x != currentRect.x || rect.y != currentRect.y || rect.width != currentRect.width || + rect.height != currentRect.height) { + encoder->setScissorRect(rect); + currentRect = rect; + } +} + } // namespace mtl } // namespace mbgl From 4ebca1d129fa7f4ac59e8d20ccf27336b78e940b Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 24 Jul 2025 10:36:03 +0300 Subject: [PATCH 149/221] remove repeated properties --- include/mbgl/map/map_options.hpp | 2 -- src/mbgl/map/transform.hpp | 3 --- 2 files changed, 5 deletions(-) diff --git a/include/mbgl/map/map_options.hpp b/include/mbgl/map/map_options.hpp index 30a143468375..9c6def668757 100644 --- a/include/mbgl/map/map_options.hpp +++ b/include/mbgl/map/map_options.hpp @@ -113,8 +113,6 @@ class MapOptions final { MapOptions& withFrustumOffset(const EdgeInsets& frustuOffset_); - MapOptions& withFrustumOffset(const EdgeInsets& frustuOffset_); - /** * @brief Gets the previously set size. * diff --git a/src/mbgl/map/transform.hpp b/src/mbgl/map/transform.hpp index e9b0bab53fc0..ab30722bafd6 100644 --- a/src/mbgl/map/transform.hpp +++ b/src/mbgl/map/transform.hpp @@ -86,9 +86,6 @@ class Transform { void setFrustumOffset(const EdgeInsets&); EdgeInsets getFrustumOffset(); - void setFrustumOffset(const EdgeInsets&); - EdgeInsets getFrustumOffset(); - // Zoom /** Returns the zoom level. */ From e1702433781c91387475ee9e341d02f86a2a0a4e Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 24 Jul 2025 10:36:33 +0300 Subject: [PATCH 150/221] expose frustumoffset to vulkan and use it for scissor test --- include/mbgl/gfx/drawable.hpp | 7 +++++++ include/mbgl/vulkan/drawable.hpp | 2 ++ include/mbgl/vulkan/pipeline.hpp | 5 +++++ src/mbgl/gfx/drawable.cpp | 10 ++++++++++ src/mbgl/gfx/scissor_rect.hpp | 21 +++++++++++++++++++++ src/mbgl/shaders/vulkan/shader_program.cpp | 4 +++- src/mbgl/vulkan/drawable.cpp | 5 +++++ src/mbgl/vulkan/pipeline.cpp | 10 ++++++++++ 8 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/mbgl/gfx/scissor_rect.hpp diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index d820040dbea3..1160ef3e809c 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -35,6 +35,7 @@ namespace gfx { class ColorMode; class CullFaceMode; +class ScissorRect; enum class DepthMaskType : bool; class DrawableTweaker; class DrawMode; @@ -187,6 +188,12 @@ class Drawable { /// Set color mode virtual void setColorMode(const gfx::ColorMode&); + /// Get scissor rect + const gfx::ScissorRect& getScissorRect() const; + + /// Sset scissor rect + virtual void setScissorRect(const gfx::ScissorRect&); + /// Get the vertex attributes that override default values in the shader program const gfx::VertexAttributeArrayPtr& getVertexAttributes() const noexcept { return vertexAttributes; } diff --git a/include/mbgl/vulkan/drawable.hpp b/include/mbgl/vulkan/drawable.hpp index 9ed2c2982ceb..7134fbc8e192 100644 --- a/include/mbgl/vulkan/drawable.hpp +++ b/include/mbgl/vulkan/drawable.hpp @@ -3,6 +3,7 @@ #include #include +#include #include namespace mbgl { @@ -43,6 +44,7 @@ class Drawable : public gfx::Drawable { void setLineWidth(int32_t value) override; void setCullFaceMode(const gfx::CullFaceMode&) override; + void setScissorRect(const gfx::ScissorRect&) override; void updateVertexAttributes(gfx::VertexAttributeArrayPtr, std::size_t vertexCount, diff --git a/include/mbgl/vulkan/pipeline.hpp b/include/mbgl/vulkan/pipeline.hpp index 69c909e09767..aede451c83ec 100644 --- a/include/mbgl/vulkan/pipeline.hpp +++ b/include/mbgl/vulkan/pipeline.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -41,6 +42,8 @@ class PipelineInfo final { bool wideLines = false; + vk::Rect2D scissorRect; + // external values (used in hash) vk::RenderPass renderPass{}; vk::Extent2D viewExtent{}; @@ -67,6 +70,7 @@ class PipelineInfo final { static vk::CompareOp vulkanCompareOp(const gfx::DepthFunctionType& value); static vk::CompareOp vulkanCompareOp(const gfx::StencilFunctionType& value); static vk::StencilOp vulkanStencilOp(const gfx::StencilOpType& value); + static vk::Rect2D vulkanScissorRect(const gfx::ScissorRect& value); void setCullMode(const gfx::CullFaceMode& value); void setDrawMode(const gfx::DrawModeType& value); @@ -78,6 +82,7 @@ class PipelineInfo final { void setStencilMode(const gfx::StencilMode& value); void setRenderable(const gfx::Renderable& value); void setLineWidth(float value); + void setScissorRect(const gfx::ScissorRect& value); bool usesBlendConstants() const; void updateVertexInputHash(); diff --git a/src/mbgl/gfx/drawable.cpp b/src/mbgl/gfx/drawable.cpp index 82d053f08ead..e04156c89b81 100644 --- a/src/mbgl/gfx/drawable.cpp +++ b/src/mbgl/gfx/drawable.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +15,7 @@ namespace gfx { struct Drawable::Impl { gfx::ColorMode colorMode = gfx::ColorMode::disabled(); gfx::CullFaceMode cullFaceMode = gfx::CullFaceMode::disabled(); + gfx::ScissorRect scissorRect = {0.f, 0.f, 0.f, 0.f}; std::shared_ptr bucket; PaintPropertyBindersBase* binders = nullptr; // owned by `bucket` @@ -46,6 +48,14 @@ void Drawable::setCullFaceMode(const gfx::CullFaceMode& value) { impl->cullFaceMode = value; } +const gfx::ScissorRect& Drawable::getScissorRect() const { + return impl->scissorRect; +} + +void Drawable::setScissorRect(const gfx::ScissorRect& value) { + impl->scissorRect = value; +} + void Drawable::setIndexData(std::vector indexes, std::vector segments) { setIndexData(std::make_shared(std::move(indexes)), std::move(segments)); } diff --git a/src/mbgl/gfx/scissor_rect.hpp b/src/mbgl/gfx/scissor_rect.hpp new file mode 100644 index 000000000000..7e21f9cb0b32 --- /dev/null +++ b/src/mbgl/gfx/scissor_rect.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include + +namespace mbgl { +namespace gfx { + +class ScissorRect { +public: + int32_t x, y; + uint32_t width, height; + + bool operator==(const ScissorRect& other) const { + return x == other.x && y == other.y && width == other.width && height == other.height; + } + + bool operator!=(const ScissorRect& other) const { return !(*this == other); } +}; + +} // namespace gfx +} // namespace mbgl diff --git a/src/mbgl/shaders/vulkan/shader_program.cpp b/src/mbgl/shaders/vulkan/shader_program.cpp index b4d000bbab5e..72763069bcfd 100644 --- a/src/mbgl/shaders/vulkan/shader_program.cpp +++ b/src/mbgl/shaders/vulkan/shader_program.cpp @@ -129,7 +129,9 @@ const vk::UniquePipeline& ShaderProgram::getPipeline(const PipelineInfo& pipelin const auto renderableExtent = pipelineInfo.viewExtent; const vk::Viewport viewportExtent(0.0f, 0.0f, renderableExtent.width, renderableExtent.height, 0.0f, 1.0f); - const vk::Rect2D scissorRect({}, {renderableExtent.width, renderableExtent.height}); + const vk::Rect2D scissorRect({pipeline.scissorRect.offset.x, pipeline.scissorRect.offset.y}, + {renderableExtent.width + pipelineInfo.scissorRect.extent.width, + renderableExtent.height + pipelineInfo.scissorRect.extent.height}); const auto viewportState = vk::PipelineViewportStateCreateInfo() .setViewportCount(1) diff --git a/src/mbgl/vulkan/drawable.cpp b/src/mbgl/vulkan/drawable.cpp index 2fedddc32bfd..2b72aec8d7a3 100644 --- a/src/mbgl/vulkan/drawable.cpp +++ b/src/mbgl/vulkan/drawable.cpp @@ -101,6 +101,11 @@ void Drawable::setCullFaceMode(const gfx::CullFaceMode& mode) { impl->pipelineInfo.setCullMode(mode); } +void Drawable::setScissorRect(const gfx::ScissorRect& rect) { + gfx::Drawable::setScissorRect(rect); + impl->pipelineInfo.setScissorRect(rect); +} + void Drawable::updateVertexAttributes(gfx::VertexAttributeArrayPtr vertices, std::size_t vertexCount, gfx::DrawMode mode, diff --git a/src/mbgl/vulkan/pipeline.cpp b/src/mbgl/vulkan/pipeline.cpp index db1d2645a354..efc4f5974f78 100644 --- a/src/mbgl/vulkan/pipeline.cpp +++ b/src/mbgl/vulkan/pipeline.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -110,6 +111,10 @@ vk::CullModeFlagBits PipelineInfo::vulkanCullMode(const gfx::CullFaceSideType& v } } +vk::Rect2D PipelineInfo::vulkanScissorRect(const gfx::ScissorRect& value) { + return {{value.x, value.y}, {value.width, value.height}}; +} + vk::FrontFace PipelineInfo::vulkanFrontFace(const gfx::CullFaceWindingType& value) { switch (value) { default: @@ -245,6 +250,10 @@ void PipelineInfo::setCullMode(const gfx::CullFaceMode& value) { frontFace = vulkanFrontFace(value.winding); } +void PipelineInfo::setScissorRect(const gfx::ScissorRect& value) { + scissorRect = vulkanScissorRect(value); +} + void PipelineInfo::setDrawMode(const gfx::DrawModeType& value) { topology = vulkanPrimitiveTopology(value); } @@ -399,6 +408,7 @@ std::size_t PipelineInfo::hash() const { stencilFail, stencilDepthFail, wideLines, + scissorRect, VkRenderPass(renderPass), #if !USE_DYNAMIC_VIEWPORT viewExtent.width, From 54c8e00bedc172438039da7a864978f288f020b7 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 24 Jul 2025 10:37:17 +0300 Subject: [PATCH 151/221] expose frustum offset to opengl and use it for scissor test --- src/mbgl/gl/context.cpp | 7 +++++++ src/mbgl/gl/context.hpp | 3 +++ src/mbgl/gl/drawable_gl.cpp | 1 + src/mbgl/gl/value.hpp | 8 ++++++++ 4 files changed, 19 insertions(+) diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 4659190c3a4a..12e4e68e604b 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -460,6 +461,7 @@ void Context::resetState(gfx::DepthMode depthMode, gfx::ColorMode colorMode) { setStencilMode(gfx::StencilMode::disabled()); setColorMode(colorMode); setCullFaceMode(gfx::CullFaceMode::disabled()); + setScissorRect({0.f, 0.f, 0.f, 0.f}); } bool Context::emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr& buffer, @@ -515,6 +517,7 @@ void Context::setDirtyState() { cullFace.setDirty(); cullFaceSide.setDirty(); cullFaceWinding.setDirty(); + scissorRect.setDirt(); program.setDirty(); lineWidth.setDirty(); activeTextureUnit.setDirty(); @@ -639,6 +642,10 @@ void Context::setCullFaceMode(const gfx::CullFaceMode& mode) { cullFaceWinding = mode.winding; } +void Context::setScissorRect(const gfx::ScissorRect& rect) { + scissorRect = rect; +} + void Context::setDepthMode(const gfx::DepthMode& depth) { if (depth.func == gfx::DepthFunctionType::Always && depth.mask != gfx::DepthMaskType::ReadWrite) { depthTest = false; diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index d7757e15c120..89c237f9d661 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -77,6 +78,7 @@ class Context final : public gfx::Context { void setStencilMode(const gfx::StencilMode&); void setColorMode(const gfx::ColorMode&); void setCullFaceMode(const gfx::CullFaceMode&); + void setScissorRect(const gfx::ScissorRect&); void draw(const gfx::DrawMode&, std::size_t indexOffset, std::size_t indexLength); @@ -204,6 +206,7 @@ class Context final : public gfx::Context { State cullFace; State cullFaceSide; State cullFaceWinding; + State scissorRect; public: std::unique_ptr createOffscreenTexture(Size, gfx::TextureChannelDataType) override; diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp index c335cebd1873..b1577a428d0a 100644 --- a/src/mbgl/gl/drawable_gl.cpp +++ b/src/mbgl/gl/drawable_gl.cpp @@ -59,6 +59,7 @@ void DrawableGL::draw(PaintParameters& parameters) const { context.setColorMode(getColorMode()); context.setCullFaceMode(getCullFaceMode()); + context.setScissorRect(getScissorRect()); impl->uniformBuffers.bind(); bindTextures(); diff --git a/src/mbgl/gl/value.hpp b/src/mbgl/gl/value.hpp index cea3136a008f..b5586b34fe7b 100644 --- a/src/mbgl/gl/value.hpp +++ b/src/mbgl/gl/value.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -238,6 +239,13 @@ struct CullFaceWinding { static Type Get(); }; +struct ScissorRect { + using Type = gfx::ScissorRect; + static const constexpr Type Default = {0.f, 0.f, 0.f, 0.f}; + static void Set(const Type&); + static Type Get(); +}; + struct BindTexture { using Type = gl::TextureID; static const constexpr Type Default = 0; From 4d98044c05b0ec9ae7a556ad43a48fed0a08bf77 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 24 Jul 2025 10:38:06 +0300 Subject: [PATCH 152/221] ignore files that aren't used --- benchmark/android/.gitignore | 4 ++++ metrics/.gitignore | 1 + platform/android/.gitignore | 6 ++++++ platform/ios/app-swift/Data/.gitignore | 4 ++++ render-test/android/.gitignore | 4 ++++ test/android/.gitignore | 4 ++++ 6 files changed, 23 insertions(+) create mode 100644 metrics/.gitignore create mode 100644 platform/ios/app-swift/Data/.gitignore diff --git a/benchmark/android/.gitignore b/benchmark/android/.gitignore index 3bb19ffd7868..efe951c706c4 100644 --- a/benchmark/android/.gitignore +++ b/benchmark/android/.gitignore @@ -1 +1,5 @@ .gradle/ +.project +.settings +.classpath +build/ diff --git a/metrics/.gitignore b/metrics/.gitignore new file mode 100644 index 000000000000..2d19fc766d98 --- /dev/null +++ b/metrics/.gitignore @@ -0,0 +1 @@ +*.html diff --git a/platform/android/.gitignore b/platform/android/.gitignore index 14c4f869cb2a..f164c7f3145a 100644 --- a/platform/android/.gitignore +++ b/platform/android/.gitignore @@ -1 +1,7 @@ MapLibreAndroid/src/vulkanDebug +.project +.settings +.classpath +.kotlin +build/ +lint/ diff --git a/platform/ios/app-swift/Data/.gitignore b/platform/ios/app-swift/Data/.gitignore new file mode 100644 index 000000000000..7e3da378d373 --- /dev/null +++ b/platform/ios/app-swift/Data/.gitignore @@ -0,0 +1,4 @@ +*.glb +*.metal +*.txt +*.json diff --git a/render-test/android/.gitignore b/render-test/android/.gitignore index 51e9160c76c4..9fbaf0ceead5 100644 --- a/render-test/android/.gitignore +++ b/render-test/android/.gitignore @@ -2,3 +2,7 @@ .gradle app/build app/src/main/assets/data.zip +.project +.settings +.classpath +build/ diff --git a/test/android/.gitignore b/test/android/.gitignore index 386f9d729622..c75999799e91 100644 --- a/test/android/.gitignore +++ b/test/android/.gitignore @@ -1,3 +1,7 @@ .gradle/ **/.cxx/ app/build +.project +.settings +.classpath +build/ From da37dbfc75927b70f7e57f997aed25c5d25e60ac Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 24 Jul 2025 11:46:02 +0300 Subject: [PATCH 153/221] resolve build issues --- bazel/core.bzl | 1 + src/mbgl/gfx/drawable.cpp | 2 +- src/mbgl/gl/value.hpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/bazel/core.bzl b/bazel/core.bzl index d1f549f3afa5..319f921f4400 100644 --- a/bazel/core.bzl +++ b/bazel/core.bzl @@ -143,6 +143,7 @@ MLN_CORE_SOURCE = [ "src/mbgl/gfx/color_mode.hpp", "src/mbgl/gfx/command_encoder.hpp", "src/mbgl/gfx/cull_face_mode.hpp", + "src/mbgl/gfx/scissor_rect.hpp", "src/mbgl/gfx/debug_group.hpp", "src/mbgl/gfx/depth_mode.hpp", "src/mbgl/gfx/draw_mode.hpp", diff --git a/src/mbgl/gfx/drawable.cpp b/src/mbgl/gfx/drawable.cpp index e04156c89b81..ef851ddea386 100644 --- a/src/mbgl/gfx/drawable.cpp +++ b/src/mbgl/gfx/drawable.cpp @@ -15,7 +15,7 @@ namespace gfx { struct Drawable::Impl { gfx::ColorMode colorMode = gfx::ColorMode::disabled(); gfx::CullFaceMode cullFaceMode = gfx::CullFaceMode::disabled(); - gfx::ScissorRect scissorRect = {0.f, 0.f, 0.f, 0.f}; + gfx::ScissorRect scissorRect = {0, 0, 0, 0}; std::shared_ptr bucket; PaintPropertyBindersBase* binders = nullptr; // owned by `bucket` diff --git a/src/mbgl/gl/value.hpp b/src/mbgl/gl/value.hpp index b5586b34fe7b..5feb6f2834d9 100644 --- a/src/mbgl/gl/value.hpp +++ b/src/mbgl/gl/value.hpp @@ -241,7 +241,7 @@ struct CullFaceWinding { struct ScissorRect { using Type = gfx::ScissorRect; - static const constexpr Type Default = {0.f, 0.f, 0.f, 0.f}; + static const constexpr Type Default = {0, 0, 0, 0}; static void Set(const Type&); static Type Get(); }; From f117cd308e3bd798f5fd649ee66ec5e9520bc658 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 24 Jul 2025 13:56:40 +0300 Subject: [PATCH 154/221] add missing vulkan and opengl files --- include/mbgl/gl/renderer_backend.hpp | 4 ++-- .../MapLibreAndroid/src/cpp/native_map_view.cpp | 11 ++++++++++- .../MapLibreAndroid/src/cpp/native_map_view.hpp | 2 ++ .../java/org/maplibre/android/maps/MapLibreMap.java | 4 ++++ .../java/org/maplibre/android/maps/NativeMap.java | 2 ++ .../org/maplibre/android/maps/NativeMapView.java | 8 ++++++++ platform/default/src/mbgl/gl/headless_backend.cpp | 2 +- src/mbgl/gl/context.cpp | 12 ++++++------ src/mbgl/gl/context.hpp | 3 +-- src/mbgl/gl/drawable_gl.cpp | 10 +++++++++- src/mbgl/gl/offscreen_texture.cpp | 2 +- src/mbgl/gl/renderer_backend.cpp | 8 ++++---- src/mbgl/gl/value.cpp | 10 ++++++---- src/mbgl/gl/value.hpp | 6 +++--- src/mbgl/map/transform_state.hpp | 5 +++++ src/mbgl/shaders/vulkan/shader_program.cpp | 4 +--- src/mbgl/vulkan/context.cpp | 2 ++ src/mbgl/vulkan/drawable.cpp | 9 +++++++++ src/mbgl/vulkan/pipeline.cpp | 12 ------------ test/util/offscreen_texture.test.cpp | 6 ++---- 20 files changed, 78 insertions(+), 44 deletions(-) diff --git a/include/mbgl/gl/renderer_backend.hpp b/include/mbgl/gl/renderer_backend.hpp index b95988589fbe..494bdae9e6b5 100644 --- a/include/mbgl/gl/renderer_backend.hpp +++ b/include/mbgl/gl/renderer_backend.hpp @@ -45,7 +45,7 @@ class RendererBackend : public gfx::RendererBackend { /// It sets the internal assumed state to the supplied values. void assumeFramebufferBinding(FramebufferID fbo); void assumeViewport(int32_t x, int32_t y, const Size&); - void assumeScissorTest(bool); + void assumeScissorTest(int32_t, int32_t, uint32_t, uint32_t); /// Returns true when assumed framebuffer binding hasn't changed from the implicit binding. bool implicitFramebufferBound(); @@ -55,7 +55,7 @@ class RendererBackend : public gfx::RendererBackend { /// match the supplied values. void setFramebufferBinding(FramebufferID fbo); void setViewport(int32_t x, int32_t y, const Size&); - void setScissorTest(bool); + void setScissorTest(int32_t, int32_t, uint32_t, uint32_t); }; } // namespace gl diff --git a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp index e354b7371f77..0736eec2df39 100644 --- a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp +++ b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp @@ -1326,6 +1326,14 @@ void NativeMapView::toggleTransform(JNIEnv&) { map->toggleTransform(); } +void NativeMapView::setFrustumOffset(JNIEnv& env, const jni::Object& padding) { + mbgl::EdgeInsets offset = {RectF::getTop(env, padding), + RectF::getLeft(env, padding), + RectF::getBottom(env, padding), + RectF::getRight(env, padding)}; + map->setFrustumOffset(offset); +} + // Static methods // void NativeMapView::registerNative(jni::JNIEnv& env) { @@ -1449,7 +1457,8 @@ void NativeMapView::registerNative(jni::JNIEnv& env) { METHOD(&NativeMapView::setTileLodZoomShift, "nativeSetTileLodZoomShift"), METHOD(&NativeMapView::getTileLodZoomShift, "nativeGetTileLodZoomShift"), METHOD(&NativeMapView::triggerRepaint, "nativeTriggerRepaint"), - METHOD(&NativeMapView::toggleTransform, "nativeToggleTransform")); + METHOD(&NativeMapView::toggleTransform, "nativeToggleTransform"), + METHOD(&NativeMapView::setFrustumOffset, "nativeSetFrustumOffset")); } void NativeMapView::onRegisterShaders(gfx::ShaderRegistry&) {}; diff --git a/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp b/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp index 75708b0d93f8..c1506dcadfa9 100644 --- a/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp +++ b/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp @@ -327,6 +327,8 @@ class NativeMapView : public MapObserver { void toggleTransform(JNIEnv&); + void setFrustumOffset(JNIEnv&, const jni::Object&); + // Shader compilation void onRegisterShaders(mbgl::gfx::ShaderRegistry&) override; void onPreCompileShader(mbgl::shaders::BuiltIn, mbgl::gfx::Backend::Type, const std::string&) override; diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java index abd89af72cfb..090aeb662ff4 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java @@ -121,6 +121,10 @@ public void toggleTransform() { nativeMapView.toggleTransform(); } + public void setFrustumOffset(@NonNull RectF offset) { + nativeMapView.setFrustumOffset(offset); + } + public void setSwapBehaviorFlush(boolean flush) { nativeMapView.setSwapBehaviorFlush(flush); } diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java index 72ed8d879344..28cbe40fdb56 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java @@ -272,6 +272,8 @@ List queryRenderedFeatures(@NonNull RectF coordinates, void toggleTransform(); + void setFrustumOffset(RectF offset); + void setSwapBehaviorFlush(boolean flush); // diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java index 9352560f68cb..45e855a42197 100755 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java @@ -1154,6 +1154,11 @@ public void toggleTransform() { nativeToggleTransform(); } + @Override + public void setFrustumOffset(RectF offset) { + nativeSetFrustumOffset(offset); + } + @Override public void setSwapBehaviorFlush(boolean flush) { mapRenderer.setSwapBehaviorFlush(flush); @@ -1754,6 +1759,9 @@ public long getNativePtr() { @Keep private native void nativeToggleTransform(); + @Keep + private native void nativeSetFrustumOffset(RectF offsset); + // // Snapshot // diff --git a/platform/default/src/mbgl/gl/headless_backend.cpp b/platform/default/src/mbgl/gl/headless_backend.cpp index 63674eee5c37..dfb1db84233f 100644 --- a/platform/default/src/mbgl/gl/headless_backend.cpp +++ b/platform/default/src/mbgl/gl/headless_backend.cpp @@ -24,7 +24,7 @@ class HeadlessRenderableResource final : public gl::RenderableResource { void bind() override { context.bindFramebuffer = framebuffer.framebuffer; - context.scissorTest = false; + context.scissorTest = {0, 0, 0, 0}; context.viewport = {0, 0, framebuffer.size}; } diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 12e4e68e604b..4e64379bdc78 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -1,7 +1,7 @@ -#include #include #include +#include #include #include #include @@ -461,7 +461,7 @@ void Context::resetState(gfx::DepthMode depthMode, gfx::ColorMode colorMode) { setStencilMode(gfx::StencilMode::disabled()); setColorMode(colorMode); setCullFaceMode(gfx::CullFaceMode::disabled()); - setScissorRect({0.f, 0.f, 0.f, 0.f}); + setScissorTest({0, 0, 0, 0}); } bool Context::emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr& buffer, @@ -494,7 +494,7 @@ void Context::unbindGlobalUniformBuffers(gfx::RenderPass&) const noexcept { void Context::setDirtyState() { MLN_TRACE_FUNC(); - // Note: does not set viewport/scissorTest/bindFramebuffer to dirty + // Note: does not set viewport/bindFramebuffer to dirty // since they are handled separately in the view object. stencilFunc.setDirty(); stencilMask.setDirty(); @@ -517,7 +517,7 @@ void Context::setDirtyState() { cullFace.setDirty(); cullFaceSide.setDirty(); cullFaceWinding.setDirty(); - scissorRect.setDirt(); + scissorTest.setDirty(); program.setDirty(); lineWidth.setDirty(); activeTextureUnit.setDirty(); @@ -642,8 +642,8 @@ void Context::setCullFaceMode(const gfx::CullFaceMode& mode) { cullFaceWinding = mode.winding; } -void Context::setScissorRect(const gfx::ScissorRect& rect) { - scissorRect = rect; +void Context::setScissorTest(const gfx::ScissorRect& rect) { + scissorTest = rect; } void Context::setDepthMode(const gfx::DepthMode& depth) { diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index 89c237f9d661..a94038df31d6 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -78,7 +78,7 @@ class Context final : public gfx::Context { void setStencilMode(const gfx::StencilMode&); void setColorMode(const gfx::ColorMode&); void setCullFaceMode(const gfx::CullFaceMode&); - void setScissorRect(const gfx::ScissorRect&); + void setScissorTest(const gfx::ScissorRect&); void draw(const gfx::DrawMode&, std::size_t indexOffset, std::size_t indexLength); @@ -206,7 +206,6 @@ class Context final : public gfx::Context { State cullFace; State cullFaceSide; State cullFaceWinding; - State scissorRect; public: std::unique_ptr createOffscreenTexture(Size, gfx::TextureChannelDataType) override; diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp index b1577a428d0a..27a88b44d958 100644 --- a/src/mbgl/gl/drawable_gl.cpp +++ b/src/mbgl/gl/drawable_gl.cpp @@ -59,7 +59,15 @@ void DrawableGL::draw(PaintParameters& parameters) const { context.setColorMode(getColorMode()); context.setCullFaceMode(getCullFaceMode()); - context.setScissorRect(getScissorRect()); + + EdgeInsets offset = parameters.state.getFrustumOffset(); + Size size = parameters.state.getSize(); + double pixelRatio = parameters.pixelRatio; + gfx::ScissorRect rect = {static_cast(offset.left() * pixelRatio), + static_cast(offset.top() * pixelRatio), + static_cast((size.width - (offset.left() + offset.right())) * pixelRatio), + static_cast((size.height - (offset.top() + offset.bottom())) * pixelRatio)}; + context.setScissorTest(rect); impl->uniformBuffers.bind(); bindTextures(); diff --git a/src/mbgl/gl/offscreen_texture.cpp b/src/mbgl/gl/offscreen_texture.cpp index e0da20dfce1b..90f71b4146bd 100644 --- a/src/mbgl/gl/offscreen_texture.cpp +++ b/src/mbgl/gl/offscreen_texture.cpp @@ -33,7 +33,7 @@ class OffscreenTextureResource final : public gl::RenderableResource { } context.activeTextureUnit = 0; - context.scissorTest = false; + context.scissorTest = {0, 0, 0, 0}; context.viewport = {.x = 0, .y = 0, .size = size}; } diff --git a/src/mbgl/gl/renderer_backend.cpp b/src/mbgl/gl/renderer_backend.cpp index 3a8a31b9d3c4..cb93e9d33a1a 100644 --- a/src/mbgl/gl/renderer_backend.cpp +++ b/src/mbgl/gl/renderer_backend.cpp @@ -53,10 +53,10 @@ void RendererBackend::assumeViewport(int32_t x, int32_t y, const Size& size) { assert(gl::value::Viewport::Get() == getContext().viewport.getCurrentValue()); } -void RendererBackend::assumeScissorTest(bool enabled) { +void RendererBackend::assumeScissorTest(int32_t x, int32_t y, uint32_t width, uint32_t height) { MLN_TRACE_FUNC(); - getContext().scissorTest.setCurrentValue(enabled); + getContext().scissorTest.setCurrentValue({x, y, width, height}); assert(gl::value::ScissorTest::Get() == getContext().scissorTest.getCurrentValue()); } @@ -82,10 +82,10 @@ void RendererBackend::setViewport(int32_t x, int32_t y, const Size& size) { assert(gl::value::Viewport::Get() == getContext().viewport.getCurrentValue()); } -void RendererBackend::setScissorTest(bool enabled) { +void RendererBackend::setScissorTest(int32_t x, int32_t y, uint32_t width, uint32_t height) { MLN_TRACE_FUNC(); - getContext().scissorTest = enabled; + getContext().scissorTest = {x, y, width, height}; assert(gl::value::ScissorTest::Get() == getContext().scissorTest.getCurrentValue()); } diff --git a/src/mbgl/gl/value.cpp b/src/mbgl/gl/value.cpp index fe0840c723cb..0aa200e00d0f 100644 --- a/src/mbgl/gl/value.cpp +++ b/src/mbgl/gl/value.cpp @@ -358,15 +358,17 @@ const constexpr ScissorTest::Type ScissorTest::Default; void ScissorTest::Set(const Type& value) { MLN_TRACE_ZONE(ScissorTest::Set); MLN_TRACE_FUNC_GL(); - MBGL_CHECK_ERROR(value ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST)); + bool enabled = value.x != 0 || value.y != 0 || value.width != 0 || value.height != 0; + MBGL_CHECK_ERROR(enabled ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST)); + MBGL_CHECK_ERROR(glScissor(value.x, value.y, value.width, value.height)); } ScissorTest::Type ScissorTest::Get() { MLN_TRACE_ZONE(ScissorTest::Get); MLN_TRACE_FUNC_GL(); - Type scissorTest; - MBGL_CHECK_ERROR(scissorTest = glIsEnabled(GL_SCISSOR_TEST)); - return scissorTest; + GLint scissor[4]; + MBGL_CHECK_ERROR(glGetIntegerv(GL_SCISSOR_BOX, scissor)); + return {scissor[0], scissor[1], static_cast(scissor[2]), static_cast(scissor[3])}; } const constexpr BindFramebuffer::Type BindFramebuffer::Default; diff --git a/src/mbgl/gl/value.hpp b/src/mbgl/gl/value.hpp index 5feb6f2834d9..22cdbdfc56c9 100644 --- a/src/mbgl/gl/value.hpp +++ b/src/mbgl/gl/value.hpp @@ -1,11 +1,11 @@ #pragma once -#include #include #include #include #include #include +#include #include #include #include @@ -190,8 +190,8 @@ struct Viewport { }; struct ScissorTest { - using Type = bool; - static const constexpr Type Default = false; + using Type = gfx::ScissorRect; + static const constexpr Type Default = {0, 0, 0, 0}; static void Set(const Type&); static Type Get(); }; diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp index 5322a1e24370..c7d75e5e7b92 100644 --- a/src/mbgl/map/transform_state.hpp +++ b/src/mbgl/map/transform_state.hpp @@ -85,6 +85,10 @@ struct TransformStateProperties { viewPortMode = val; return *this; } + TransformStateProperties withFrustumOffset(const std::optional& val) { + frustumOffset = val; + return *this; + } std::optional x; std::optional y; @@ -102,6 +106,7 @@ struct TransformStateProperties { std::optional constrain; std::optional northOrientation; std::optional viewPortMode; + std::optional frustumOffset; }; class TransformState { diff --git a/src/mbgl/shaders/vulkan/shader_program.cpp b/src/mbgl/shaders/vulkan/shader_program.cpp index 72763069bcfd..b4d000bbab5e 100644 --- a/src/mbgl/shaders/vulkan/shader_program.cpp +++ b/src/mbgl/shaders/vulkan/shader_program.cpp @@ -129,9 +129,7 @@ const vk::UniquePipeline& ShaderProgram::getPipeline(const PipelineInfo& pipelin const auto renderableExtent = pipelineInfo.viewExtent; const vk::Viewport viewportExtent(0.0f, 0.0f, renderableExtent.width, renderableExtent.height, 0.0f, 1.0f); - const vk::Rect2D scissorRect({pipeline.scissorRect.offset.x, pipeline.scissorRect.offset.y}, - {renderableExtent.width + pipelineInfo.scissorRect.extent.width, - renderableExtent.height + pipelineInfo.scissorRect.extent.height}); + const vk::Rect2D scissorRect({}, {renderableExtent.width, renderableExtent.height}); const auto viewportState = vk::PipelineViewportStateCreateInfo() .setViewportCount(1) diff --git a/src/mbgl/vulkan/context.cpp b/src/mbgl/vulkan/context.cpp index 5084262761c8..790586f2b7a1 100644 --- a/src/mbgl/vulkan/context.cpp +++ b/src/mbgl/vulkan/context.cpp @@ -547,6 +547,8 @@ bool Context::renderTileClippingMasks(gfx::RenderPass& renderPass, const auto& pipeline = shaderImpl.getPipeline(clipping.pipelineInfo); commandBuffer->bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.get()); + clipping.pipelineInfo.setScissorRect( + {0, 0, clipping.pipelineInfo.viewExtent.width, clipping.pipelineInfo.viewExtent.height}); clipping.pipelineInfo.setDynamicValues(backend, commandBuffer); const std::array vertexBuffers = {clipping.vertexBuffer->getVulkanBuffer()}; diff --git a/src/mbgl/vulkan/drawable.cpp b/src/mbgl/vulkan/drawable.cpp index 2b72aec8d7a3..505aca829b6d 100644 --- a/src/mbgl/vulkan/drawable.cpp +++ b/src/mbgl/vulkan/drawable.cpp @@ -301,6 +301,15 @@ void Drawable::draw(PaintParameters& parameters) const { // update pipeline info with per segment modifiers impl->pipelineInfo.setDrawMode(seg->getMode()); + EdgeInsets offset = parameters.state.getFrustumOffset(); + Size size = parameters.state.getSize(); + double pixelRatio = parameters.pixelRatio; + gfx::ScissorRect rect = {static_cast(offset.left() * pixelRatio), + static_cast(offset.top() * pixelRatio), + static_cast((size.width - (offset.left() + offset.right())) * pixelRatio), + static_cast((size.height - (offset.top() + offset.bottom())) * pixelRatio)}; + impl->pipelineInfo.setScissorRect(rect); + impl->pipelineInfo.setDynamicValues(context.getBackend(), commandBuffer); const auto& pipeline = shaderImpl.getPipeline(impl->pipelineInfo); diff --git a/src/mbgl/vulkan/pipeline.cpp b/src/mbgl/vulkan/pipeline.cpp index efc4f5974f78..88eb8ef3bc0f 100644 --- a/src/mbgl/vulkan/pipeline.cpp +++ b/src/mbgl/vulkan/pipeline.cpp @@ -7,8 +7,6 @@ namespace mbgl { namespace vulkan { -#define USE_DYNAMIC_VIEWPORT 0 - vk::Format PipelineInfo::vulkanFormat(const gfx::AttributeDataType& value) { switch (value) { case gfx::AttributeDataType::Byte: @@ -408,12 +406,7 @@ std::size_t PipelineInfo::hash() const { stencilFail, stencilDepthFail, wideLines, - scissorRect, VkRenderPass(renderPass), -#if !USE_DYNAMIC_VIEWPORT - viewExtent.width, - viewExtent.height, -#endif vertexInputHash); } @@ -432,13 +425,10 @@ void PipelineInfo::setDynamicValues(const RendererBackend& backend, const vk::Un buffer->setLineWidth(dynamicValues.lineWidth); } -#if USE_DYNAMIC_VIEWPORT const vk::Viewport viewport(0.0f, 0.0f, viewExtent.width, viewExtent.height, 0.0f, 1.0f); - const vk::Rect2D scissorRect({}, {viewExtent.width, viewExtent.height}); buffer->setViewport(0, viewport); buffer->setScissor(0, scissorRect); -#endif } std::vector PipelineInfo::getDynamicStates(const RendererBackend& backend) const { @@ -458,10 +448,8 @@ std::vector PipelineInfo::getDynamicStates(const RendererBacke dynamicStates.push_back(vk::DynamicState::eLineWidth); } -#if USE_DYNAMIC_VIEWPORT dynamicStates.push_back(vk::DynamicState::eViewport); dynamicStates.push_back(vk::DynamicState::eScissor); -#endif return dynamicStates; } diff --git a/test/util/offscreen_texture.test.cpp b/test/util/offscreen_texture.test.cpp index e4e0fe69df69..6cf2bfbf88b5 100644 --- a/test/util/offscreen_texture.test.cpp +++ b/test/util/offscreen_texture.test.cpp @@ -24,8 +24,7 @@ TEST(OffscreenTexture, EmptyRed) { gfx::BackendScope scope{backend}; // Scissor test shouldn't leak after gl::HeadlessBackend::bind(). - MBGL_CHECK_ERROR(glScissor(64, 64, 128, 128)); - static_cast(backend.getContext()).scissorTest.setCurrentValue(true); + static_cast(backend.getContext()).scissorTest.setCurrentValue({64, 64, 128, 128}); backend.getDefaultRenderable().getResource().bind(); @@ -146,8 +145,7 @@ void main() { gl::OffscreenTexture offscreenTexture(context, {128, 128}); // Scissor test shouldn't leak after OffscreenTexture::bind(). - MBGL_CHECK_ERROR(glScissor(32, 32, 64, 64)); - context.scissorTest.setCurrentValue(true); + context.scissorTest.setCurrentValue({32, 32, 64, 64}); offscreenTexture.getResource().bind(); From ce92aae7a49e76b08142400d376265ad03279380 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Sun, 27 Jul 2025 17:34:26 +0300 Subject: [PATCH 155/221] resolve issues with previous setup - only initialize the scissor rect once per frame - correctly remove scissor rect when using render targets --- include/mbgl/gfx/drawable.hpp | 6 ---- include/mbgl/vulkan/drawable.hpp | 1 - src/mbgl/gfx/drawable.cpp | 9 ------ src/mbgl/gl/drawable_gl.cpp | 9 +----- src/mbgl/mtl/drawable.cpp | 13 +++----- src/mbgl/renderer/paint_parameters.cpp | 6 ++-- src/mbgl/renderer/paint_parameters.hpp | 6 +++- src/mbgl/renderer/render_target.cpp | 6 ++++ src/mbgl/renderer/renderer_impl.cpp | 43 +++++++++++++++++--------- src/mbgl/vulkan/drawable.cpp | 14 +-------- 10 files changed, 50 insertions(+), 63 deletions(-) diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index 1160ef3e809c..78683a83101a 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -188,12 +188,6 @@ class Drawable { /// Set color mode virtual void setColorMode(const gfx::ColorMode&); - /// Get scissor rect - const gfx::ScissorRect& getScissorRect() const; - - /// Sset scissor rect - virtual void setScissorRect(const gfx::ScissorRect&); - /// Get the vertex attributes that override default values in the shader program const gfx::VertexAttributeArrayPtr& getVertexAttributes() const noexcept { return vertexAttributes; } diff --git a/include/mbgl/vulkan/drawable.hpp b/include/mbgl/vulkan/drawable.hpp index 7134fbc8e192..a4b73497a922 100644 --- a/include/mbgl/vulkan/drawable.hpp +++ b/include/mbgl/vulkan/drawable.hpp @@ -44,7 +44,6 @@ class Drawable : public gfx::Drawable { void setLineWidth(int32_t value) override; void setCullFaceMode(const gfx::CullFaceMode&) override; - void setScissorRect(const gfx::ScissorRect&) override; void updateVertexAttributes(gfx::VertexAttributeArrayPtr, std::size_t vertexCount, diff --git a/src/mbgl/gfx/drawable.cpp b/src/mbgl/gfx/drawable.cpp index ef851ddea386..def1e052580f 100644 --- a/src/mbgl/gfx/drawable.cpp +++ b/src/mbgl/gfx/drawable.cpp @@ -15,7 +15,6 @@ namespace gfx { struct Drawable::Impl { gfx::ColorMode colorMode = gfx::ColorMode::disabled(); gfx::CullFaceMode cullFaceMode = gfx::CullFaceMode::disabled(); - gfx::ScissorRect scissorRect = {0, 0, 0, 0}; std::shared_ptr bucket; PaintPropertyBindersBase* binders = nullptr; // owned by `bucket` @@ -48,14 +47,6 @@ void Drawable::setCullFaceMode(const gfx::CullFaceMode& value) { impl->cullFaceMode = value; } -const gfx::ScissorRect& Drawable::getScissorRect() const { - return impl->scissorRect; -} - -void Drawable::setScissorRect(const gfx::ScissorRect& value) { - impl->scissorRect = value; -} - void Drawable::setIndexData(std::vector indexes, std::vector segments) { setIndexData(std::make_shared(std::move(indexes)), std::move(segments)); } diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp index 27a88b44d958..e322b3310b8e 100644 --- a/src/mbgl/gl/drawable_gl.cpp +++ b/src/mbgl/gl/drawable_gl.cpp @@ -60,14 +60,7 @@ void DrawableGL::draw(PaintParameters& parameters) const { context.setColorMode(getColorMode()); context.setCullFaceMode(getCullFaceMode()); - EdgeInsets offset = parameters.state.getFrustumOffset(); - Size size = parameters.state.getSize(); - double pixelRatio = parameters.pixelRatio; - gfx::ScissorRect rect = {static_cast(offset.left() * pixelRatio), - static_cast(offset.top() * pixelRatio), - static_cast((size.width - (offset.left() + offset.right())) * pixelRatio), - static_cast((size.height - (offset.top() + offset.bottom())) * pixelRatio)}; - context.setScissorTest(rect); + context.setScissorTest(parameters.scissorRect); impl->uniformBuffers.bind(); bindTextures(); diff --git a/src/mbgl/mtl/drawable.cpp b/src/mbgl/mtl/drawable.cpp index 62ee3dbacc53..7959e3736d82 100644 --- a/src/mbgl/mtl/drawable.cpp +++ b/src/mbgl/mtl/drawable.cpp @@ -121,6 +121,10 @@ MTL::Winding mapWindingMode(const gfx::CullFaceWindingType mode) noexcept { } } +MTL::ScissorRect getMetalScissorRect(gfx::ScissorRect rect) noexcept { + return {static_cast(rect.x), static_cast(rect.y), rect.width, rect.height}; +} + } // namespace void Drawable::setColorMode(const gfx::ColorMode& value) { @@ -214,14 +218,7 @@ void Drawable::draw(PaintParameters& parameters) const { const auto& cullMode = getCullFaceMode(); renderPass.setCullMode(cullMode.enabled ? mapCullMode(cullMode.side) : MTL::CullModeNone); renderPass.setFrontFacingWinding(mapWindingMode(cullMode.winding)); - EdgeInsets offset = parameters.state.getFrustumOffset(); - Size size = parameters.state.getSize(); - double pixelRatio = parameters.pixelRatio; - MTL::ScissorRect rect = {static_cast(offset.left() * pixelRatio), - static_cast(offset.top() * pixelRatio), - static_cast((size.width - (offset.left() + offset.right())) * pixelRatio), - static_cast((size.height - (offset.top() + offset.bottom())) * pixelRatio)}; - renderPass.setScissorRect(rect); + renderPass.setScissorRect(getMetalScissorRect(parameters.scissorRect)); if (!impl->pipelineState) { impl->pipelineState = shaderMTL.getRenderPipelineState( diff --git a/src/mbgl/renderer/paint_parameters.cpp b/src/mbgl/renderer/paint_parameters.cpp index 1b80741d339c..baebbf101ce3 100644 --- a/src/mbgl/renderer/paint_parameters.cpp +++ b/src/mbgl/renderer/paint_parameters.cpp @@ -58,7 +58,8 @@ PaintParameters::PaintParameters(gfx::Context& context_, uint64_t frameCount_, double tileLodMinRadius_, double tileLodScale_, - double tileLodPitchThreshold_) + double tileLodPitchThreshold_, + const gfx::ScissorRect& scissorRect_) : context(context_), backend(backend_), encoder(context.createCommandEncoder()), @@ -76,7 +77,8 @@ PaintParameters::PaintParameters(gfx::Context& context_, frameCount(frameCount_), tileLodMinRadius(tileLodMinRadius_), tileLodScale(tileLodScale_), - tileLodPitchThreshold(tileLodPitchThreshold_) { + tileLodPitchThreshold(tileLodPitchThreshold_), + scissorRect(scissorRect_) { pixelsToGLUnits = {{2.0f / state.getSize().width, -2.0f / state.getSize().height}}; if (state.getViewportMode() == ViewportMode::FlippedY) { diff --git a/src/mbgl/renderer/paint_parameters.hpp b/src/mbgl/renderer/paint_parameters.hpp index 4f4be3b2c3c1..ff09f16b35a7 100644 --- a/src/mbgl/renderer/paint_parameters.hpp +++ b/src/mbgl/renderer/paint_parameters.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -60,7 +61,8 @@ class PaintParameters { uint64_t frameCount, double tileLodMinRadius, double tileLodScale, - double tileLodPitchThreshold); + double tileLodPitchThreshold, + const gfx::ScissorRect&); ~PaintParameters(); gfx::Context& context; @@ -137,6 +139,8 @@ class PaintParameters { double tileLodMinRadius; double tileLodScale; double tileLodPitchThreshold; + + gfx::ScissorRect scissorRect; }; } // namespace mbgl diff --git a/src/mbgl/renderer/render_target.cpp b/src/mbgl/renderer/render_target.cpp index ef75e44be119..dd2a5a49902d 100644 --- a/src/mbgl/renderer/render_target.cpp +++ b/src/mbgl/renderer/render_target.cpp @@ -71,6 +71,10 @@ void RenderTarget::render(RenderOrchestrator& orchestrator, const RenderTree& re .clearDepth = {}, .clearStencil = {}}); + const gfx::ScissorRect prevSicssorRect = parameters.scissorRect; + const auto& size = getTexture()->getSize(); + parameters.scissorRect = {0, 0, size.width, size.height}; + // Run layer tweakers to update any dynamic elements parameters.currentLayer = 0; visitLayerGroups([&](LayerGroupBase& layerGroup) { @@ -104,6 +108,8 @@ void RenderTarget::render(RenderOrchestrator& orchestrator, const RenderTree& re parameters.renderPass.reset(); parameters.encoder->present(*offscreenTexture); + + parameters.scissorRect = prevSicssorRect; } } // namespace mbgl diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 5091c9eddd6c..0b92386d9b89 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -181,21 +181,34 @@ void Renderer::Impl::render(const RenderTree& renderTree, const std::shared_ptr< observer->onWillStartRenderingFrame(); - PaintParameters parameters{context, - pixelRatio, - backend, - renderTreeParameters.light, - renderTreeParameters.mapMode, - renderTreeParameters.debugOptions, - renderTreeParameters.timePoint, - renderTreeParameters.transformParams, - *staticData, - renderTree.getLineAtlas(), - renderTree.getPatternAtlas(), - frameCount, - updateParameters->tileLodMinRadius, - updateParameters->tileLodScale, - updateParameters->tileLodPitchThreshold}; + const TransformState& state = renderTreeParameters.transformParams.state; + const Size& size = state.getSize(); + const EdgeInsets& frustumOffset = state.getFrustumOffset(); + const gfx::ScissorRect scissorRect = { + static_cast(frustumOffset.left() * pixelRatio), + static_cast(frustumOffset.top() * pixelRatio), + static_cast((size.width - (frustumOffset.left() + frustumOffset.right())) * pixelRatio), + static_cast((size.height - (frustumOffset.top() + frustumOffset.bottom())) * pixelRatio), + }; + + PaintParameters parameters{ + context, + pixelRatio, + backend, + renderTreeParameters.light, + renderTreeParameters.mapMode, + renderTreeParameters.debugOptions, + renderTreeParameters.timePoint, + renderTreeParameters.transformParams, + *staticData, + renderTree.getLineAtlas(), + renderTree.getPatternAtlas(), + frameCount, + updateParameters->tileLodMinRadius, + updateParameters->tileLodScale, + updateParameters->tileLodPitchThreshold, + scissorRect, + }; parameters.symbolFadeChange = renderTreeParameters.symbolFadeChange; parameters.opaquePassCutoff = renderTreeParameters.opaquePassCutOff; diff --git a/src/mbgl/vulkan/drawable.cpp b/src/mbgl/vulkan/drawable.cpp index 505aca829b6d..014302c2153d 100644 --- a/src/mbgl/vulkan/drawable.cpp +++ b/src/mbgl/vulkan/drawable.cpp @@ -101,11 +101,6 @@ void Drawable::setCullFaceMode(const gfx::CullFaceMode& mode) { impl->pipelineInfo.setCullMode(mode); } -void Drawable::setScissorRect(const gfx::ScissorRect& rect) { - gfx::Drawable::setScissorRect(rect); - impl->pipelineInfo.setScissorRect(rect); -} - void Drawable::updateVertexAttributes(gfx::VertexAttributeArrayPtr vertices, std::size_t vertexCount, gfx::DrawMode mode, @@ -301,14 +296,7 @@ void Drawable::draw(PaintParameters& parameters) const { // update pipeline info with per segment modifiers impl->pipelineInfo.setDrawMode(seg->getMode()); - EdgeInsets offset = parameters.state.getFrustumOffset(); - Size size = parameters.state.getSize(); - double pixelRatio = parameters.pixelRatio; - gfx::ScissorRect rect = {static_cast(offset.left() * pixelRatio), - static_cast(offset.top() * pixelRatio), - static_cast((size.width - (offset.left() + offset.right())) * pixelRatio), - static_cast((size.height - (offset.top() + offset.bottom())) * pixelRatio)}; - impl->pipelineInfo.setScissorRect(rect); + impl->pipelineInfo.setScissorRect(parameters.scissorRect); impl->pipelineInfo.setDynamicValues(context.getBackend(), commandBuffer); From a06d2432ac6eac092580d3ecbd3c43fe32c5b250 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Sun, 27 Jul 2025 19:18:28 +0300 Subject: [PATCH 156/221] make ios and android release --- platform/android/CHANGELOG.md | 7 +++++++ platform/android/VERSION | 2 +- platform/ios/VERSION | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index 2c9a4e0758a4..37d6306a3c69 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog MapLibre Native for Android +## 11.12.1 + +### ✨ Features and improvements + +- Concurrent Camera Animations +- Ability to set out of bounds region to improve rendering + ## 11.12.0 ### ✨ Features and improvements diff --git a/platform/android/VERSION b/platform/android/VERSION index a0980739e20b..4feb4470926b 100644 --- a/platform/android/VERSION +++ b/platform/android/VERSION @@ -1 +1 @@ -11.12.0 +11.12.1 diff --git a/platform/ios/VERSION b/platform/ios/VERSION index 89b71fa94204..2c2a1513040f 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.17.4 +6.17.5 From eae8078055fd7e20fbd040b02f63494b9d8d1146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Tue, 29 Jul 2025 11:44:45 -0400 Subject: [PATCH 157/221] Starting to add android implementation --- .../MapLibreAndroid/src/cpp/jni_native.cpp | 5 + .../src/cpp/native_map_view.cpp | 94 ++++++++++++++++++- .../src/cpp/native_map_view.hpp | 11 ++- .../src/cpp/plugin/plugin_file_source.cpp | 59 ++++++++++++ .../src/cpp/plugin/plugin_file_source.hpp | 38 ++++++++ .../maplibre/android/maps/MapLibreMap.java | 16 ++++ .../org/maplibre/android/maps/MapView.java | 11 +++ .../org/maplibre/android/maps/NativeMap.java | 3 + .../maplibre/android/maps/NativeMapView.java | 16 ++++ .../android/plugin/PluginFileSource.java | 28 ++++++ .../android/plugin/PluginProtocolHandler.kt | 18 ++++ .../plugin/PluginProtocolHandlerResource.kt | 33 +++++++ .../plugin/PluginProtocolHandlerResponse.kt | 7 ++ .../org/maplibre/android/plugin/TileData.kt | 15 +++ .../activity/maplayout/SimpleMapActivity.kt | 3 + .../activity/plugin/PluginProtocolExample.kt | 34 +++++++ platform/android/android.cmake | 2 + .../src/mbgl/storage/plugin_file_source.cpp | 2 +- 18 files changed, 391 insertions(+), 4 deletions(-) create mode 100644 platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.cpp create mode 100644 platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.hpp create mode 100644 platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginFileSource.java create mode 100644 platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandler.kt create mode 100644 platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResource.kt create mode 100644 platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResponse.kt create mode 100644 platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/TileData.kt create mode 100644 platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt diff --git a/platform/android/MapLibreAndroid/src/cpp/jni_native.cpp b/platform/android/MapLibreAndroid/src/cpp/jni_native.cpp index b0a29b677d3d..55071f20bf42 100644 --- a/platform/android/MapLibreAndroid/src/cpp/jni_native.cpp +++ b/platform/android/MapLibreAndroid/src/cpp/jni_native.cpp @@ -37,6 +37,7 @@ #include "native_map_options.hpp" #include "rendering_stats.hpp" #include "util/tile_server_options.hpp" +#include "plugin/plugin_file_source.hpp" #ifndef MBGL_MODULE_OFFLINE_DISABLE #include "offline/offline_manager.hpp" #include "offline/offline_region.hpp" @@ -107,6 +108,10 @@ void registerNatives(JavaVM* vm) { Polygon::registerNative(env); Polyline::registerNative(env); + // Plugins + PluginProtocolHandlerResource::registerNative(env); + PluginFileSource::registerNative(env); + // Map MapRenderer::registerNative(env); MapRendererRunnable::registerNative(env); diff --git a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp index e7a48ac3c31f..588dcd67a080 100644 --- a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp +++ b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp @@ -29,6 +29,8 @@ #include #include #include +#include +#include // Java -> C++ conversion #include "style/android_conversion.hpp" @@ -1320,6 +1322,94 @@ void NativeMapView::enableRenderingStatsView(JNIEnv&, jni::jboolean value) { map->enableRenderingStatsView(value); } +// Plugins +void NativeMapView::addPluginFileSource(JNIEnv &jniEnv, + const jni::Object& pluginFileSource) { + + // TODO: Unclear if any of these options are needed for plugins + mbgl::ResourceOptions resourceOptions; + + // TODO: Unclear if any of the properties on clientOptions need to be set + mbgl::ClientOptions clientOptions; + + android::UniqueEnv _env = android::AttachEnv(); + + // Set when the source is added to a map. + jni::Global> pluginPeer = jni::NewGlobal(*_env, pluginFileSource); + std::shared_ptr fileSourceContainer = std::make_shared(); + fileSourceContainer->_fileSource = std::move(pluginPeer); + _pluginFileSources.push_back(fileSourceContainer); + + std::shared_ptr pluginSource = std::make_shared(resourceOptions, clientOptions); + pluginSource->setOnRequestResourceFunction([fileSourceContainer](const mbgl::Resource &resource) -> mbgl::Response { + mbgl::Response tempResult; + + return tempResult; + }); + pluginSource->setOnCanRequestFunction([fileSourceContainer](const mbgl::Resource &resource) -> bool { + android::UniqueEnv env = android::AttachEnv(); + static auto& javaClass = jni::Class::Singleton(*env); + static auto canRequestResource = javaClass.GetMethod)>(*env, "canRequestResource"); + auto javaResource = PluginFileSource::createJavaResource(*env, resource); + auto tempResult = fileSourceContainer->_fileSource.Call(*env, canRequestResource, javaResource); + return tempResult; + + + /* + if (!renderingStats) { + renderingStats = jni::NewGlobal(*_env, RenderingStats::Create(*_env)); + } + + RenderingStats::Update(*_env, renderingStats, status.renderingStats); + + weakReference.Call(*_env, + onDidFinishRenderingFrame, + (jboolean)(status.mode != MapObserver::RenderMode::Partial), + renderingStats); + */ +/* + static auto resourceURLField = javaClass.GetField>(env, "resource"); + auto str = jni::Make(env, resource.url); // wrap the jstring + javaObject.Set(env, resourceURLField, str); + + fileSourceContainer->_fileSource.Set(env, ) +*/ + + + + + }); + auto fileSourceManager = mbgl::FileSourceManager::get(); + fileSourceManager->registerCustomFileSource(pluginSource); + + +/* + android::UniqueEnv _env = android::AttachEnv(); + static auto& javaClass = jni::Class::Singleton(*_env); + static auto onDidFinishRenderingFrame = javaClass.GetMethod)>( + *_env, "onDidFinishRenderingFrame"); + auto weakReference = javaPeer.get(*_env); + if (weakReference) { + if (!renderingStats) { + renderingStats = jni::NewGlobal(*_env, RenderingStats::Create(*_env)); + } + + RenderingStats::Update(*_env, renderingStats, status.renderingStats); + + weakReference.Call(*_env, + onDidFinishRenderingFrame, + (jboolean)(status.mode != MapObserver::RenderMode::Partial), + renderingStats); + } + + */ + + + +} + + + // Static methods // void NativeMapView::registerNative(jni::JNIEnv& env) { @@ -1442,7 +1532,9 @@ void NativeMapView::registerNative(jni::JNIEnv& env) { METHOD(&NativeMapView::getTileLodZoomShift, "nativeGetTileLodZoomShift"), METHOD(&NativeMapView::triggerRepaint, "nativeTriggerRepaint"), METHOD(&NativeMapView::isRenderingStatsViewEnabled, "nativeIsRenderingStatsViewEnabled"), - METHOD(&NativeMapView::enableRenderingStatsView, "nativeEnableRenderingStatsView")); + METHOD(&NativeMapView::enableRenderingStatsView, "nativeEnableRenderingStatsView"), + METHOD(&NativeMapView::addPluginFileSource, "nativeAddPluginFileSource")); + } void NativeMapView::onRegisterShaders(gfx::ShaderRegistry&) {}; diff --git a/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp b/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp index f9a0c7a3e136..2eec8461c909 100644 --- a/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp +++ b/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp @@ -25,7 +25,7 @@ #include "style/light.hpp" #include "native_map_options.hpp" #include "bitmap.hpp" - +#include "plugin/plugin_file_source.hpp" #include #include #include @@ -325,7 +325,11 @@ class NativeMapView : public MapObserver { jni::jboolean isRenderingStatsViewEnabled(JNIEnv&); void enableRenderingStatsView(JNIEnv&, jni::jboolean); - // Shader compilation + // Plugins + void addPluginFileSource(JNIEnv &, + const jni::Object& ); + + // Shader compilation void onRegisterShaders(mbgl::gfx::ShaderRegistry&) override; void onPreCompileShader(mbgl::shaders::BuiltIn, mbgl::gfx::Backend::Type, const std::string&) override; void onPostCompileShader(mbgl::shaders::BuiltIn, mbgl::gfx::Backend::Type, const std::string&) override; @@ -364,6 +368,9 @@ class NativeMapView : public MapObserver { // Ensure these are initialised last std::unique_ptr map; + + // List of plugin file source + std::vector> _pluginFileSources; }; } // namespace android diff --git a/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.cpp b/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.cpp new file mode 100644 index 000000000000..425142d21a18 --- /dev/null +++ b/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.cpp @@ -0,0 +1,59 @@ + +#include "plugin_file_source.hpp" + +using namespace mbgl::android; + +void PluginFileSource::registerNative(jni::JNIEnv& env) { + jni::Class::Singleton(env); +} + +jni::Global> PluginFileSource::createJavaResource(jni::JNIEnv& env, + const mbgl::Resource &resource) { + jni::Global> tempResult = jni::NewGlobal(env, PluginProtocolHandlerResource::Create(env)); + PluginProtocolHandlerResource::Update(env, tempResult, resource); + return tempResult; +} + +void PluginProtocolHandlerResource::registerNative(jni::JNIEnv& env) { + jni::Class::Singleton(env); +} + +jni::Local> PluginProtocolHandlerResource::Create(jni::JNIEnv& env) { + auto& javaClass = jni::Class::Singleton(env); + auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor); +} + +void PluginProtocolHandlerResource::Update(jni::JNIEnv& env, + jni::Object& javaObject, + const mbgl::Resource &resource) { + + static auto &javaClass = jni::Class::Singleton(env); + + static auto resourceKindField = javaClass.GetField(env, "kind"); + javaObject.Set(env, resourceKindField, static_cast(resource.kind)); + + static auto resourceURLField = javaClass.GetField(env, "resourceURL"); + auto str = jni::Make(env, resource.url); // wrap the jstring + javaObject.Set(env, resourceURLField, str); + +} + + + + + + + +/* +mbgl::PluginFileSource PluginFileSource::getFileSource(jni::JNIEnv&, + const jni::Object&) { + + ResourceOptions resourceOptions; + ClientOptions clientOptions; + mbgl::PluginFileSource tempResult(resourceOptions, clientOptions); + + return tempResult; + +} +*/ \ No newline at end of file diff --git a/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.hpp b/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.hpp new file mode 100644 index 000000000000..a98c0bcc9b45 --- /dev/null +++ b/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include + +namespace mbgl { + namespace android { + + class PluginProtocolHandlerResource { + public: + static constexpr auto Name() { return "org/maplibre/android/plugin/PluginProtocolHandlerResource"; }; + static void registerNative(jni::JNIEnv&); + + static jni::Local> Create(jni::JNIEnv&); + static void Update(jni::JNIEnv&, jni::Object&, const mbgl::Resource &); + }; + + class PluginFileSource { + public: + static constexpr auto Name() { return "org/maplibre/android/plugin/PluginFileSource"; }; + + //static mbgl::PluginFileSource getFileSource(jni::JNIEnv&, const jni::Object&); + + static jni::Global> createJavaResource(jni::JNIEnv& env, + const mbgl::Resource &resource); + + static void registerNative(jni::JNIEnv&); + }; + + class PluginFileSourceContainer { + public: + jni::Global> _fileSource; + }; + + } +} + + diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java index cdbecdfd660a..82ad755da11e 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java @@ -20,6 +20,7 @@ import org.maplibre.android.gestures.RotateGestureDetector; import org.maplibre.android.gestures.ShoveGestureDetector; import org.maplibre.android.gestures.StandardScaleGestureDetector; +import org.maplibre.android.plugin.PluginProtocolHandler; import org.maplibre.geojson.Feature; import org.maplibre.geojson.Geometry; import org.maplibre.android.MapStrictMode; @@ -2694,4 +2695,19 @@ private void notifyDeveloperAnimationListeners() { listener.onDeveloperAnimationStarted(); } } + + + + /** + * Adds a custom protocol handler to the map view + */ + ArrayList pluginProtocolHandlers = new ArrayList(); + public void addPluginProtocolHandler(PluginProtocolHandler protocolHandler) { + pluginProtocolHandlers.add(protocolHandler); + nativeMapView.addPluginProtocolHandler(protocolHandler); + + // nativeMapView.addPolygon() + } + + } diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapView.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapView.java index d0828b14272f..7673241ec043 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapView.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapView.java @@ -31,6 +31,7 @@ import org.maplibre.android.maps.renderer.MapRenderer; import org.maplibre.android.maps.widgets.CompassView; import org.maplibre.android.net.ConnectivityReceiver; +import org.maplibre.android.plugin.PluginProtocolHandler; import org.maplibre.android.storage.FileSource; import org.maplibre.android.utils.BitmapUtils; import org.maplibre.android.tile.TileOperation; @@ -1817,4 +1818,14 @@ private AttributionDialogManager getDialogManager() { public static void setMapStrictModeEnabled(boolean strictModeEnabled) { MapStrictMode.setStrictModeEnabled(strictModeEnabled); } + + /** + * Adds a custom protocol handler to the map view + */ + public void addPluginProtocolHandler(PluginProtocolHandler protocolHandler) { + if (maplibreMap != null) { + maplibreMap.addPluginProtocolHandler(protocolHandler); + } + } + } diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java index 585f7ed332b6..50dd727e6971 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java @@ -8,6 +8,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.maplibre.android.plugin.PluginProtocolHandler; import org.maplibre.geojson.Feature; import org.maplibre.geojson.Geometry; import org.maplibre.android.annotations.Marker; @@ -270,6 +271,8 @@ List queryRenderedFeatures(@NonNull RectF coordinates, void enableRenderingStatsView(boolean value); + void addPluginProtocolHandler(PluginProtocolHandler protocolHandler); + void setSwapBehaviorFlush(boolean flush); // diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java index 571193bd45d5..1e89a31b07cd 100755 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java @@ -13,6 +13,9 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.maplibre.android.plugin.PluginFileSource; +import org.maplibre.android.plugin.PluginProtocolHandler; +import org.maplibre.android.plugin.PluginProtocolHandlerResource; import org.maplibre.geojson.Feature; import org.maplibre.geojson.Geometry; import org.maplibre.android.LibraryLoader; @@ -38,6 +41,7 @@ import org.maplibre.android.style.sources.Source; import org.maplibre.android.utils.BitmapUtils; import org.maplibre.android.tile.TileOperation; +import org.maplibre.android.plugin.PluginFileSource; import java.util.ArrayList; import java.util.Arrays; @@ -1149,6 +1153,13 @@ public void enableRenderingStatsView(boolean value) { nativeEnableRenderingStatsView(value); } + @Override + public void addPluginProtocolHandler(PluginProtocolHandler protocolHandler) { + PluginFileSource pluginFileSource = new PluginFileSource(); + pluginFileSource.protocolHandler = protocolHandler; + nativeAddPluginFileSource(pluginFileSource); + } + @Override public void setSwapBehaviorFlush(boolean flush) { mapRenderer.setSwapBehaviorFlush(flush); @@ -1746,6 +1757,11 @@ public long getNativePtr() { @Keep private native void nativeEnableRenderingStatsView(boolean enabled); + @Keep + private native void nativeAddPluginFileSource(PluginFileSource fileSource); + + + // // Snapshot // diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginFileSource.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginFileSource.java new file mode 100644 index 000000000000..5f19cad98fba --- /dev/null +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginFileSource.java @@ -0,0 +1,28 @@ +package org.maplibre.android.plugin; + +public class PluginFileSource { + + public PluginProtocolHandler protocolHandler; + + public boolean canRequestResource(PluginProtocolHandlerResource resource) { + + if (protocolHandler.canRequestResource(resource)) { + return true; + } + return false; + + } +/* + public boolean canRequestResource() { + if (protocolHandler.canRequestResource(resource)) { + return true; + } + return false; + } +*/ + public PluginProtocolHandlerResponse requestResource(PluginProtocolHandlerResource resource) { + PluginProtocolHandlerResponse response = protocolHandler.requestResource(resource); + return response; + } + +} diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandler.kt b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandler.kt new file mode 100644 index 000000000000..2b84385a9d2a --- /dev/null +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandler.kt @@ -0,0 +1,18 @@ +package org.maplibre.android.plugin + +import android.icu.text.Normalizer + +public open class PluginProtocolHandler { + + open fun canRequestResource(resource: PluginProtocolHandlerResource?): Boolean { + // Base class does nothing + return false; + } + + + open fun requestResource(resource: PluginProtocolHandlerResource?): PluginProtocolHandlerResponse? { + // Base class does nothing + return null; + } + +} diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResource.kt b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResource.kt new file mode 100644 index 000000000000..f72b4628889f --- /dev/null +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResource.kt @@ -0,0 +1,33 @@ +package org.maplibre.android.plugin + +class PluginProtocolHandlerResource { + + enum class PluginProtocolHandlerResourceKind { + Unknown, + Style, + Source, + Tile, + Glyphs, + SpriteImage, + SpriteJSON, + Image + }; + + enum class PluginProtocolHandlerResourceLoadingMethod { + Unknown, + CacheOnly, + NetworkOnly, + All + }; + + var resourceURL: String = "Test"; + + var kind: Int = 0; + + var resourceKind: PluginProtocolHandlerResourceKind = PluginProtocolHandlerResourceKind.Unknown; + + var loadingMethod: PluginProtocolHandlerResourceLoadingMethod = PluginProtocolHandlerResourceLoadingMethod.Unknown; + + var tileData: TileData? = null; + +} diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResponse.kt b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResponse.kt new file mode 100644 index 000000000000..eb36275ec31d --- /dev/null +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResponse.kt @@ -0,0 +1,7 @@ +package org.maplibre.android.plugin + +class PluginProtocolHandlerResponse { + + var data: ByteArray? = null; + +} \ No newline at end of file diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/TileData.kt b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/TileData.kt new file mode 100644 index 000000000000..9ecdb35b5460 --- /dev/null +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/TileData.kt @@ -0,0 +1,15 @@ +package org.maplibre.android.plugin + +class TileData { + + var tileURLTemplate: String? = null; + + var tilePixelRatio: Int = 0; + + var tileX: Int = 0; + + var tileY: Int = 0; + + var tileZoom: Int = 0; + +} \ No newline at end of file diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/SimpleMapActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/SimpleMapActivity.kt index 8afad9bf94be..1717ee451d08 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/SimpleMapActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/maplayout/SimpleMapActivity.kt @@ -6,6 +6,7 @@ import androidx.activity.OnBackPressedCallback import androidx.appcompat.app.AppCompatActivity import org.maplibre.android.maps.* import org.maplibre.android.testapp.R +import org.maplibre.android.testapp.activity.plugin.PluginProtocolExample import org.maplibre.android.testapp.utils.ApiKeyUtils import org.maplibre.android.testapp.utils.NavUtils @@ -27,6 +28,8 @@ class SimpleMapActivity : AppCompatActivity() { mapView = findViewById(R.id.mapView) mapView.onCreate(savedInstanceState) mapView.getMapAsync { + val protocolExample = PluginProtocolExample(); + mapView.addPluginProtocolHandler(protocolExample); val key = ApiKeyUtils.getApiKey(applicationContext) if (key == null || key == "YOUR_API_KEY_GOES_HERE") { it.setStyle( diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt new file mode 100644 index 000000000000..fdddaecf7668 --- /dev/null +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt @@ -0,0 +1,34 @@ +package org.maplibre.android.testapp.activity.plugin + +import org.maplibre.android.plugin.PluginProtocolHandler +import org.maplibre.android.plugin.PluginProtocolHandlerResource +import org.maplibre.android.plugin.PluginProtocolHandlerResponse + +class PluginProtocolExample : PluginProtocolHandler() { + + override fun canRequestResource(resource: PluginProtocolHandlerResource?): Boolean { + + if (resource == null) { + return false; + } + + if (resource.resourceURL != null) { + if (resource.resourceURL!!.contains("pluginProtocol")) { + return true; + } + } + + if (resource.resourceKind == PluginProtocolHandlerResource.PluginProtocolHandlerResourceKind.Unknown) { + return true; + } + + return false; + } + + + override fun requestResource(resource: PluginProtocolHandlerResource?): PluginProtocolHandlerResponse? { + // Return some data here + return null; + } + +} \ No newline at end of file diff --git a/platform/android/android.cmake b/platform/android/android.cmake index cb9e28e5a5de..72fc11d7276f 100644 --- a/platform/android/android.cmake +++ b/platform/android/android.cmake @@ -45,6 +45,7 @@ target_sources( ${PROJECT_SOURCE_DIR}/platform/android/src/string_util.cpp ${PROJECT_SOURCE_DIR}/platform/android/src/thread.cpp ${PROJECT_SOURCE_DIR}/platform/android/src/timer.cpp + ${PROJECT_SOURCE_DIR}/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.cpp ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/gfx/headless_backend.cpp ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/gfx/headless_frontend.cpp ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/map/map_snapshotter.cpp @@ -61,6 +62,7 @@ target_sources( ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/storage/offline_database.cpp ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/storage/offline_download.cpp ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/storage/online_file_source.cpp + ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/storage/plugin_file_source.cpp ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/storage/$,pmtiles_file_source.cpp,pmtiles_file_source_stub.cpp> ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/storage/sqlite3.cpp ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/text/bidi.cpp diff --git a/platform/default/src/mbgl/storage/plugin_file_source.cpp b/platform/default/src/mbgl/storage/plugin_file_source.cpp index 0e0fa0b79b1c..120308a743da 100644 --- a/platform/default/src/mbgl/storage/plugin_file_source.cpp +++ b/platform/default/src/mbgl/storage/plugin_file_source.cpp @@ -15,7 +15,7 @@ namespace mbgl { -void PluginFileSource::setProtocolPrefix(const std::string& protocolPrefix) {} +void PluginFileSource::setProtocolPrefix([[maybe_unused]] const std::string& protocolPrefix) {} class PluginFileSource::Impl { public: From 7d27873278e4ff8bf8d6e823e4b85677f731c794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Tue, 29 Jul 2025 17:16:20 -0400 Subject: [PATCH 158/221] Passing along the byte buffer from the plugin to the native response --- .../MapLibreAndroid/src/cpp/jni_native.cpp | 1 + .../src/cpp/native_map_view.cpp | 13 ++++- .../src/cpp/plugin/plugin_file_source.cpp | 51 ++++++++++++++----- .../src/cpp/plugin/plugin_file_source.hpp | 12 +++++ .../android/plugin/PluginFileSource.java | 14 +---- .../plugin/PluginProtocolHandlerResponse.kt | 14 ++++- .../activity/plugin/PluginProtocolExample.kt | 4 +- 7 files changed, 79 insertions(+), 30 deletions(-) diff --git a/platform/android/MapLibreAndroid/src/cpp/jni_native.cpp b/platform/android/MapLibreAndroid/src/cpp/jni_native.cpp index 55071f20bf42..24ab77e1b224 100644 --- a/platform/android/MapLibreAndroid/src/cpp/jni_native.cpp +++ b/platform/android/MapLibreAndroid/src/cpp/jni_native.cpp @@ -110,6 +110,7 @@ void registerNatives(JavaVM* vm) { // Plugins PluginProtocolHandlerResource::registerNative(env); + PluginProtocolHandlerResponse::registerNative(env); PluginFileSource::registerNative(env); // Map diff --git a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp index 588dcd67a080..8fa8331b6839 100644 --- a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp +++ b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp @@ -1342,9 +1342,18 @@ void NativeMapView::addPluginFileSource(JNIEnv &jniEnv, std::shared_ptr pluginSource = std::make_shared(resourceOptions, clientOptions); pluginSource->setOnRequestResourceFunction([fileSourceContainer](const mbgl::Resource &resource) -> mbgl::Response { - mbgl::Response tempResult; + mbgl::Response tempResponse; - return tempResult; + android::UniqueEnv env = android::AttachEnv(); + static auto& javaClass = jni::Class::Singleton(*env); + static auto requestResource = javaClass.GetMethod(jni::Object)>(*env, "requestResource"); + auto javaResource = PluginFileSource::createJavaResource(*env, resource); + auto tempResult = fileSourceContainer->_fileSource.Call(*env, requestResource, javaResource); + PluginProtocolHandlerResponse::Update(*env, + tempResult, + tempResponse); + + return tempResponse; }); pluginSource->setOnCanRequestFunction([fileSourceContainer](const mbgl::Resource &resource) -> bool { android::UniqueEnv env = android::AttachEnv(); diff --git a/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.cpp b/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.cpp index 425142d21a18..a7153e87c11d 100644 --- a/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.cpp +++ b/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.cpp @@ -3,6 +3,25 @@ using namespace mbgl::android; +// Putting these here (should probably move out to a more dedicated JNI place within +// the native repo at some point, but this means we don't have to update +// the jni.hpp dependency +namespace jni { + + struct ByteBufferTag + { + static constexpr auto Name() { return "java/nio/ByteBuffer"; } + }; + + template <> + struct TagTraits< ByteBufferTag > + { + using SuperType = Object; + using UntaggedType = jobject; + }; + +} + void PluginFileSource::registerNative(jni::JNIEnv& env) { jni::Class::Singleton(env); } @@ -40,20 +59,24 @@ void PluginProtocolHandlerResource::Update(jni::JNIEnv& env, } +void PluginProtocolHandlerResponse::registerNative(jni::JNIEnv& env) { + jni::Class::Singleton(env); +} +jni::Local> PluginProtocolHandlerResponse::Create(jni::JNIEnv&env) { + auto& javaClass = jni::Class::Singleton(env); + auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor); +} - - - -/* -mbgl::PluginFileSource PluginFileSource::getFileSource(jni::JNIEnv&, - const jni::Object&) { - - ResourceOptions resourceOptions; - ClientOptions clientOptions; - mbgl::PluginFileSource tempResult(resourceOptions, clientOptions); - - return tempResult; - +void PluginProtocolHandlerResponse::Update(jni::JNIEnv & env, + [[maybe_unused]] jni::Object& javaObject, + [[maybe_unused]] mbgl::Response &response) { + static auto &javaClass = jni::Class::Singleton(env); + static auto dataField = javaClass.GetField>(env, "data"); + auto objectValue = javaObject.Get(env, dataField); + auto objectRef = jobject(objectValue.get()); + void* bufPtr = env.GetDirectBufferAddress(objectRef); + jsize length = env.GetDirectBufferCapacity(objectRef); + response.data = std::make_shared((const char*)bufPtr, length); } -*/ \ No newline at end of file diff --git a/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.hpp b/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.hpp index a98c0bcc9b45..6e829004a513 100644 --- a/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.hpp +++ b/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.hpp @@ -15,6 +15,18 @@ namespace mbgl { static void Update(jni::JNIEnv&, jni::Object&, const mbgl::Resource &); }; + class PluginProtocolHandlerResponse { + public: + static constexpr auto Name() { return "org/maplibre/android/plugin/PluginProtocolHandlerResponse"; }; + static void registerNative(jni::JNIEnv&); + + static jni::Local> Create(jni::JNIEnv&); + static void Update(jni::JNIEnv&, + jni::Object&, + mbgl::Response &); + + }; + class PluginFileSource { public: static constexpr auto Name() { return "org/maplibre/android/plugin/PluginFileSource"; }; diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginFileSource.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginFileSource.java index 5f19cad98fba..e99ca05a08fb 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginFileSource.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginFileSource.java @@ -6,20 +6,10 @@ public class PluginFileSource { public boolean canRequestResource(PluginProtocolHandlerResource resource) { - if (protocolHandler.canRequestResource(resource)) { - return true; - } - return false; + return protocolHandler.canRequestResource(resource); } -/* - public boolean canRequestResource() { - if (protocolHandler.canRequestResource(resource)) { - return true; - } - return false; - } -*/ + public PluginProtocolHandlerResponse requestResource(PluginProtocolHandlerResource resource) { PluginProtocolHandlerResponse response = protocolHandler.requestResource(resource); return response; diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResponse.kt b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResponse.kt index eb36275ec31d..d9fd3a242739 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResponse.kt +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResponse.kt @@ -1,7 +1,19 @@ package org.maplibre.android.plugin +import java.nio.ByteBuffer + class PluginProtocolHandlerResponse { - var data: ByteArray? = null; + fun generateBuffer() { + data = ByteBuffer.allocateDirect(1000); + + // Example: write bytes + for (i in 0..<255) { + data!!.put(i.toByte()) + } + + } + + var data: ByteBuffer? = null; } \ No newline at end of file diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt index fdddaecf7668..7b1970a886a6 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt @@ -28,7 +28,9 @@ class PluginProtocolExample : PluginProtocolHandler() { override fun requestResource(resource: PluginProtocolHandlerResource?): PluginProtocolHandlerResponse? { // Return some data here - return null; + var tempResult = PluginProtocolHandlerResponse(); + tempResult.generateBuffer(); + return tempResult; } } \ No newline at end of file From 73d92782e8a2f0ecfb6fd08de5feaca14ecd754e Mon Sep 17 00:00:00 2001 From: AtlasProgramming Date: Tue, 29 Jul 2025 17:27:52 -0400 Subject: [PATCH 159/221] Update src/mbgl/plugin/feature_collection.hpp Co-authored-by: Tim Sylvester --- src/mbgl/plugin/feature_collection.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mbgl/plugin/feature_collection.hpp b/src/mbgl/plugin/feature_collection.hpp index 3ea9b5c70b5a..6520105f3294 100644 --- a/src/mbgl/plugin/feature_collection.hpp +++ b/src/mbgl/plugin/feature_collection.hpp @@ -22,7 +22,7 @@ class FeatureCoordinate { double _tileY = 0; // Tile coord }; -// This is a list of coordinates. Broken out into it's own class because +// This is a list of coordinates. Broken out into its own class because // a raw bucket feature can have an array of these class FeatureCoordinateCollection { public: From 386b898f97c315c8f2e0a70d30cef81d4fe36873 Mon Sep 17 00:00:00 2001 From: AtlasProgramming Date: Tue, 29 Jul 2025 17:28:06 -0400 Subject: [PATCH 160/221] Update src/mbgl/plugin/plugin_layer_render.cpp Co-authored-by: Tim Sylvester --- src/mbgl/plugin/plugin_layer_render.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mbgl/plugin/plugin_layer_render.cpp b/src/mbgl/plugin/plugin_layer_render.cpp index 8b57e8d071eb..27c4d3b6e806 100644 --- a/src/mbgl/plugin/plugin_layer_render.cpp +++ b/src/mbgl/plugin/plugin_layer_render.cpp @@ -130,7 +130,7 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis continue; } - // See if we already have this tile'a feature collection + // See if we already have this tile's feature collection if (_featureCollectionByTile.contains(tileID)) { continue; } From 34d9abf2d4929bebd2f74a11d3d9e49179a9640b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Tue, 29 Jul 2025 17:38:34 -0400 Subject: [PATCH 161/221] Updafed with feedback --- platform/ios/src/MLNMapView.mm | 2 +- src/mbgl/plugin/feature_collection_bucket.cpp | 13 +++++-------- src/mbgl/plugin/feature_collection_bucket.hpp | 1 - src/mbgl/plugin/plugin_layer_factory.cpp | 4 ++-- src/mbgl/plugin/plugin_layer_factory.hpp | 2 +- src/mbgl/plugin/plugin_layer_render.cpp | 3 --- 6 files changed, 9 insertions(+), 16 deletions(-) diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 4c2aa9d24851..001279737495 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -7745,7 +7745,7 @@ -(void)addPluginLayerType:(Class)pluginLayerClass { __weak MLNMapView *weakMapView = self; Class layerClass = pluginLayerClass; - factory->_supportsFeatureCollectionBuckets = capabilities.supportsReadingTileFeatures; + factory->supportsFeatureCollectionBuckets = capabilities.supportsReadingTileFeatures; factory->setOnLayerCreatedEvent([layerClass, weakMapView, pluginLayerClass](mbgl::style::PluginLayer *pluginLayer) { //NSLog(@"Creating Plugin Layer: %@", layerClass); diff --git a/src/mbgl/plugin/feature_collection_bucket.cpp b/src/mbgl/plugin/feature_collection_bucket.cpp index 05cdf268c4b6..fb2c9f9e6625 100644 --- a/src/mbgl/plugin/feature_collection_bucket.cpp +++ b/src/mbgl/plugin/feature_collection_bucket.cpp @@ -38,18 +38,15 @@ void geometryToLatLon(const GeometryCoordinate& coord, } std::string toString(FeatureIdentifier& v) { - std::string tempResult = ""; auto ti = v.which(); - if (ti == 0) { - return tempResult; - } else if (ti == 1) { - tempResult = std::to_string(v.get()); + if (ti == 1) { + return std::to_string(v.get()); } else if (ti == 2) { - tempResult = std::to_string(v.get()); + return std::to_string(v.get()); } else if (ti == 3) { - tempResult = v.get(); + return v.get(); } - return tempResult; + return ""; } void FeatureCollectionBucket::addFeature(const GeometryTileFeature& tileFeature, diff --git a/src/mbgl/plugin/feature_collection_bucket.hpp b/src/mbgl/plugin/feature_collection_bucket.hpp index fc5499488822..90ae88bb738f 100644 --- a/src/mbgl/plugin/feature_collection_bucket.hpp +++ b/src/mbgl/plugin/feature_collection_bucket.hpp @@ -19,7 +19,6 @@ class RenderFillLayer; class FeatureCollectionBucket final : public Bucket { public: ~FeatureCollectionBucket() override; - // using PossiblyEvaluatedLayoutProperties = style::FillLayoutProperties::PossiblyEvaluated; FeatureCollectionBucket(const BucketParameters&, const std::vector>&); diff --git a/src/mbgl/plugin/plugin_layer_factory.cpp b/src/mbgl/plugin/plugin_layer_factory.cpp index a30db5105ee8..8fc2d8b1027f 100644 --- a/src/mbgl/plugin/plugin_layer_factory.cpp +++ b/src/mbgl/plugin/plugin_layer_factory.cpp @@ -151,7 +151,7 @@ std::unique_ptr PluginLayerFactory::createLayer(const std::string& } std::string sourceStr = "pluginLayerNoSource"; - if (_supportsFeatureCollectionBuckets) { + if (supportsFeatureCollectionBuckets) { auto source = getSource(value); if (source.has_value()) { sourceStr = source.value(); @@ -179,7 +179,7 @@ std::unique_ptr PluginLayerFactory::createLayer(const std::string& std::unique_ptr PluginLayerFactory::createBucket( [[maybe_unused]] const BucketParameters& parameters, [[maybe_unused]] const std::vector>& layers) noexcept { - if (_supportsFeatureCollectionBuckets) { + if (supportsFeatureCollectionBuckets) { return std::make_unique(parameters, layers); } return nullptr; diff --git a/src/mbgl/plugin/plugin_layer_factory.hpp b/src/mbgl/plugin/plugin_layer_factory.hpp index e2d3aa4e392b..a0acc5936afd 100644 --- a/src/mbgl/plugin/plugin_layer_factory.hpp +++ b/src/mbgl/plugin/plugin_layer_factory.hpp @@ -24,7 +24,7 @@ class PluginLayerFactory : public LayerFactory { mbgl::style::LayerTypeInfo::TileKind tileKind); // Set to false, but if the caller wants to support on features loaded, then set this to true - bool _supportsFeatureCollectionBuckets = false; + bool supportsFeatureCollectionBuckets = false; using OnLayerCreatedEvent = std::function; void setOnLayerCreatedEvent(OnLayerCreatedEvent onLayerCreated) { _onLayerCreated = onLayerCreated; } diff --git a/src/mbgl/plugin/plugin_layer_render.cpp b/src/mbgl/plugin/plugin_layer_render.cpp index 8b57e8d071eb..cd858a688a48 100644 --- a/src/mbgl/plugin/plugin_layer_render.cpp +++ b/src/mbgl/plugin/plugin_layer_render.cpp @@ -115,9 +115,6 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); - if (!hasRenderTile(tileID)) { - } - const auto* optRenderData = getRenderDataForPass(tile, drawPass); if (!optRenderData || !optRenderData->bucket || !optRenderData->bucket->hasData()) { removeTile(drawPass, tileID); From 9c3ef30aa787a2eaa01b776b5a3ccaf423d19a6b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 29 Jul 2025 21:42:24 +0000 Subject: [PATCH 162/221] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../src/cpp/native_map_view.cpp | 83 ++++++++----------- .../src/cpp/native_map_view.hpp | 5 +- .../src/cpp/plugin/plugin_file_source.cpp | 46 +++++----- .../src/cpp/plugin/plugin_file_source.hpp | 63 +++++++------- .../plugin/PluginProtocolHandlerResponse.kt | 2 +- .../org/maplibre/android/plugin/TileData.kt | 2 +- .../activity/plugin/PluginProtocolExample.kt | 2 +- 7 files changed, 91 insertions(+), 112 deletions(-) diff --git a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp index 8fa8331b6839..910ef7d4fea4 100644 --- a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp +++ b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp @@ -1323,9 +1323,7 @@ void NativeMapView::enableRenderingStatsView(JNIEnv&, jni::jboolean value) { } // Plugins -void NativeMapView::addPluginFileSource(JNIEnv &jniEnv, - const jni::Object& pluginFileSource) { - +void NativeMapView::addPluginFileSource(JNIEnv& jniEnv, const jni::Object& pluginFileSource) { // TODO: Unclear if any of these options are needed for plugins mbgl::ResourceOptions resourceOptions; @@ -1340,30 +1338,31 @@ void NativeMapView::addPluginFileSource(JNIEnv &jniEnv, fileSourceContainer->_fileSource = std::move(pluginPeer); _pluginFileSources.push_back(fileSourceContainer); - std::shared_ptr pluginSource = std::make_shared(resourceOptions, clientOptions); - pluginSource->setOnRequestResourceFunction([fileSourceContainer](const mbgl::Resource &resource) -> mbgl::Response { + std::shared_ptr pluginSource = std::make_shared(resourceOptions, + clientOptions); + pluginSource->setOnRequestResourceFunction([fileSourceContainer](const mbgl::Resource& resource) -> mbgl::Response { mbgl::Response tempResponse; android::UniqueEnv env = android::AttachEnv(); static auto& javaClass = jni::Class::Singleton(*env); - static auto requestResource = javaClass.GetMethod(jni::Object)>(*env, "requestResource"); + static auto requestResource = + javaClass.GetMethod(jni::Object)>( + *env, "requestResource"); auto javaResource = PluginFileSource::createJavaResource(*env, resource); auto tempResult = fileSourceContainer->_fileSource.Call(*env, requestResource, javaResource); - PluginProtocolHandlerResponse::Update(*env, - tempResult, - tempResponse); + PluginProtocolHandlerResponse::Update(*env, tempResult, tempResponse); return tempResponse; }); - pluginSource->setOnCanRequestFunction([fileSourceContainer](const mbgl::Resource &resource) -> bool { + pluginSource->setOnCanRequestFunction([fileSourceContainer](const mbgl::Resource& resource) -> bool { android::UniqueEnv env = android::AttachEnv(); static auto& javaClass = jni::Class::Singleton(*env); - static auto canRequestResource = javaClass.GetMethod)>(*env, "canRequestResource"); + static auto canRequestResource = javaClass.GetMethod)>( + *env, "canRequestResource"); auto javaResource = PluginFileSource::createJavaResource(*env, resource); auto tempResult = fileSourceContainer->_fileSource.Call(*env, canRequestResource, javaResource); return tempResult; - /* if (!renderingStats) { renderingStats = jni::NewGlobal(*_env, RenderingStats::Create(*_env)); @@ -1376,49 +1375,40 @@ void NativeMapView::addPluginFileSource(JNIEnv &jniEnv, (jboolean)(status.mode != MapObserver::RenderMode::Partial), renderingStats); */ -/* - static auto resourceURLField = javaClass.GetField>(env, "resource"); - auto str = jni::Make(env, resource.url); // wrap the jstring - javaObject.Set(env, resourceURLField, str); - - fileSourceContainer->_fileSource.Set(env, ) -*/ - - - + /* + static auto resourceURLField = javaClass.GetField>(env, + "resource"); auto str = jni::Make(env, resource.url); // wrap the jstring javaObject.Set(env, + resourceURLField, str); + fileSourceContainer->_fileSource.Set(env, ) + */ }); auto fileSourceManager = mbgl::FileSourceManager::get(); fileSourceManager->registerCustomFileSource(pluginSource); - -/* - android::UniqueEnv _env = android::AttachEnv(); - static auto& javaClass = jni::Class::Singleton(*_env); - static auto onDidFinishRenderingFrame = javaClass.GetMethod)>( - *_env, "onDidFinishRenderingFrame"); - auto weakReference = javaPeer.get(*_env); - if (weakReference) { - if (!renderingStats) { - renderingStats = jni::NewGlobal(*_env, RenderingStats::Create(*_env)); + /* + android::UniqueEnv _env = android::AttachEnv(); + static auto& javaClass = jni::Class::Singleton(*_env); + static auto onDidFinishRenderingFrame = javaClass.GetMethod)>( + *_env, "onDidFinishRenderingFrame"); + auto weakReference = javaPeer.get(*_env); + if (weakReference) { + if (!renderingStats) { + renderingStats = jni::NewGlobal(*_env, RenderingStats::Create(*_env)); + } + + RenderingStats::Update(*_env, renderingStats, status.renderingStats); + + weakReference.Call(*_env, + onDidFinishRenderingFrame, + (jboolean)(status.mode != MapObserver::RenderMode::Partial), + renderingStats); } - RenderingStats::Update(*_env, renderingStats, status.renderingStats); - - weakReference.Call(*_env, - onDidFinishRenderingFrame, - (jboolean)(status.mode != MapObserver::RenderMode::Partial), - renderingStats); - } - - */ - - - + */ } - - // Static methods // void NativeMapView::registerNative(jni::JNIEnv& env) { @@ -1543,7 +1533,6 @@ void NativeMapView::registerNative(jni::JNIEnv& env) { METHOD(&NativeMapView::isRenderingStatsViewEnabled, "nativeIsRenderingStatsViewEnabled"), METHOD(&NativeMapView::enableRenderingStatsView, "nativeEnableRenderingStatsView"), METHOD(&NativeMapView::addPluginFileSource, "nativeAddPluginFileSource")); - } void NativeMapView::onRegisterShaders(gfx::ShaderRegistry&) {}; diff --git a/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp b/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp index 2eec8461c909..ab58fcdd904b 100644 --- a/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp +++ b/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp @@ -326,10 +326,9 @@ class NativeMapView : public MapObserver { void enableRenderingStatsView(JNIEnv&, jni::jboolean); // Plugins - void addPluginFileSource(JNIEnv &, - const jni::Object& ); + void addPluginFileSource(JNIEnv&, const jni::Object&); - // Shader compilation + // Shader compilation void onRegisterShaders(mbgl::gfx::ShaderRegistry&) override; void onPreCompileShader(mbgl::shaders::BuiltIn, mbgl::gfx::Backend::Type, const std::string&) override; void onPostCompileShader(mbgl::shaders::BuiltIn, mbgl::gfx::Backend::Type, const std::string&) override; diff --git a/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.cpp b/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.cpp index a7153e87c11d..b288678af17a 100644 --- a/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.cpp +++ b/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.cpp @@ -8,27 +8,26 @@ using namespace mbgl::android; // the jni.hpp dependency namespace jni { - struct ByteBufferTag - { - static constexpr auto Name() { return "java/nio/ByteBuffer"; } - }; - - template <> - struct TagTraits< ByteBufferTag > - { - using SuperType = Object; - using UntaggedType = jobject; - }; +struct ByteBufferTag { + static constexpr auto Name() { return "java/nio/ByteBuffer"; } +}; -} +template <> +struct TagTraits { + using SuperType = Object; + using UntaggedType = jobject; +}; + +} // namespace jni void PluginFileSource::registerNative(jni::JNIEnv& env) { jni::Class::Singleton(env); } -jni::Global> PluginFileSource::createJavaResource(jni::JNIEnv& env, - const mbgl::Resource &resource) { - jni::Global> tempResult = jni::NewGlobal(env, PluginProtocolHandlerResource::Create(env)); +jni::Global> PluginFileSource::createJavaResource( + jni::JNIEnv& env, const mbgl::Resource& resource) { + jni::Global> tempResult = jni::NewGlobal( + env, PluginProtocolHandlerResource::Create(env)); PluginProtocolHandlerResource::Update(env, tempResult, resource); return tempResult; } @@ -44,10 +43,9 @@ jni::Local> PluginProtocolHandlerReso } void PluginProtocolHandlerResource::Update(jni::JNIEnv& env, - jni::Object& javaObject, - const mbgl::Resource &resource) { - - static auto &javaClass = jni::Class::Singleton(env); + jni::Object& javaObject, + const mbgl::Resource& resource) { + static auto& javaClass = jni::Class::Singleton(env); static auto resourceKindField = javaClass.GetField(env, "kind"); javaObject.Set(env, resourceKindField, static_cast(resource.kind)); @@ -55,24 +53,22 @@ void PluginProtocolHandlerResource::Update(jni::JNIEnv& env, static auto resourceURLField = javaClass.GetField(env, "resourceURL"); auto str = jni::Make(env, resource.url); // wrap the jstring javaObject.Set(env, resourceURLField, str); - } - void PluginProtocolHandlerResponse::registerNative(jni::JNIEnv& env) { jni::Class::Singleton(env); } -jni::Local> PluginProtocolHandlerResponse::Create(jni::JNIEnv&env) { +jni::Local> PluginProtocolHandlerResponse::Create(jni::JNIEnv& env) { auto& javaClass = jni::Class::Singleton(env); auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor); } -void PluginProtocolHandlerResponse::Update(jni::JNIEnv & env, +void PluginProtocolHandlerResponse::Update(jni::JNIEnv& env, [[maybe_unused]] jni::Object& javaObject, - [[maybe_unused]] mbgl::Response &response) { - static auto &javaClass = jni::Class::Singleton(env); + [[maybe_unused]] mbgl::Response& response) { + static auto& javaClass = jni::Class::Singleton(env); static auto dataField = javaClass.GetField>(env, "data"); auto objectValue = javaObject.Get(env, dataField); auto objectRef = jobject(objectValue.get()); diff --git a/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.hpp b/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.hpp index 6e829004a513..cea25e21e4de 100644 --- a/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.hpp +++ b/platform/android/MapLibreAndroid/src/cpp/plugin/plugin_file_source.hpp @@ -4,47 +4,42 @@ #include namespace mbgl { - namespace android { +namespace android { - class PluginProtocolHandlerResource { - public: - static constexpr auto Name() { return "org/maplibre/android/plugin/PluginProtocolHandlerResource"; }; - static void registerNative(jni::JNIEnv&); +class PluginProtocolHandlerResource { +public: + static constexpr auto Name() { return "org/maplibre/android/plugin/PluginProtocolHandlerResource"; }; + static void registerNative(jni::JNIEnv &); - static jni::Local> Create(jni::JNIEnv&); - static void Update(jni::JNIEnv&, jni::Object&, const mbgl::Resource &); - }; + static jni::Local> Create(jni::JNIEnv &); + static void Update(jni::JNIEnv &, jni::Object &, const mbgl::Resource &); +}; - class PluginProtocolHandlerResponse { - public: - static constexpr auto Name() { return "org/maplibre/android/plugin/PluginProtocolHandlerResponse"; }; - static void registerNative(jni::JNIEnv&); +class PluginProtocolHandlerResponse { +public: + static constexpr auto Name() { return "org/maplibre/android/plugin/PluginProtocolHandlerResponse"; }; + static void registerNative(jni::JNIEnv &); - static jni::Local> Create(jni::JNIEnv&); - static void Update(jni::JNIEnv&, - jni::Object&, - mbgl::Response &); + static jni::Local> Create(jni::JNIEnv &); + static void Update(jni::JNIEnv &, jni::Object &, mbgl::Response &); +}; - }; +class PluginFileSource { +public: + static constexpr auto Name() { return "org/maplibre/android/plugin/PluginFileSource"; }; - class PluginFileSource { - public: - static constexpr auto Name() { return "org/maplibre/android/plugin/PluginFileSource"; }; + // static mbgl::PluginFileSource getFileSource(jni::JNIEnv&, const jni::Object&); - //static mbgl::PluginFileSource getFileSource(jni::JNIEnv&, const jni::Object&); + static jni::Global> createJavaResource(jni::JNIEnv &env, + const mbgl::Resource &resource); - static jni::Global> createJavaResource(jni::JNIEnv& env, - const mbgl::Resource &resource); - - static void registerNative(jni::JNIEnv&); - }; - - class PluginFileSourceContainer { - public: - jni::Global> _fileSource; - }; - - } -} + static void registerNative(jni::JNIEnv &); +}; +class PluginFileSourceContainer { +public: + jni::Global> _fileSource; +}; +} // namespace android +} // namespace mbgl diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResponse.kt b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResponse.kt index d9fd3a242739..c630626e4ed8 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResponse.kt +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResponse.kt @@ -16,4 +16,4 @@ class PluginProtocolHandlerResponse { var data: ByteBuffer? = null; -} \ No newline at end of file +} diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/TileData.kt b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/TileData.kt index 9ecdb35b5460..2a9f27abe151 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/TileData.kt +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/TileData.kt @@ -12,4 +12,4 @@ class TileData { var tileZoom: Int = 0; -} \ No newline at end of file +} diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt index 7b1970a886a6..42838fadcce5 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt @@ -33,4 +33,4 @@ class PluginProtocolExample : PluginProtocolHandler() { return tempResult; } -} \ No newline at end of file +} From f40828257f49421ba5324f370f4ea42f4e417e19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Tue, 29 Jul 2025 18:10:53 -0400 Subject: [PATCH 163/221] Updates --- .../plugin/PluginProtocolHandlerResource.kt | 10 ++-- .../plugin/PluginProtocolHandlerResponse.kt | 15 +++--- .../activity/plugin/PluginProtocolExample.kt | 48 +++++++++++++------ 3 files changed, 45 insertions(+), 28 deletions(-) diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResource.kt b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResource.kt index f72b4628889f..606311cdf690 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResource.kt +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResource.kt @@ -2,7 +2,7 @@ package org.maplibre.android.plugin class PluginProtocolHandlerResource { - enum class PluginProtocolHandlerResourceKind { + enum class Kind { Unknown, Style, Source, @@ -13,20 +13,20 @@ class PluginProtocolHandlerResource { Image }; - enum class PluginProtocolHandlerResourceLoadingMethod { + enum class LoadingMethod { Unknown, CacheOnly, NetworkOnly, All }; - var resourceURL: String = "Test"; + var resourceURL: String = ""; var kind: Int = 0; - var resourceKind: PluginProtocolHandlerResourceKind = PluginProtocolHandlerResourceKind.Unknown; + var resourceKind: Kind = Kind.Unknown; - var loadingMethod: PluginProtocolHandlerResourceLoadingMethod = PluginProtocolHandlerResourceLoadingMethod.Unknown; + var loadingMethod: LoadingMethod = LoadingMethod.Unknown; var tileData: TileData? = null; diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResponse.kt b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResponse.kt index c630626e4ed8..5df047bd7c51 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResponse.kt +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginProtocolHandlerResponse.kt @@ -1,17 +1,16 @@ package org.maplibre.android.plugin import java.nio.ByteBuffer +import java.nio.charset.StandardCharsets class PluginProtocolHandlerResponse { - fun generateBuffer() { - data = ByteBuffer.allocateDirect(1000); - - // Example: write bytes - for (i in 0..<255) { - data!!.put(i.toByte()) - } - + fun generateBuffer(stringBuffer: String) { + val byteArray = stringBuffer.toByteArray(StandardCharsets.UTF_8); + val buffer = ByteBuffer.allocateDirect(byteArray.size); + buffer.put(byteArray); + buffer.flip(); + data = buffer; } var data: ByteBuffer? = null; diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt index 42838fadcce5..6e99f2cf0b73 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt @@ -3,33 +3,51 @@ package org.maplibre.android.testapp.activity.plugin import org.maplibre.android.plugin.PluginProtocolHandler import org.maplibre.android.plugin.PluginProtocolHandlerResource import org.maplibre.android.plugin.PluginProtocolHandlerResponse +import java.net.URI + class PluginProtocolExample : PluginProtocolHandler() { override fun canRequestResource(resource: PluginProtocolHandlerResource?): Boolean { - if (resource == null) { - return false; - } - - if (resource.resourceURL != null) { - if (resource.resourceURL!!.contains("pluginProtocol")) { - return true; - } - } + return true; - if (resource.resourceKind == PluginProtocolHandlerResource.PluginProtocolHandlerResourceKind.Unknown) { - return true; - } - - return false; } override fun requestResource(resource: PluginProtocolHandlerResource?): PluginProtocolHandlerResponse? { // Return some data here var tempResult = PluginProtocolHandlerResponse(); - tempResult.generateBuffer(); + + val tempStyle: String = + "{\n" + + " \"id\": \"43f36e14-e3f5-43c1-84c0-50a9c80dc5c7\",\n" + + " \"name\": \"MapLibre\",\n" + + " \"zoom\": 0.8619833357855968,\n" + + " \"pitch\": 0,\n" + + " \"center\": [\n" + + " 17.65431710431244,\n" + + " 32.954120326746775\n" + + " ],\n" + + " \"layers\": [\n" + + " {\n" + + " \"id\": \"background\",\n" + + " \"type\": \"background\",\n" + + " \"paint\": {\n" + + " \"background-color\": \"#000000\"\n" + + " },\n" + + " \"filter\": [\n" + + " \"all\"\n" + + " ],\n" + + " \"layout\": {\n" + + " \"visibility\": \"visible\"\n" + + " },\n" + + " \"maxzoom\": 24\n" + + " }\n" + " ]\n" + " } \n" + + tempResult.generateBuffer(tempStyle); return tempResult; } From 3406120f733f8621174ed2dd441f4f6dbbc41763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Tue, 29 Jul 2025 21:15:09 -0400 Subject: [PATCH 164/221] Added example plugin --- .../activity/plugin/PluginProtocolExample.kt | 60 +++++++++++++++++-- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt index 6e99f2cf0b73..f027dde05fc3 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/plugin/PluginProtocolExample.kt @@ -7,10 +7,14 @@ import java.net.URI class PluginProtocolExample : PluginProtocolHandler() { + var styleLoaded: Boolean = false; override fun canRequestResource(resource: PluginProtocolHandlerResource?): Boolean { - - return true; + if (!styleLoaded) { + styleLoaded = true; + return true; + } + return false; } @@ -43,9 +47,55 @@ class PluginProtocolExample : PluginProtocolHandler() { " \"visibility\": \"visible\"\n" + " },\n" + " \"maxzoom\": 24\n" + - " }\n" - " ]\n" - " } \n" + " },\n"+ + " {\n" + + " \"id\": \"coastline\",\n" + + " \"type\": \"line\",\n" + + " \"paint\": {\n" + + " \"line-blur\": 0.5,\n" + + " \"line-color\": \"#198EC8\",\n" + + " \"line-width\": {\n" + + " \"stops\": [\n" + + " [\n" + + " 0,\n" + + " 2\n" + + " ],\n" + + " [\n" + + " 6,\n" + + " 6\n" + + " ],\n" + + " [\n" + + " 14,\n" + + " 9\n" + + " ],\n" + + " [\n" + + " 22,\n" + + " 18\n" + + " ]\n" + + " ]\n" + + " }\n" + + " },\n" + + " \"filter\": [\n" + + " \"all\"\n" + + " ],\n" + + " \"layout\": {\n" + + " \"line-cap\": \"round\",\n" + + " \"line-join\": \"round\",\n" + + " \"visibility\": \"visible\"\n" + + " },\n" + + " \"source\": \"maplibre\",\n" + + " \"maxzoom\": 24,\n" + + " \"minzoom\": 0,\n" + + " \"source-layer\": \"countries\"\n" + + " }"+ + " ],\n"+ + " \"sources\": {\n" + + " \"maplibre\": {\n" + + " \"url\": \"https://demotiles.maplibre.org/tiles/tiles.json\",\n" + + " \"type\": \"vector\"\n" + + " },"+ + " \"version\": 8\n"+ + " } }\n"; tempResult.generateBuffer(tempStyle); return tempResult; From 4a8010c08b1f3a2170ca83cecf65041860e0e26c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Fri, 1 Aug 2025 10:10:26 -0400 Subject: [PATCH 165/221] Updated the file source name --- platform/default/src/mbgl/storage/plugin_file_source.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/default/src/mbgl/storage/plugin_file_source.cpp b/platform/default/src/mbgl/storage/plugin_file_source.cpp index 120308a743da..163542eeef30 100644 --- a/platform/default/src/mbgl/storage/plugin_file_source.cpp +++ b/platform/default/src/mbgl/storage/plugin_file_source.cpp @@ -75,7 +75,7 @@ void PluginFileSource::setOnRequestResourceFunction(OnRequestResource requestFun PluginFileSource::PluginFileSource(const ResourceOptions& resourceOptions, const ClientOptions& clientOptions) : impl(std::make_unique>( util::makeThreadPrioritySetter(platform::EXPERIMENTAL_THREAD_PRIORITY_FILE), - "LocalFileSource", + "PluginFileSource", resourceOptions.clone(), clientOptions.clone())) {} From 0199769f7682c034b7758f7e6bbc622bf0e8a76b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Fri, 1 Aug 2025 10:55:29 -0400 Subject: [PATCH 166/221] Clean up from merge --- platform/ios/src/MLNMapView.mm | 1 - 1 file changed, 1 deletion(-) diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 8c77a023f65a..305ebbf0adf7 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -7921,7 +7921,6 @@ -(void)addPluginLayerType:(Class)pluginLayerClass { } -<<<<<<< HEAD - (MLNPluginProtocolHandlerResource *)resourceFromCoreResource:(const mbgl::Resource &)resource { MLNPluginProtocolHandlerResource *tempResult = [[MLNPluginProtocolHandlerResource alloc] init]; From a75ca03539bc042ed8eb54801f414ce8416add95 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 15:16:32 +0000 Subject: [PATCH 167/221] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- platform/ios/src/MLNMapView.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/src/MLNMapView.h b/platform/ios/src/MLNMapView.h index 5ce8c69b24cc..3758303e8d4c 100644 --- a/platform/ios/src/MLNMapView.h +++ b/platform/ios/src/MLNMapView.h @@ -2282,7 +2282,7 @@ vertically on the map. */ - (void)addPluginProtocolHandler:(Class)pluginProtocolHandlerClass; -/** +/** Adds a style filter to the map view */ - (void)addStyleFilter:(MLNStyleFilter *)styleFilter; From 6c10c0c4ebd7977f463dfd624644b52a9e20e755 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 31 Jul 2025 12:28:16 +0300 Subject: [PATCH 168/221] cleanup code and remove unnecessary logic --- include/mbgl/gfx/drawable.hpp | 1 - include/mbgl/map/map_options.hpp | 2 -- include/mbgl/vulkan/drawable.hpp | 1 - src/mbgl/gfx/drawable.cpp | 1 - src/mbgl/map/map.cpp | 1 - src/mbgl/map/map_options.cpp | 6 ------ 6 files changed, 12 deletions(-) diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index 78683a83101a..d820040dbea3 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -35,7 +35,6 @@ namespace gfx { class ColorMode; class CullFaceMode; -class ScissorRect; enum class DepthMaskType : bool; class DrawableTweaker; class DrawMode; diff --git a/include/mbgl/map/map_options.hpp b/include/mbgl/map/map_options.hpp index 9c6def668757..12a6b874f9e0 100644 --- a/include/mbgl/map/map_options.hpp +++ b/include/mbgl/map/map_options.hpp @@ -111,8 +111,6 @@ class MapOptions final { */ MapOptions& withSize(Size size_); - MapOptions& withFrustumOffset(const EdgeInsets& frustuOffset_); - /** * @brief Gets the previously set size. * diff --git a/include/mbgl/vulkan/drawable.hpp b/include/mbgl/vulkan/drawable.hpp index a4b73497a922..9ed2c2982ceb 100644 --- a/include/mbgl/vulkan/drawable.hpp +++ b/include/mbgl/vulkan/drawable.hpp @@ -3,7 +3,6 @@ #include #include -#include #include namespace mbgl { diff --git a/src/mbgl/gfx/drawable.cpp b/src/mbgl/gfx/drawable.cpp index def1e052580f..82d053f08ead 100644 --- a/src/mbgl/gfx/drawable.cpp +++ b/src/mbgl/gfx/drawable.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 8ad07b9bad25..fe87cbb1ca8d 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -410,7 +410,6 @@ MapOptions Map::getMapOptions() const { .withCrossSourceCollisions(impl->crossSourceCollisions) .withNorthOrientation(impl->transform->getNorthOrientation()) .withSize(impl->transform->getState().getSize()) - .withFrustumOffset(impl->transform->getState().getFrustumOffset()) .withPixelRatio(impl->pixelRatio)); } diff --git a/src/mbgl/map/map_options.cpp b/src/mbgl/map/map_options.cpp index ffbdaeea5d1a..ea9a0679e0cf 100644 --- a/src/mbgl/map/map_options.cpp +++ b/src/mbgl/map/map_options.cpp @@ -11,7 +11,6 @@ class MapOptions::Impl { NorthOrientation orientation = NorthOrientation::Upwards; bool crossSourceCollisions = true; Size size = {64, 64}; - EdgeInsets frustumOffset = {0.f, 0.f, 0.f, 0.f}; float pixelRatio = 1.0; }; @@ -71,11 +70,6 @@ MapOptions& MapOptions::withSize(Size size_) { return *this; } -MapOptions& MapOptions::withFrustumOffset(const EdgeInsets& frustumOffset_) { - impl_->frustumOffset = frustumOffset_; - return *this; -} - Size MapOptions::size() const { return impl_->size; } From 9688d7d964c41d79479f0a2ea6c3323e186ada17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Tue, 5 Aug 2025 23:06:51 -0400 Subject: [PATCH 169/221] Added a couple of delegate methods to the network delegate --- platform/darwin/core/http_file_source.mm | 9 +++++++++ .../include/mbgl/interface/native_apple_interface.h | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/platform/darwin/core/http_file_source.mm b/platform/darwin/core/http_file_source.mm index 62ced8e7d1f3..5ca75e65c057 100644 --- a/platform/darwin/core/http_file_source.mm +++ b/platform/darwin/core/http_file_source.mm @@ -292,11 +292,20 @@ BOOL isValidMapboxEndpoint(NSURL *url) { assert(session); + if ([networkManager.delegate respondsToSelector:@selector(willSendRequest:)]) { + req = [networkManager.delegate willSendRequest:req]; + } + request->task = [session dataTaskWithRequest:req completionHandler:^(NSData* data, NSURLResponse* res, NSError* error) { session = nil; + if ([networkManager.delegate respondsToSelector:@selector(didReceiveResponse:data:error:)]) { + [networkManager.delegate didReceiveResponse:res data:data error:error]; + } + + if (error && [error code] == NSURLErrorCancelled) { [MLNNativeNetworkManager.sharedManager cancelDownloadEventForResponse:res]; return; diff --git a/platform/darwin/include/mbgl/interface/native_apple_interface.h b/platform/darwin/include/mbgl/interface/native_apple_interface.h index 7633819bb302..0976ed8a405f 100644 --- a/platform/darwin/include/mbgl/interface/native_apple_interface.h +++ b/platform/darwin/include/mbgl/interface/native_apple_interface.h @@ -10,6 +10,10 @@ NS_ASSUME_NONNULL_BEGIN - (NSURLSession *)sessionForNetworkManager:(MLNNativeNetworkManager *)networkManager; +-(NSMutableURLRequest *)willSendRequest:(NSMutableURLRequest *)request; + +-(void)didReceiveResponse:(NSURLResponse *)response data:(NSData *)data error:(NSError *)error; + @required - (NSURLSessionConfiguration *)sessionConfiguration; From f6684f57ae68ff02e75be1b6c10cff91202064f2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 6 Aug 2025 03:09:31 +0000 Subject: [PATCH 170/221] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- platform/darwin/core/http_file_source.mm | 6 +++--- .../darwin/include/mbgl/interface/native_apple_interface.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/platform/darwin/core/http_file_source.mm b/platform/darwin/core/http_file_source.mm index 5ca75e65c057..3c7303cfe92b 100644 --- a/platform/darwin/core/http_file_source.mm +++ b/platform/darwin/core/http_file_source.mm @@ -295,7 +295,7 @@ BOOL isValidMapboxEndpoint(NSURL *url) { if ([networkManager.delegate respondsToSelector:@selector(willSendRequest:)]) { req = [networkManager.delegate willSendRequest:req]; } - + request->task = [session dataTaskWithRequest:req completionHandler:^(NSData* data, NSURLResponse* res, NSError* error) { @@ -304,8 +304,8 @@ BOOL isValidMapboxEndpoint(NSURL *url) { if ([networkManager.delegate respondsToSelector:@selector(didReceiveResponse:data:error:)]) { [networkManager.delegate didReceiveResponse:res data:data error:error]; } - - + + if (error && [error code] == NSURLErrorCancelled) { [MLNNativeNetworkManager.sharedManager cancelDownloadEventForResponse:res]; return; diff --git a/platform/darwin/include/mbgl/interface/native_apple_interface.h b/platform/darwin/include/mbgl/interface/native_apple_interface.h index 0976ed8a405f..74532d763df9 100644 --- a/platform/darwin/include/mbgl/interface/native_apple_interface.h +++ b/platform/darwin/include/mbgl/interface/native_apple_interface.h @@ -10,9 +10,9 @@ NS_ASSUME_NONNULL_BEGIN - (NSURLSession *)sessionForNetworkManager:(MLNNativeNetworkManager *)networkManager; --(NSMutableURLRequest *)willSendRequest:(NSMutableURLRequest *)request; +- (NSMutableURLRequest *)willSendRequest:(NSMutableURLRequest *)request; --(void)didReceiveResponse:(NSURLResponse *)response data:(NSData *)data error:(NSError *)error; +- (void)didReceiveResponse:(NSURLResponse *)response data:(NSData *)data error:(NSError *)error; @required From 8f89266482cf471955afedab08f00048254572fa Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 6 Aug 2025 15:28:18 +0300 Subject: [PATCH 171/221] make new ios release with fix --- platform/ios/VERSION | 2 +- platform/ios/src/MLNMapView.mm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/ios/VERSION b/platform/ios/VERSION index 89b71fa94204..2c2a1513040f 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.17.4 +6.17.5 diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 5c5d52418d5f..8fb715d92d24 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -4466,7 +4466,7 @@ - (void)_flyToCamera:(MLNMapCamera *)camera edgePadding:(UIEdgeInsets)insets wit } - (void)cancelTransitions { - if (!_mbglMap || (self.concurrentAnimations && self.userTrackingMode != MLNUserTrackingModeNone && self.userTrackingMode != MLNUserTrackingModeFollow)) + if (!_mbglMap || self.concurrentAnimations) { return; } From 1f2c150e856e3d658377c0a2af69555944d81b04 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 6 Aug 2025 18:11:40 +0300 Subject: [PATCH 172/221] fix conflicts after merging from main --- src/mbgl/vulkan/pipeline.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mbgl/vulkan/pipeline.cpp b/src/mbgl/vulkan/pipeline.cpp index 44124594966c..b2bc477879cb 100644 --- a/src/mbgl/vulkan/pipeline.cpp +++ b/src/mbgl/vulkan/pipeline.cpp @@ -431,7 +431,6 @@ void PipelineInfo::setDynamicValues(const RendererBackend& backend, const vk::Un buffer->setViewport(0, viewport, dispatcher); buffer->setScissor(0, scissorRect, dispatcher); -#endif } std::vector PipelineInfo::getDynamicStates(const RendererBackend& backend) const { From 14d0f1ee0e3102fe503a049da7dc77a1dd64d599 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 7 Aug 2025 11:52:52 +0300 Subject: [PATCH 173/221] remove release announcements because they announce in the maplibre:main unnecessarily --- .github/workflows/android-release.yml | 10 +++++----- .github/workflows/ios-ci.yml | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/android-release.yml b/.github/workflows/android-release.yml index 785df874c360..80d70434de23 100644 --- a/.github/workflows/android-release.yml +++ b/.github/workflows/android-release.yml @@ -150,8 +150,8 @@ jobs: - run: npm install working-directory: . - - name: Write release notifications - env: - GITHUB_TOKEN: ${{ secrets.MAPLIBRE_NATIVE_PRIVATE_TOKEN }} - run: node .github/scripts/notify-release-on-prs.ts --tag ${{ needs.android-create-release.outputs.version_tag }} - working-directory: . + # - name: Write release notifications + # env: + # GITHUB_TOKEN: ${{ secrets.MAPLIBRE_NATIVE_PRIVATE_TOKEN }} + # run: node .github/scripts/notify-release-on-prs.ts --tag ${{ needs.android-create-release.outputs.version_tag }} + # working-directory: . diff --git a/.github/workflows/ios-ci.yml b/.github/workflows/ios-ci.yml index 23f71e7c8371..b97bb3b2dc90 100644 --- a/.github/workflows/ios-ci.yml +++ b/.github/workflows/ios-ci.yml @@ -364,12 +364,12 @@ jobs: # env: # GH_TOKEN: ${{ secrets.MAPLIBRE_NATIVE_PRIVATE_TOKEN }} - - name: Write release notifications - if: env.make_release - env: - GITHUB_TOKEN: ${{ secrets.MAPLIBRE_NATIVE_PRIVATE_TOKEN }} - run: node .github/scripts/notify-release-on-prs.ts --tag ios-v${{ env.version }} - working-directory: . + # - name: Write release notifications + # if: env.make_release + # env: + # GITHUB_TOKEN: ${{ secrets.MAPLIBRE_NATIVE_PRIVATE_TOKEN }} + # run: node .github/scripts/notify-release-on-prs.ts --tag ios-v${{ env.version }} + # working-directory: . ios-build-cmake: needs: pre_job From 216dd74ea5cb6eb4fd75678ccbc38791d8e0042e Mon Sep 17 00:00:00 2001 From: AtlasProgramming Date: Sat, 9 Aug 2025 21:42:28 -0400 Subject: [PATCH 174/221] Update native_map_view.cpp --- platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp index 5ea95cc63e23..27d0f39e555f 100644 --- a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp +++ b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp @@ -1546,14 +1546,11 @@ void NativeMapView::registerNative(jni::JNIEnv& env) { METHOD(&NativeMapView::setTileLodZoomShift, "nativeSetTileLodZoomShift"), METHOD(&NativeMapView::getTileLodZoomShift, "nativeGetTileLodZoomShift"), METHOD(&NativeMapView::triggerRepaint, "nativeTriggerRepaint"), -<<<<<<< HEAD METHOD(&NativeMapView::toggleTransform, "nativeToggleTransform"), METHOD(&NativeMapView::setFrustumOffset, "nativeSetFrustumOffset")); -======= METHOD(&NativeMapView::isRenderingStatsViewEnabled, "nativeIsRenderingStatsViewEnabled"), METHOD(&NativeMapView::enableRenderingStatsView, "nativeEnableRenderingStatsView"), METHOD(&NativeMapView::addPluginFileSource, "nativeAddPluginFileSource")); ->>>>>>> maplibre/feature/2025-08-plugins } void NativeMapView::onRegisterShaders(gfx::ShaderRegistry&) {}; From 61dfbb35e3f74f687d33ede9e916d79f08d2970f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sat, 9 Aug 2025 21:58:41 -0400 Subject: [PATCH 175/221] Removed single feature loaded function --- platform/darwin/app/PluginLayerExample.mm | 6 ------ platform/darwin/src/MLNPluginLayer.h | 7 ------- platform/darwin/src/MLNPluginLayer.mm | 6 ------ platform/ios/src/MLNMapView.mm | 11 ----------- src/mbgl/plugin/feature_collection_bucket.cpp | 11 ----------- src/mbgl/plugin/plugin_layer.hpp | 1 - src/mbgl/plugin/plugin_layer_impl.hpp | 7 ------- 7 files changed, 49 deletions(-) diff --git a/platform/darwin/app/PluginLayerExample.mm b/platform/darwin/app/PluginLayerExample.mm index 92d7056a0f19..1339f51289dd 100644 --- a/platform/darwin/app/PluginLayerExample.mm +++ b/platform/darwin/app/PluginLayerExample.mm @@ -69,12 +69,6 @@ -(void)featureUnloaded:(MLNPluginLayerTileFeature *)tileFeature { } -- (void)onFeatureLoaded:(MLNPluginLayerTileFeature *)tileFeature { - - [self featureLoaded:tileFeature]; - -} - /// Called when a set of features are loaded from the tile - (void)onFeatureCollectionLoaded:(MLNPluginLayerTileFeatureCollection *)tileFeatureCollection { //NSLog(@"Feature Collection Loaded for tile: %@", tileFeatureCollection.tileID); diff --git a/platform/darwin/src/MLNPluginLayer.h b/platform/darwin/src/MLNPluginLayer.h index 5b3fe06f7cca..7f3242a13573 100644 --- a/platform/darwin/src/MLNPluginLayer.h +++ b/platform/darwin/src/MLNPluginLayer.h @@ -123,14 +123,7 @@ MLN_EXPORT /// dynamic properties are updated - (void)onUpdateLayerProperties:(NSDictionary *)layerProperties; -/// Called when a feature is loaded from the tile -- (void)onFeatureLoaded:(MLNPluginLayerTileFeature *)tileFeature; - /// Called when a set of features are loaded from the tile -/* - TODO: Think about returning that this layer doesn't care about this feature collection via a - bool/etc and then the underlying layer won't have to track this collection. - */ - (void)onFeatureCollectionLoaded:(MLNPluginLayerTileFeatureCollection *)tileFeatureCollection; /// Called when a set of features are unloaded because the tile goes out of scene/etc diff --git a/platform/darwin/src/MLNPluginLayer.mm b/platform/darwin/src/MLNPluginLayer.mm index 05de4517e1ce..0e57affd1e7f 100644 --- a/platform/darwin/src/MLNPluginLayer.mm +++ b/platform/darwin/src/MLNPluginLayer.mm @@ -74,12 +74,6 @@ -(void)onUpdateLayerProperties:(NSDictionary *)layerProperties { // Base class does nothing } -// If the layer properties indicate that this layer has a the ability to intercept -// features, then this method will be called when a feature is loaded -- (void)onFeatureLoaded:(MLNPluginLayerTileFeature *)tileFeature { - // Base class does nothing -} - // If the layer properties indicate that this layer has a the ability to intercept // features, then this method will be called when a feature is loaded - (void)onFeatureCollectionLoaded:(MLNPluginLayerTileFeatureCollection *)tileFeatureCollection { diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 305ebbf0adf7..8e62beaeb131 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -7851,17 +7851,6 @@ -(void)addPluginLayerType:(Class)pluginLayerClass { // If this layer can read tile features, then setup that lambda if (capabilities.supportsReadingTileFeatures) { - pluginLayerImpl->setFeatureLoadedFunction([weakPlugInLayer, weakMapView](const std::shared_ptr feature) { - - @autoreleasepool { - MLNPluginLayerTileFeature *tileFeature = [weakMapView featureFromCore:feature]; - - [weakPlugInLayer onFeatureLoaded:tileFeature]; - - } - - }); - pluginLayerImpl->setFeatureCollectionLoadedFunction([weakPlugInLayer, weakMapView](const std::shared_ptr featureCollection) { diff --git a/src/mbgl/plugin/feature_collection_bucket.cpp b/src/mbgl/plugin/feature_collection_bucket.cpp index fb2c9f9e6625..09d24dbbd09b 100644 --- a/src/mbgl/plugin/feature_collection_bucket.cpp +++ b/src/mbgl/plugin/feature_collection_bucket.cpp @@ -111,17 +111,6 @@ void FeatureCollectionBucket::addFeature(const GeometryTileFeature& tileFeature, tempFeature->_featureCoordinates.push_back(c); } - for (auto l : _layers) { - auto bi = l->baseImpl; - auto bip = bi.get(); - auto pluginLayer = static_cast(bip); - if (pluginLayer != nullptr) { - if (pluginLayer->_featureLoadedFunction != nullptr) { - pluginLayer->_featureLoadedFunction(tempFeature); - } - } - } - _featureCollection->_features.push_back(tempFeature); } diff --git a/src/mbgl/plugin/plugin_layer.hpp b/src/mbgl/plugin/plugin_layer.hpp index 5e6bb9adb06d..07fd90228cad 100644 --- a/src/mbgl/plugin/plugin_layer.hpp +++ b/src/mbgl/plugin/plugin_layer.hpp @@ -31,7 +31,6 @@ class PluginLayer final : public Layer { using OnRenderLayer = std::function; using OnUpdateLayer = std::function; using OnUpdateLayerProperties = std::function; - using OnFeatureLoaded = std::function feature)>; using OnFeatureCollectionLoaded = std::function featureCollection)>; using OnFeatureCollectionUnloaded = diff --git a/src/mbgl/plugin/plugin_layer_impl.hpp b/src/mbgl/plugin/plugin_layer_impl.hpp index 7b79399ee07b..e79e75320d77 100644 --- a/src/mbgl/plugin/plugin_layer_impl.hpp +++ b/src/mbgl/plugin/plugin_layer_impl.hpp @@ -99,10 +99,6 @@ class PluginLayer::Impl : public Layer::Impl { _updateLayerPropertiesFunction = updateLayerPropertiesFunction; } - void setFeatureLoadedFunction(OnFeatureLoaded featureLoadedFunction) { - _featureLoadedFunction = featureLoadedFunction; - } - void setFeatureCollectionLoadedFunction(OnFeatureCollectionLoaded featureCollectionLoadedFunction) { _featureCollectionLoadedFunction = featureCollectionLoadedFunction; } @@ -125,9 +121,6 @@ class PluginLayer::Impl : public Layer::Impl { //! Optional: Called when the layer properties change. The properties are passed as JSON for now OnUpdateLayerProperties _updateLayerPropertiesFunction; - //! Optional: Called when feature is loaded - OnFeatureLoaded _featureLoadedFunction; - //! Optional: Called when a feature collection is loaded OnFeatureCollectionLoaded _featureCollectionLoadedFunction; From de359a84a61d76c8ac4b48aa3a5811f6efed421d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Mon, 11 Aug 2025 01:04:24 -0400 Subject: [PATCH 176/221] Update --- platform/BUILD.bazel | 4 - platform/darwin/BUILD.bazel | 18 - platform/darwin/bazel/files.bzl | 82 -- platform/darwin/src/MLNPluginLayer.h | 1 - platform/darwin/src/gltf/Camera.cpp | 54 - platform/darwin/src/gltf/Camera.hpp | 32 - platform/darwin/src/gltf/GLTFMTLRenderItem.h | 22 - platform/darwin/src/gltf/GLTFMTLRenderItem.mm | 12 - platform/darwin/src/gltf/GLTFManager.hpp | 106 -- platform/darwin/src/gltf/GLTFManager.mm | 170 --- .../gltf/GLTFManagerRenderingEnvironment.hpp | 40 - .../gltf/GLTFManagerRenderingEnvironment.mm | 8 - .../GLTFManagerRenderingEnvironmentMetal.hpp | 41 - .../GLTFManagerRenderingEnvironmentMetal.mm | 8 - platform/darwin/src/gltf/GLTFMath.cpp | 192 --- platform/darwin/src/gltf/GLTFMath.hpp | 139 -- platform/darwin/src/gltf/GLTFModel.cpp | 8 - platform/darwin/src/gltf/GLTFModel.hpp | 46 - platform/darwin/src/gltf/GLTFModelLayer.h | 29 - platform/darwin/src/gltf/GLTFModelLayer.mm | 357 ----- platform/darwin/src/gltf/GLTFModelLoader.h | 23 - platform/darwin/src/gltf/GLTFModelLoader.mm | 74 - platform/darwin/src/gltf/GLTFRenderer.cpp | 71 - platform/darwin/src/gltf/GLTFRenderer.hpp | 70 - .../src/gltf/MetalRenderer+GLTFAsset.mm | 561 -------- platform/darwin/src/gltf/MetalRenderer.hpp | 228 --- platform/darwin/src/gltf/MetalRenderer.mm | 540 ------- .../darwin/src/gltf/gltfkit/GLTFAccessor.h | 40 - .../darwin/src/gltf/gltfkit/GLTFAccessor.mm | 26 - .../darwin/src/gltf/gltfkit/GLTFAnimation.h | 46 - .../darwin/src/gltf/gltfkit/GLTFAnimation.mm | 173 --- platform/darwin/src/gltf/gltfkit/GLTFAsset.h | 70 - platform/darwin/src/gltf/gltfkit/GLTFAsset.mm | 1274 ----------------- .../darwin/src/gltf/gltfkit/GLTFBinaryChunk.h | 35 - .../src/gltf/gltfkit/GLTFBinaryChunk.mm | 23 - platform/darwin/src/gltf/gltfkit/GLTFBuffer.h | 31 - .../src/gltf/gltfkit/GLTFBufferAllocator.h | 29 - .../darwin/src/gltf/gltfkit/GLTFBufferView.h | 32 - .../darwin/src/gltf/gltfkit/GLTFBufferView.mm | 26 - platform/darwin/src/gltf/gltfkit/GLTFCamera.h | 42 - .../darwin/src/gltf/gltfkit/GLTFCamera.mm | 115 -- .../gltf/gltfkit/GLTFDefaultBufferAllocator.h | 27 - .../gltfkit/GLTFDefaultBufferAllocator.mm | 93 -- platform/darwin/src/gltf/gltfkit/GLTFEnums.h | 178 --- .../src/gltf/gltfkit/GLTFExtensionNames.h | 23 - .../src/gltf/gltfkit/GLTFExtensionNames.mm | 23 - platform/darwin/src/gltf/gltfkit/GLTFImage.h | 40 - platform/darwin/src/gltf/gltfkit/GLTFImage.mm | 57 - .../darwin/src/gltf/gltfkit/GLTFKHRLight.h | 53 - .../darwin/src/gltf/gltfkit/GLTFKHRLight.mm | 33 - .../src/gltf/gltfkit/GLTFMTLBufferAllocator.h | 36 - .../gltf/gltfkit/GLTFMTLBufferAllocator.mm | 101 -- .../src/gltf/gltfkit/GLTFMTLShaderBuilder.h | 40 - .../src/gltf/gltfkit/GLTFMTLShaderBuilder.mm | 246 ---- .../src/gltf/gltfkit/GLTFMTLTextureLoader.h | 35 - .../src/gltf/gltfkit/GLTFMTLTextureLoader.mm | 244 ---- .../src/gltf/gltfkit/GLTFMTLUtilities.h | 56 - .../src/gltf/gltfkit/GLTFMTLUtilities.mm | 291 ---- .../darwin/src/gltf/gltfkit/GLTFMaterial.h | 65 - .../darwin/src/gltf/gltfkit/GLTFMaterial.mm | 35 - platform/darwin/src/gltf/gltfkit/GLTFMesh.h | 43 - platform/darwin/src/gltf/gltfkit/GLTFMesh.mm | 69 - platform/darwin/src/gltf/gltfkit/GLTFNode.h | 49 - platform/darwin/src/gltf/gltfkit/GLTFNode.mm | 171 --- .../darwin/src/gltf/gltfkit/GLTFNodeVisitor.h | 31 - platform/darwin/src/gltf/gltfkit/GLTFObject.h | 45 - .../darwin/src/gltf/gltfkit/GLTFObject.mm | 32 - platform/darwin/src/gltf/gltfkit/GLTFScene.h | 35 - platform/darwin/src/gltf/gltfkit/GLTFScene.mm | 57 - platform/darwin/src/gltf/gltfkit/GLTFSkin.h | 30 - platform/darwin/src/gltf/gltfkit/GLTFSkin.mm | 20 - .../darwin/src/gltf/gltfkit/GLTFTexture.h | 63 - .../darwin/src/gltf/gltfkit/GLTFTexture.mm | 44 - .../src/gltf/gltfkit/GLTFTextureSampler.h | 34 - .../src/gltf/gltfkit/GLTFTextureSampler.mm | 60 - .../darwin/src/gltf/gltfkit/GLTFUtilities.h | 72 - .../darwin/src/gltf/gltfkit/GLTFUtilities.mm | 262 ---- .../src/gltf/gltfkit/GLTFVertexDescriptor.h | 54 - .../src/gltf/gltfkit/GLTFVertexDescriptor.mm | 71 - .../src/gltf/gltfkit/shaders/brdf.metal | 230 --- .../darwin/src/gltf/gltfkit/shaders/hdr.metal | 123 -- .../darwin/src/gltf/gltfkit/shaders/pbr.metal | 463 ------ .../darwin/src/gltf/gltfkit/shaders/pbr.txt | 463 ------ platform/ios/BUILD.bazel | 1 - 84 files changed, 9096 deletions(-) delete mode 100644 platform/darwin/src/gltf/Camera.cpp delete mode 100644 platform/darwin/src/gltf/Camera.hpp delete mode 100644 platform/darwin/src/gltf/GLTFMTLRenderItem.h delete mode 100644 platform/darwin/src/gltf/GLTFMTLRenderItem.mm delete mode 100644 platform/darwin/src/gltf/GLTFManager.hpp delete mode 100644 platform/darwin/src/gltf/GLTFManager.mm delete mode 100644 platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp delete mode 100644 platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.mm delete mode 100644 platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp delete mode 100644 platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.mm delete mode 100644 platform/darwin/src/gltf/GLTFMath.cpp delete mode 100644 platform/darwin/src/gltf/GLTFMath.hpp delete mode 100644 platform/darwin/src/gltf/GLTFModel.cpp delete mode 100644 platform/darwin/src/gltf/GLTFModel.hpp delete mode 100644 platform/darwin/src/gltf/GLTFModelLayer.h delete mode 100644 platform/darwin/src/gltf/GLTFModelLayer.mm delete mode 100644 platform/darwin/src/gltf/GLTFModelLoader.h delete mode 100644 platform/darwin/src/gltf/GLTFModelLoader.mm delete mode 100644 platform/darwin/src/gltf/GLTFRenderer.cpp delete mode 100644 platform/darwin/src/gltf/GLTFRenderer.hpp delete mode 100644 platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm delete mode 100644 platform/darwin/src/gltf/MetalRenderer.hpp delete mode 100644 platform/darwin/src/gltf/MetalRenderer.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFAccessor.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFAccessor.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFAnimation.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFAnimation.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFAsset.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFAsset.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFBuffer.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFBufferAllocator.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFBufferView.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFBufferView.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFCamera.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFCamera.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFEnums.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFImage.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFImage.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFKHRLight.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFKHRLight.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMaterial.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMaterial.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMesh.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFMesh.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFNode.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFNode.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFNodeVisitor.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFObject.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFObject.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFScene.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFScene.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFSkin.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFSkin.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFTexture.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFTexture.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFUtilities.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFUtilities.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.h delete mode 100644 platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.mm delete mode 100644 platform/darwin/src/gltf/gltfkit/shaders/brdf.metal delete mode 100644 platform/darwin/src/gltf/gltfkit/shaders/hdr.metal delete mode 100644 platform/darwin/src/gltf/gltfkit/shaders/pbr.metal delete mode 100644 platform/darwin/src/gltf/gltfkit/shaders/pbr.txt diff --git a/platform/BUILD.bazel b/platform/BUILD.bazel index 84b7e534328b..cd070cb58a08 100644 --- a/platform/BUILD.bazel +++ b/platform/BUILD.bazel @@ -5,8 +5,6 @@ load("//bazel:flags.bzl", "CPP_FLAGS", "MAPLIBRE_FLAGS", "WARNING_FLAGS") objc_library( name = "macos-objcpp", srcs = [ - "//platform/darwin:darwin_gltf_hdrs", - "//platform/darwin:darwin_gltf_srcs", "//platform/darwin:darwin_objcpp_custom_drawable_srcs", "//platform/darwin:darwin_objcpp_srcs", "//platform/darwin:darwin_private_hdrs", @@ -138,7 +136,6 @@ objc_library( objc_library( name = "objc-sdk", srcs = [ - "//platform/darwin:darwin_gltf_srcs", "//platform/darwin:darwin_objc_srcs", "//platform/ios:ios_objc_srcs", "//platform/ios:ios_private_hdrs", @@ -199,7 +196,6 @@ objc_library( objc_library( name = "ios-sdk", hdrs = [ - "//platform/darwin:darwin_gltf_hdrs", "//platform/darwin:darwin_objc_hdrs", "//platform/darwin:generated_style_public_hdrs", "//platform/ios:ios_sdk_hdrs", diff --git a/platform/darwin/BUILD.bazel b/platform/darwin/BUILD.bazel index ae559bd59e05..fb2ae62f57ab 100644 --- a/platform/darwin/BUILD.bazel +++ b/platform/darwin/BUILD.bazel @@ -17,8 +17,6 @@ load( "MLN_GENERATED_DARWIN_STYLE_PUBLIC_HEADERS", "MLN_GENERATED_DARWIN_STYLE_SOURCE", "MLN_GENERATED_DARWIN_TEST_CODE", - "MLN_GLTF_HEADERS", - "MLN_GLTF_SOURCE", ) filegroup( @@ -45,18 +43,6 @@ filegroup( visibility = ["//visibility:public"], ) -filegroup( - name = "darwin_gltf_hdrs", - srcs = MLN_GLTF_HEADERS, - visibility = ["//visibility:public"], -) - -filegroup( - name = "darwin_gltf_srcs", - srcs = MLN_GLTF_SOURCE, - visibility = ["//visibility:public"], -) - filegroup( name = "darwin_objcpp_custom_drawable_srcs", srcs = MLN_DARWIN_PUBLIC_OBJCPP_CUSTOM_DRAWABLE_SOURCE, @@ -330,8 +316,6 @@ exports_files( "include/mbgl/util/image+MLNAdditions.hpp", ] + MLN_DARWIN_PUBLIC_OBJC_SOURCE + MLN_DARWIN_PUBLIC_OBJCPP_SOURCE + - MLN_GLTF_HEADERS + - MLN_GLTF_SOURCE + MLN_DARWIN_PUBLIC_OBJCPP_CUSTOM_DRAWABLE_SOURCE + MLN_DARWIN_PRIVATE_HEADERS + MLN_DARWIN_OBJC_HEADERS + @@ -355,8 +339,6 @@ js_binary( js_library( name = "symbols-to-check", srcs = [ - ":darwin_gltf_hdrs", - ":darwin_gltf_srcs", ":darwin_objc_hdrs", ":darwin_objc_srcs", ":darwin_objcpp_hdrs", diff --git a/platform/darwin/bazel/files.bzl b/platform/darwin/bazel/files.bzl index d643cd4d6000..6bcee77ad0b3 100644 --- a/platform/darwin/bazel/files.bzl +++ b/platform/darwin/bazel/files.bzl @@ -1,85 +1,3 @@ -MLN_GLTF_HEADERS = [ - "src/gltf/GLTFModelLayer.h", -] - -MLN_GLTF_SOURCE = [ - "src/gltf/Camera.hpp", - "src/gltf/Camera.cpp", - "src/gltf/GLTFMath.cpp", - "src/gltf/GLTFMath.hpp", - "src/gltf/GLTFManager.hpp", - "src/gltf/GLTFManager.mm", - "src/gltf/GLTFManagerRenderingEnvironment.hpp", - "src/gltf/GLTFManagerRenderingEnvironment.mm", - "src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp", - "src/gltf/GLTFManagerRenderingEnvironmentMetal.mm", - "src/gltf/GLTFModel.hpp", - "src/gltf/GLTFModel.cpp", - "src/gltf/MetalRenderer.hpp", - "src/gltf/MetalRenderer.mm", - "src/gltf/GLTFModelLayer.h", - "src/gltf/GLTFModelLayer.mm", - "src/gltf/GLTFModelLoader.h", - "src/gltf/GLTFModelLoader.mm", - "src/gltf/GLTFMTLRenderItem.h", - "src/gltf/GLTFMTLRenderItem.mm", - "src/gltf/GLTFRenderer.hpp", - "src/gltf/GLTFRenderer.cpp", - "src/gltf/MetalRenderer+GLTFAsset.mm", - "src/gltf/gltfkit/GLTFAsset.h", - "src/gltf/gltfkit/GLTFAsset.mm", - "src/gltf/gltfkit/GLTFAccessor.h", - "src/gltf/gltfkit/GLTFAccessor.mm", - "src/gltf/gltfkit/GLTFAnimation.h", - "src/gltf/gltfkit/GLTFAnimation.mm", - "src/gltf/gltfkit/GLTFBinaryChunk.h", - "src/gltf/gltfkit/GLTFBinaryChunk.mm", - "src/gltf/gltfkit/GLTFBuffer.h", - "src/gltf/gltfkit/GLTFBufferAllocator.h", - "src/gltf/gltfkit/GLTFBufferView.h", - "src/gltf/gltfkit/GLTFBufferView.mm", - "src/gltf/gltfkit/GLTFCamera.h", - "src/gltf/gltfkit/GLTFCamera.mm", - "src/gltf/gltfkit/GLTFDefaultBufferAllocator.h", - "src/gltf/gltfkit/GLTFDefaultBufferAllocator.mm", - "src/gltf/gltfkit/GLTFEnums.h", - "src/gltf/gltfkit/GLTFExtensionNames.h", - "src/gltf/gltfkit/GLTFExtensionNames.mm", - "src/gltf/gltfkit/GLTFImage.h", - "src/gltf/gltfkit/GLTFImage.mm", - "src/gltf/gltfkit/GLTFKHRLight.h", - "src/gltf/gltfkit/GLTFKHRLight.mm", - "src/gltf/gltfkit/GLTFMaterial.h", - "src/gltf/gltfkit/GLTFMaterial.mm", - "src/gltf/gltfkit/GLTFMesh.h", - "src/gltf/gltfkit/GLTFMesh.mm", - "src/gltf/gltfkit/GLTFMTLBufferAllocator.h", - "src/gltf/gltfkit/GLTFMTLBufferAllocator.mm", - "src/gltf/gltfkit/GLTFMTLShaderBuilder.h", - "src/gltf/gltfkit/GLTFMTLShaderBuilder.mm", - "src/gltf/gltfkit/GLTFMTLTextureLoader.h", - "src/gltf/gltfkit/GLTFMTLTextureLoader.mm", - "src/gltf/gltfkit/GLTFMTLUtilities.h", - "src/gltf/gltfkit/GLTFMTLUtilities.mm", - "src/gltf/gltfkit/GLTFNode.h", - "src/gltf/gltfkit/GLTFNode.mm", - "src/gltf/gltfkit/GLTFNodeVisitor.h", - "src/gltf/gltfkit/GLTFObject.h", - "src/gltf/gltfkit/GLTFObject.mm", - "src/gltf/gltfkit/GLTFScene.h", - "src/gltf/gltfkit/GLTFScene.mm", - "src/gltf/gltfkit/GLTFSkin.h", - "src/gltf/gltfkit/GLTFSkin.mm", - "src/gltf/gltfkit/GLTFTexture.h", - "src/gltf/gltfkit/GLTFTexture.mm", - "src/gltf/gltfkit/GLTFTextureSampler.h", - "src/gltf/gltfkit/GLTFTextureSampler.mm", - "src/gltf/gltfkit/GLTFUtilities.h", - "src/gltf/gltfkit/GLTFUtilities.mm", - "src/gltf/gltfkit/GLTFVertexDescriptor.h", - "src/gltf/gltfkit/GLTFVertexDescriptor.mm", -] - MLN_GENERATED_DARWIN_STYLE_SOURCE = [ "src/MLNLight.mm", "src/MLNBackgroundStyleLayer.mm", diff --git a/platform/darwin/src/MLNPluginLayer.h b/platform/darwin/src/MLNPluginLayer.h index 7f3242a13573..91f3eb98304f 100644 --- a/platform/darwin/src/MLNPluginLayer.h +++ b/platform/darwin/src/MLNPluginLayer.h @@ -101,7 +101,6 @@ typedef struct MLNPluginLayerDrawingContext { MLNMatrix4 projectionMatrix; /// A 4×4 matrix representing the map view’s current near clip projection state. MLNMatrix4 nearClippedProjMatrix; - } MLNPluginLayerDrawingContext; MLN_EXPORT diff --git a/platform/darwin/src/gltf/Camera.cpp b/platform/darwin/src/gltf/Camera.cpp deleted file mode 100644 index 6dc63dced2f3..000000000000 --- a/platform/darwin/src/gltf/Camera.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// Camera.cpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#include "Camera.hpp" -#include "GLTFMath.hpp" - -const float GLTFViewerOrbitCameraDefaultDistance = 2; -const float GLTFViewerOrbitCameraZoomDrag = 0.95; -const float GLTFViewerOrbitCameraRotationDrag = 0.6667; -const float GLTFViewerOrbitCameraZoomSensitivity = 2; - -using namespace maplibre::gltf; - -Camera::Camera() { - _rotationAngles = 0; - _rotationVelocity = 0; - _velocity = 0; - _distance = 4; // 0; // 2; -} - -simd_double4x4 Camera::projectionMatrix() { - float fov = M_PI / 3; // original - fov = 0.6435011087932844; // Constant that i found in ML - simd_double4x4 matrix = GLTFPerspectiveProjectionMatrixAspectFovRH(fov, 1.0, 0.01, 250); - return matrix; -} - -void Camera::updateWithTimestep(double timestep) { - _rotationAngles += _rotationVelocity * timestep; - - static double rot = 0; - // rot += 0.03; - // self.rotationAngles = rot; - // _rotationAngles = simd_make_float3(rot, M_PI/4.0, 0); - _rotationAngles = simd_make_float3(rot, 0, 0); - - // Clamp pitch - _rotationAngles = (simd_float3){ - _rotationAngles.x, static_cast(fmax(-M_PI_2, fmin(_rotationAngles.y, M_PI_2))), 0}; - - _rotationVelocity *= GLTFViewerOrbitCameraRotationDrag; - - // _distance += _velocity * timestep; - _velocity *= GLTFViewerOrbitCameraZoomDrag; - - simd_double4x4 pitchRotation = GLTFRotationMatrixFromAxisAngleD(GLTFAxisXD, -_rotationAngles.y); - simd_double4x4 yawRotation = GLTFRotationMatrixFromAxisAngleD(GLTFAxisYD, -_rotationAngles.x); - simd_double4x4 translation = GLTFMatrixFromTranslationD((simd_double3){0, 0, _distance}); - _viewMatrix = matrix_invert(matrix_multiply(matrix_multiply(yawRotation, pitchRotation), translation)); -} diff --git a/platform/darwin/src/gltf/Camera.hpp b/platform/darwin/src/gltf/Camera.hpp deleted file mode 100644 index 89f760c7e035..000000000000 --- a/platform/darwin/src/gltf/Camera.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// -// Camera.hpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#ifndef Camera_hpp -#define Camera_hpp - -#include -#include - -namespace maplibre { -namespace gltf { - -class Camera { -public: - simd_float3 _rotationAngles; - simd_float3 _rotationVelocity; - double _velocity; - float _distance; - Camera(); - simd_double4x4 projectionMatrix(); - simd_double4x4 _viewMatrix; - void updateWithTimestep(double timestep); -}; - -} // namespace gltf -} // namespace maplibre - -#endif /* Camera_hpp */ diff --git a/platform/darwin/src/gltf/GLTFMTLRenderItem.h b/platform/darwin/src/gltf/GLTFMTLRenderItem.h deleted file mode 100644 index 68b0753b1a67..000000000000 --- a/platform/darwin/src/gltf/GLTFMTLRenderItem.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// GLTFMTLRenderItem.h -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#import -#import "gltfkit/GLTFMesh.h" -#import "gltfkit/GLTFNode.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface GLTFMTLRenderItem : NSObject -@property (nonatomic) NSString *label; -@property (nonatomic) GLTFNode *node; -@property (nonatomic, strong) GLTFSubmesh *submesh; -@property (nonatomic, assign) VertexUniforms vertexUniforms; -@property (nonatomic, assign) FragmentUniforms fragmentUniforms; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/GLTFMTLRenderItem.mm b/platform/darwin/src/gltf/GLTFMTLRenderItem.mm deleted file mode 100644 index 9f7ac94705cf..000000000000 --- a/platform/darwin/src/gltf/GLTFMTLRenderItem.mm +++ /dev/null @@ -1,12 +0,0 @@ -// -// GLTFMTLRenderItem.m -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#import "GLTFMTLRenderItem.h" - -@implementation GLTFMTLRenderItem - -@end diff --git a/platform/darwin/src/gltf/GLTFManager.hpp b/platform/darwin/src/gltf/GLTFManager.hpp deleted file mode 100644 index 9fce472cb1e2..000000000000 --- a/platform/darwin/src/gltf/GLTFManager.hpp +++ /dev/null @@ -1,106 +0,0 @@ -// -// GLTFManager.hpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#ifndef GLTFManager_hpp -#define GLTFManager_hpp - -#include -#include -#include -#include -#include -#include "GLTFRenderer.hpp" -#include "GLTFModel.hpp" -#include "GLTFManagerRenderingEnvironment.hpp" - -namespace maplibre { -namespace gltf { - -// The type of rendering environment we're in -typedef enum { - RenderingEnvironmentUnknown, - RenderingEnvironmentMetal, - RenderingEnvironmentOpenGL, - RenderingEnvironmentVulkan -} RenderingEnvironment; - -struct Coordinate2D { - double _lat; - double _lon; -}; - -struct Cartesian3D { - double _x; - double _y; - double _z; -}; - -typedef std::function ProjectionCallback; - -// The GLTF Manager class is the top level entry point -// for all things model based -class GLTFManager { -public: - // Set the callback - void setProjectionCallback(ProjectionCallback projectionCallback); - - // Instantiate the manager with the appropriate environment - GLTFManager(RenderingEnvironment renderingEnvironment); - - // Load a model - void addModel(std::shared_ptr model); - - // Remove a model - void removeModel(std::shared_ptr model); - - // Current meter to screen pixel scale - double _metersPerPixel = 1.0; - - // Set the drawable size - void setDrawableSize(int width, int height); - - // Set the tilt deg - void setTiltDeg(double tiltDeg); - - // Set the rotation deg - void setRotationDeg(double rotationDeg); - - // Set the rendering environment variables - void setRenderingEnvironmentVariables(std::shared_ptr environmentVars); - - // Update any animations - void updateScene(float timeSinceLastDraw); - - // Render - void render(); - -private: - RenderingEnvironment _renderingEnvironment = RenderingEnvironmentUnknown; - - // List of models - std::vector> _models; - - // Projection callback - ProjectionCallback _projectionCallback; - -private: - // Rendering environment - void createRenderingEnvironment(); - - // The renderer - std::shared_ptr _renderer = nullptr; - - int _drawableWidth = 1; - int _drawableHeight = 1; - double _tiltDeg = 0; - double _rotationDeg = 0; -}; - -} // namespace gltf -} // namespace maplibre - -#endif /* GLTFManager_hpp */ diff --git a/platform/darwin/src/gltf/GLTFManager.mm b/platform/darwin/src/gltf/GLTFManager.mm deleted file mode 100644 index 7a3936a53668..000000000000 --- a/platform/darwin/src/gltf/GLTFManager.mm +++ /dev/null @@ -1,170 +0,0 @@ -// -// GLTFManager.cpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#include "GLTFManager.hpp" -#include "MetalRenderer.hpp" -#include "GLTFManagerRenderingEnvironmentMetal.hpp" -#include - -using namespace maplibre::gltf; - -// Set the callback -void GLTFManager::setProjectionCallback(ProjectionCallback projectionCallback) { - _projectionCallback = projectionCallback; -} - -// Instantiate the manager with the appropriate environment -GLTFManager::GLTFManager(RenderingEnvironment renderingEnvironment) { - _renderingEnvironment = renderingEnvironment; - createRenderingEnvironment(); -} - -// Load a model -void GLTFManager::addModel(std::shared_ptr model) { - - _models.push_back(model); - if (_renderer != nullptr) { - _renderer->loadGLTFModel(model); - } - - - -} - -// Remove a model -void GLTFManager::removeModel(std::shared_ptr model) { - - _models.erase(std::find(_models.begin(), _models.end(), model)); - -} - -// Set the drawable size -void GLTFManager::setDrawableSize(int width, int height) { - - _drawableWidth = width; - _drawableHeight = height; - - if (_renderer != nullptr) { - _renderer->setDrawableSize(_drawableWidth, _drawableHeight); - } - -} - - -// Set the tilt deg -void GLTFManager::setTiltDeg(double tiltDeg) { - - _tiltDeg = tiltDeg; - if (_renderer != nullptr) { - _renderer->setTiltDeg(_tiltDeg); - } - -} - - -// Set the rotation deg -void GLTFManager::setRotationDeg(double rotationDeg) { - - _rotationDeg = rotationDeg; - if (_renderer != nullptr) { - _renderer->setRotationDeg(_rotationDeg); - } -} - - - -// Set the rendering environment variables -void GLTFManager::setRenderingEnvironmentVariables(std::shared_ptr environmentVars) { - - if (_renderingEnvironment == RenderingEnvironmentMetal) { - - if (_renderer != nullptr) { - - // Set metal specific stuff - auto mr = std::static_pointer_cast(_renderer); - auto mevars = std::static_pointer_cast(environmentVars); - mr->setMetalDevice(mevars->_metalDevice); - //mr->setCurrentDrawable(mevars->_currentDrawable); - //mr->setCurrentOutputRenderPassDescriptor(mevars->_currentRenderPassDescriptor); - - // TODO: Add depth buffer variable management - - // TODO: Add bloom pass toggle - mr->setUseBloomPass(mevars->_useBloomPass); - - // TODO: Remove all the above and use this instead - mr->setRenderingEnvironemnt(environmentVars); - - - } - - } - -} - - -// Update any animations -void GLTFManager::updateScene(float timeSinceLastDraw) { - if (_renderer == nullptr) { - return; - } - - // Go through all the models and project them. This is a - // hack right now to try and sync the models with the scene - if (_projectionCallback != nullptr) { - - for (auto m: _models) { - Coordinate2D c; - c._lat = m->_referenceLat; - c._lon = m->_referenceLon; - - - - auto cartesian = _projectionCallback(c); - m->_xLateX = cartesian._x; - m->_xLateY = cartesian._y; - m->_xLateZ = cartesian._z; - - } - - } - - - _renderer->setMetersPerPixel(_metersPerPixel); - _renderer->update(timeSinceLastDraw); -} - -// Render -void GLTFManager::render() { - if (_renderer == nullptr) { - return; - } - _renderer->render(); -} - - - -void GLTFManager::createRenderingEnvironment() { - - if (_renderingEnvironment == RenderingEnvironmentMetal) { - - // Create the renderer - _renderer = std::make_shared(); - - // Set the drawable size - _renderer->setDrawableSize(_drawableWidth, _drawableHeight); - - // Set the initial tilt deg - _renderer->setTiltDeg(_tiltDeg); - - // Set metal specific stuff - auto mr = std::static_pointer_cast(_renderer); - - - } - -} diff --git a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp deleted file mode 100644 index 1e37c11260ce..000000000000 --- a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// GLTFManagerRenderingEnvironment.hpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#ifndef GLTFManagerRenderingEnvironment_hpp -#define GLTFManagerRenderingEnvironment_hpp - -#include -#include - -namespace maplibre { -namespace gltf { - -// Bsae class does nothing really, just a place holder -class GLTFManagerRenderingEnvironment { -public: - // If the bloom should be used - bool _useBloomPass = false; - - // FOV - double _currentFOVDEG = 50; - - // Environment projection matrix - simd_double4x4 _currentProjectionMatrix; - - // Current zoom level - double _currentZoomLevel = 1; - - // - simd_float3 _lightDirection; - - GLTFManagerRenderingEnvironment() { _lightDirection = simd_make_float3(0.0, 10000.0, 10000.0); } -}; - -} // namespace gltf -} // namespace maplibre -#endif /* GLTFManagerRenderingEnvironment_hpp */ diff --git a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.mm b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.mm deleted file mode 100644 index c372f7608b8d..000000000000 --- a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironment.mm +++ /dev/null @@ -1,8 +0,0 @@ -// -// GLTFManagerRenderingEnvironment.cpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#include "GLTFManagerRenderingEnvironment.hpp" diff --git a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp deleted file mode 100644 index b64b422bf6bd..000000000000 --- a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// -// GLTFManagerRenderingEnvironmentMetal.hpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#ifndef GLTFManagerRenderingEnvironmentMetal_hpp -#define GLTFManagerRenderingEnvironmentMetal_hpp - -#include -#include -#include -#include "GLTFManagerRenderingEnvironment.hpp" - -namespace maplibre { -namespace gltf { - -// Bsae class does nothing really, just a place holder -class GLTFManagerRenderingEnvironmentMetal : public GLTFManagerRenderingEnvironment { -public: - // Allows command buffer and render encoder to be passed in. - // if these are nil, then the renderer will create them - id _currentCommandEncoder = nullptr; - id _currentCommandBuffer = nullptr; - - id _currentDrawable = nullptr; - MTLRenderPassDescriptor *_currentRenderPassDescriptor = nullptr; - id _metalDevice = nullptr; - - // TBD: These are placeholders as we noodle how to integrate with ML - // Depth descriptor: If this is null, then use an internal depth - id _depthStencilTexture = nullptr; - - id _colorTexture = nullptr; -}; - -} // namespace gltf -} // namespace maplibre - -#endif /* GLTFManagerRenderingEnvironmentMetal_hpp */ diff --git a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.mm b/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.mm deleted file mode 100644 index fd35693ae6bb..000000000000 --- a/platform/darwin/src/gltf/GLTFManagerRenderingEnvironmentMetal.mm +++ /dev/null @@ -1,8 +0,0 @@ -// -// GLTFManagerRenderingEnvironmentMetal.cpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#include "GLTFManagerRenderingEnvironmentMetal.hpp" diff --git a/platform/darwin/src/gltf/GLTFMath.cpp b/platform/darwin/src/gltf/GLTFMath.cpp deleted file mode 100644 index 8a067505ef5d..000000000000 --- a/platform/darwin/src/gltf/GLTFMath.cpp +++ /dev/null @@ -1,192 +0,0 @@ -// -// Math.cpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#include "GLTFMath.hpp" - -simd_float4x4 GLTFMatrixFromScale(const simd_float3 s) { - simd_float4x4 m = matrix_identity_float4x4; - m.columns[0].x = s.x; - m.columns[1].y = s.y; - m.columns[2].z = s.z; - return m; -} - -simd_double4x4 GLTFMatrixFromScaleD(const simd_double3 s) { - simd_double4x4 m = matrix_identity_double4x4; - m.columns[0].x = s.x; - m.columns[1].y = s.y; - m.columns[2].z = s.z; - return m; -} - -simd_float4x4 GLTFMatrixFromUniformScale(float s) { - simd_float4x4 m = matrix_identity_float4x4; - m.columns[0].x = s; - m.columns[1].y = s; - m.columns[2].z = s; - return m; -} - -simd_double4x4 GLTFMatrixFromUniformScaleD(double s) { - simd_double4x4 m = matrix_identity_double4x4; - m.columns[0].x = s; - m.columns[1].y = s; - m.columns[2].z = s; - return m; -} - -simd_double4x4 GLTFMatrixFromTranslationD(simd_double3 t) { - simd_double4x4 m = matrix_identity_double4x4; - m.columns[3] = (simd_double4){t.x, t.y, t.z, 1.0}; - return m; -} - -simd_float4x4 GLTFMatrixFromTranslation(simd_float3 t) { - simd_float4x4 m = matrix_identity_float4x4; - m.columns[3] = (simd_float4){t.x, t.y, t.z, 1.0}; - return m; -} - -GLTFBoundingSphere GLTFBoundingSphereFromBox(const GLTFBoundingBox b) { - GLTFBoundingSphere s; - double midX = (b.maxPoint.x + b.minPoint.x) * 0.5; - double midY = (b.maxPoint.y + b.minPoint.y) * 0.5; - double midZ = (b.maxPoint.z + b.minPoint.z) * 0.5; - - double r = sqrt(pow(b.maxPoint.x - midX, 2) + pow(b.maxPoint.y - midY, 2) + pow(b.maxPoint.z - midZ, 2)); - - s.center = (simd_double3){midX, midY, midZ}; - s.radius = r; - return s; -} - -simd_float4x4 GLTFRotationMatrixFromAxisAngle(simd_float3 axis, float angle) { - float x = axis.x, y = axis.y, z = axis.z; - float c = cosf(angle); - float s = sinf(angle); - float t = 1 - c; - - simd_float4 c0 = {t * x * x + c, t * x * y + z * s, t * x * z - y * s, 0}; - simd_float4 c1 = {t * x * y - z * s, t * y * y + c, t * y * z + x * s, 0}; - simd_float4 c2 = {t * x * z + y * s, t * y * z - x * s, t * z * z + c, 0}; - simd_float4 c3 = {0, 0, 0, 1}; - - return (simd_float4x4){c0, c1, c2, c3}; -} - -simd_double4x4 GLTFRotationMatrixFromAxisAngleD(simd_double3 axis, double angle) { - double x = axis.x, y = axis.y, z = axis.z; - double c = cos(angle); - double s = sin(angle); - double t = 1 - c; - - simd_double4 c0 = {t * x * x + c, t * x * y + z * s, t * x * z - y * s, 0}; - simd_double4 c1 = {t * x * y - z * s, t * y * y + c, t * y * z + x * s, 0}; - simd_double4 c2 = {t * x * z + y * s, t * y * z - x * s, t * z * z + c, 0}; - simd_double4 c3 = {0, 0, 0, 1}; - - return (simd_double4x4){c0, c1, c2, c3}; -} - -simd_float3 GLTFAxisX = (simd_float3){1, 0, 0}; -simd_float3 GLTFAxisY = (simd_float3){0, 1, 0}; -simd_float3 GLTFAxisZ = (simd_float3){0, 0, 1}; - -simd_double3 GLTFAxisXD = (simd_double3){1, 0, 0}; -simd_double3 GLTFAxisYD = (simd_double3){0, 1, 0}; -simd_double3 GLTFAxisZD = (simd_double3){0, 0, 1}; - -simd_double4x4 GLTFPerspectiveProjectionMatrixAspectFovRH(const double fovY, - const double aspect, - const double nearZ, - const double farZ) { - double yscale = 1 / tanf(fovY * 0.5f); // 1 / tan == cot - double xscale = yscale / aspect; - double q = -farZ / (farZ - nearZ); - - simd_double4x4 m = {.columns[0] = {xscale, 0, 0, 0}, - .columns[1] = {0, yscale, 0, 0}, - .columns[2] = {0, 0, q, -1}, - .columns[3] = {0, 0, q * nearZ, 0}}; - - return m; -} - -simd_float4x4 GLTFOrthoProjectionMatrix( - const float left, const float right, const float bottom, const float top, const float nearZ, const float farZ) { - simd_float4x4 m = { - .columns[0] = {2 / (right - left), 0, 0, 0}, - .columns[1] = {0, 2 / (top - bottom), 0, 0}, - .columns[2] = {0, 0, 1 / (farZ - nearZ), 0}, - .columns[3] = {(left + right) / (left - right), (top + bottom) / (bottom - top), nearZ / (nearZ - farZ), 1}}; - - return m; -} - -simd_float3x3 GLTFMatrixUpperLeft3x3(simd_float4x4 m) { - simd_float3x3 mout = {{{m.columns[0][0], m.columns[0][1], m.columns[0][2]}, - {m.columns[1][0], m.columns[1][1], m.columns[1][2]}, - {m.columns[2][0], m.columns[2][1], m.columns[2][2]}}}; - return mout; -} - -simd_double3x3 GLTFMatrixUpperLeft3x3D(simd_double4x4 m) { - simd_double3x3 mout = {{{m.columns[0][0], m.columns[0][1], m.columns[0][2]}, - {m.columns[1][0], m.columns[1][1], m.columns[1][2]}, - {m.columns[2][0], m.columns[2][1], m.columns[2][2]}}}; - return mout; -} - -GLTFTextureTransform GLTFTextureTransformMakeIdentity(void) { - GLTFTextureTransform t = { - .offset = (simd_float2){0, 0}, - .scale = (simd_float2){1, 1}, - .rotation = 0, - }; - return t; -} - -GLTFTextureTransform GLTFTextureTransformMakeSRT(simd_float2 scale, float rotation, simd_float2 offset) { - GLTFTextureTransform t = { - .offset = offset, - .scale = scale, - .rotation = rotation, - }; - return t; -} - -simd_float3x3 GLTFTextureMatrixFromTransform(GLTFTextureTransform transform) { - float rs = sinf(-transform.rotation); - float rc = cosf(-transform.rotation); - float tx = transform.offset.x; - float ty = transform.offset.y; - float sx = transform.scale.x; - float sy = transform.scale.y; - simd_float3 c0 = (simd_float3){rc * sx, rs * sy, 0}; - simd_float3 c1 = (simd_float3){-rs * sx, rc * sy, 0}; - simd_float3 c2 = (simd_float3){tx, ty, 1}; - simd_float3x3 m = (simd_float3x3){c0, c1, c2}; - return m; -} - -simd_float4x4 GLTFNormalMatrixFromModelMatrix(simd_float4x4 m) { - simd_float3x3 nm = simd_inverse(simd_transpose(GLTFMatrixUpperLeft3x3(m))); - simd_float4x4 mout = {{{nm.columns[0][0], nm.columns[0][1], nm.columns[0][2], 0}, - {nm.columns[1][0], nm.columns[1][1], nm.columns[1][2], 0}, - {nm.columns[2][0], nm.columns[2][1], nm.columns[2][2], 0}, - {0, 0, 0, 1}}}; - return mout; -} - -simd_double4x4 GLTFNormalMatrixFromModelMatrixD(simd_double4x4 m) { - simd_double3x3 nm = simd_inverse(simd_transpose(GLTFMatrixUpperLeft3x3D(m))); - simd_double4x4 mout = {{{nm.columns[0][0], nm.columns[0][1], nm.columns[0][2], 0}, - {nm.columns[1][0], nm.columns[1][1], nm.columns[1][2], 0}, - {nm.columns[2][0], nm.columns[2][1], nm.columns[2][2], 0}, - {0, 0, 0, 1}}}; - return mout; -} diff --git a/platform/darwin/src/gltf/GLTFMath.hpp b/platform/darwin/src/gltf/GLTFMath.hpp deleted file mode 100644 index 6e8ce7a4f397..000000000000 --- a/platform/darwin/src/gltf/GLTFMath.hpp +++ /dev/null @@ -1,139 +0,0 @@ -// -// Math.hpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#ifndef Math_hpp -#define Math_hpp - -#include -#include - -typedef enum { - GLTFTextureBindIndexBaseColor, - GLTFTextureBindIndexNormal, - GLTFTextureBindIndexMetallicRoughness, - GLTFTextureBindIndexOcclusion, - GLTFTextureBindIndexEmissive, - GLTFTextureBindIndexDiffuseEnvironment, - GLTFTextureBindIndexSpecularEnvironment, - GLTFTextureBindIndexBRDFLookup, -} GLTFMTLTextureBindIndex; - -#define DEG_RAD (M_PI / 180.0) -#define RAD_DEG (180.0 / M_PI) - -// 0.0174533 -// 57.2958 - -#define GLTFMTLMaximumLightCount 3 -#define GLTFMTLMaximumTextureCount (GLTFTextureBindIndexEmissive + 1) - -typedef struct { - simd_float3 minPoint; - simd_float3 maxPoint; -} GLTFBoundingBox; - -typedef struct { - simd_double3 center; - float radius; -} GLTFBoundingSphere; - -typedef struct { - simd_float4x4 modelMatrix; - simd_float4x4 modelViewProjectionMatrix; - simd_float4x4 normalMatrix; - float scaleFactor; - float brightness; - simd_float3 lightDirection; -} VertexUniforms; - -typedef struct { - simd_float4 position; - simd_float4 color; - float intensity; - float innerConeAngle; - float outerConeAngle; - float range; - simd_float4 spotDirection; -} Light; - -typedef struct { - float normalScale; - simd_float3 emissiveFactor; - float occlusionStrength; - simd_float2 metallicRoughnessValues; - simd_float4 baseColorFactor; - simd_float3 camera; - float alphaCutoff; - float envIntensity; - Light ambientLight; - Light lights[GLTFMTLMaximumLightCount]; - simd_float3x3 textureMatrices[GLTFMTLMaximumTextureCount]; -} FragmentUniforms; - -typedef struct { - simd_float2 offset; - simd_float2 scale; - float rotation; -} GLTFTextureTransform; - -#ifdef __cplusplus -extern "C" { -#endif - -extern simd_float3 GLTFAxisX; -extern simd_float3 GLTFAxisY; -extern simd_float3 GLTFAxisZ; - -extern simd_double3 GLTFAxisXD; -extern simd_double3 GLTFAxisYD; -extern simd_double3 GLTFAxisZD; - -simd_float4x4 GLTFMatrixFromScale(const simd_float3 s); - -simd_double4x4 GLTFMatrixFromScaleD(const simd_double3 s); - -simd_float4x4 GLTFMatrixFromUniformScale(float s); - -simd_double4x4 GLTFMatrixFromUniformScaleD(double s); - -GLTFBoundingSphere GLTFBoundingSphereFromBox(GLTFBoundingBox b); - -simd_float4x4 GLTFMatrixFromTranslation(simd_float3 t); - -simd_double4x4 GLTFMatrixFromTranslationD(simd_double3 t); - -simd_float4x4 GLTFRotationMatrixFromAxisAngle(simd_float3 axis, float angle); - -simd_double4x4 GLTFRotationMatrixFromAxisAngleD(simd_double3 axis, double angle); - -simd_double4x4 GLTFPerspectiveProjectionMatrixAspectFovRH(const double fovY, - const double aspect, - const double nearZ, - const double farZ); - -simd_float4x4 GLTFOrthoProjectionMatrix( - const float left, const float right, const float bottom, const float top, const float nearZ, const float farZ); - -simd_float3x3 GLTFMatrixUpperLeft3x3(simd_float4x4 m); - -simd_double3x3 GLTFMatrixUpperLeft3x3D(simd_double4x4 m); - -GLTFTextureTransform GLTFTextureTransformMakeIdentity(void); - -GLTFTextureTransform GLTFTextureTransformMakeSRT(simd_float2 scale, float rotation, simd_float2 offset); - -simd_float3x3 GLTFTextureMatrixFromTransform(GLTFTextureTransform transform); - -simd_float4x4 GLTFNormalMatrixFromModelMatrix(simd_float4x4 m); - -simd_double4x4 GLTFNormalMatrixFromModelMatrixD(simd_double4x4 m); - -#ifdef __cplusplus -} -#endif - -#endif /* Math_hpp */ diff --git a/platform/darwin/src/gltf/GLTFModel.cpp b/platform/darwin/src/gltf/GLTFModel.cpp deleted file mode 100644 index 4d97152eff71..000000000000 --- a/platform/darwin/src/gltf/GLTFModel.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// -// GLTFModel.cpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#include "GLTFModel.hpp" diff --git a/platform/darwin/src/gltf/GLTFModel.hpp b/platform/darwin/src/gltf/GLTFModel.hpp deleted file mode 100644 index 174b7dd91ee3..000000000000 --- a/platform/darwin/src/gltf/GLTFModel.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// GLTFModel.hpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#ifndef GLTFModel_hpp -#define GLTFModel_hpp - -#include -#include - -namespace maplibre { -namespace gltf { - -// Model -class GLTFModel { -public: - // - double _referenceLat = 0; - double _referenceLon = 0; - - // What it takes to scale this model to meters units - float _scaleFactor = 1; - - // Rotation around the reference point - float _rotationDeg = 0; - - // The URL for the model, used by the loader - std::string _modelURL; - - // The brightness - float _brightness = 1.0; - - // This is a hack to deal with passing in the translation vector. - // NEed to reconcile this with the renderable model's version of it - double _xLateX = 0; - double _xLateY = 0; - double _xLateZ = 0; -}; - -} // namespace gltf -} // namespace maplibre - -#endif /* GLTFModel_hpp */ diff --git a/platform/darwin/src/gltf/GLTFModelLayer.h b/platform/darwin/src/gltf/GLTFModelLayer.h deleted file mode 100644 index 640f37355659..000000000000 --- a/platform/darwin/src/gltf/GLTFModelLayer.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// CustomLayerTest.h -// MapLibreTest -// -// Created by Malcolm Toon on 11/7/24. -// - -#import "MLNCustomStyleLayer.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface GLTFModelLayer : MLNCustomStyleLayer - -// This sets the relative light position for all the models being rendered -// The light position is in meters from the origin of the model. -- (void)setLightPositionX:(float)x y:(float)y z:(float)z; - -- (void)loadModelFromJSON:(NSString *)modelMetadataFilename; - -- (void)loadModel:(NSString *)appResourceFilename - lat:(double)lat - lon:(double)lon - rotationDeg:(double)rotationDeg - scaleFactor:(float)scaleFactor - brightness:(float)brightness; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/GLTFModelLayer.mm b/platform/darwin/src/gltf/GLTFModelLayer.mm deleted file mode 100644 index b71972d27d46..000000000000 --- a/platform/darwin/src/gltf/GLTFModelLayer.mm +++ /dev/null @@ -1,357 +0,0 @@ -// -// CustomLayerTest.m -// MapLibreTest -// -// Created by Malcolm Toon on 11/6/24. -// - -#import "GLTFModelLayer.h" -#import -#import "MLNBackendResource.h" -#import "MLNMapView.h" -#include -#import "GLTFManagerRenderingEnvironmentMetal.hpp" -#import "GLTFManager.hpp" -#import "GLTFMath.hpp" - -using namespace maplibre::gltf; - -// This is here to hold the metadata about the model if load is called before -// the layer is created -@interface GLTFModelMetadata : NSObject -@property NSString *modelPath; -@property CLLocationCoordinate2D modelCoordinate; -@property double modelRotation; -@property BOOL modelLoaded; -@property float modelScale; -@property float brightness; - -@end - -@implementation GLTFModelMetadata --(id)init { - if (self = [super init]) { - self.brightness = 1.0; - } - return self; -} -@end - -@interface GLTFModelLayer () { - std::shared_ptr _metalEnvironment; - std::shared_ptr _manager; - -} - -@property NSMutableArray *models; -@property BOOL managerCreated; - -// Would be nice to change this to a vec3 or something similar at some point -@property BOOL lightSet; -@property float lightX; -@property float lightY; -@property float lightZ; - - -@end - -simd_float4x4 toSimdMatrix4F(const MLNMatrix4 & mlMatrix) { - simd_float4x4 tempResult; - - /* - typedef struct MLNMatrix4 { - double m00, m01, m02, m03; - double m10, m11, m12, m13; - double m20, m21, m22, m23; - double m30, m31, m32, m33; - } MLNMatrix4; -*/ - - tempResult.columns[0][0] = mlMatrix.m00; - tempResult.columns[0][1] = mlMatrix.m01; - tempResult.columns[0][2] = mlMatrix.m02; - tempResult.columns[0][3] = mlMatrix.m03; - tempResult.columns[1][0] = mlMatrix.m10; - tempResult.columns[1][1] = mlMatrix.m11; - tempResult.columns[1][2] = mlMatrix.m12; - tempResult.columns[1][3] = mlMatrix.m13; - tempResult.columns[2][0] = mlMatrix.m20; - tempResult.columns[2][1] = mlMatrix.m21; - tempResult.columns[2][2] = mlMatrix.m22; - tempResult.columns[2][3] = mlMatrix.m23; - tempResult.columns[3][0] = mlMatrix.m30; - tempResult.columns[3][1] = mlMatrix.m31; - tempResult.columns[3][2] = mlMatrix.m32; - tempResult.columns[3][3] = mlMatrix.m33; - - - return tempResult; -} - - - -simd_double4x4 toSimdMatrix4D(const MLNMatrix4 & mlMatrix) { - simd_double4x4 tempResult; - - /* - typedef struct MLNMatrix4 { - double m00, m01, m02, m03; - double m10, m11, m12, m13; - double m20, m21, m22, m23; - double m30, m31, m32, m33; - } MLNMatrix4; -*/ - - tempResult.columns[0][0] = mlMatrix.m00; - tempResult.columns[0][1] = mlMatrix.m01; - tempResult.columns[0][2] = mlMatrix.m02; - tempResult.columns[0][3] = mlMatrix.m03; - tempResult.columns[1][0] = mlMatrix.m10; - tempResult.columns[1][1] = mlMatrix.m11; - tempResult.columns[1][2] = mlMatrix.m12; - tempResult.columns[1][3] = mlMatrix.m13; - tempResult.columns[2][0] = mlMatrix.m20; - tempResult.columns[2][1] = mlMatrix.m21; - tempResult.columns[2][2] = mlMatrix.m22; - tempResult.columns[2][3] = mlMatrix.m23; - tempResult.columns[3][0] = mlMatrix.m30; - tempResult.columns[3][1] = mlMatrix.m31; - tempResult.columns[3][2] = mlMatrix.m32; - tempResult.columns[3][3] = mlMatrix.m33; - - - return tempResult; -} - -@implementation GLTFModelLayer { - // The render pipeline state - id _pipelineState; - id _depthStencilStateWithoutStencil; -} - --(id)initWithIdentifier:(NSString *)identifier { - if (self = [super initWithIdentifier:identifier]) { - self.models = [NSMutableArray array]; - } - return self; -} - -- (void)didMoveToMapView:(MLNMapView *)mapView { - -} - -// This sets the relative light position for all the models being rendered -// The light position is in meters from the origin of the model. --(void)setLightPositionX:(float)x y:(float)y z:(float)z { - - self.lightSet = YES; - self.lightX = x; - self.lightY = y; - self.lightZ = z; - - if (_metalEnvironment != nullptr) { - _metalEnvironment->_lightDirection = simd_make_float3(_lightX, _lightY, _lightZ); - } - -} - - --(void)loadModels { - - // This goes through the model array and loads whatever hasn't been loaded already - for (GLTFModelMetadata *m in self.models) { - [self addModel:m]; - } - - /* - @{@"modelURL":@"al_awwal_v02.glb",@"lat":@(24.729326775575686),@"lon":@(46.623841518553355),@"rot":@(0)}, - @{@"modelURL":@"alawwalpark-03.glb",@"lat":@(24.729326775575686),@"lon":@(46.623841518553355),@"rot":@(0)}, - @{@"modelURL":@"Al_faisaliyah_005.glb",@"lat":@(24.69052042910012),@"lon":@(46.6856124145449),@"rot":@(0)}, - @{@"modelURL":@"Al_faisaliyah_007.glb",@"lat":@(24.69052042910012),@"lon":@(46.6856124145449),@"rot":@(0)}, - @{@"modelURL":@"alnajdoul_004.glb",@"lat":@(24.739367517042293),@"lon":@(46.65956858776968),@"rot":@(0)}, - @{@"modelURL":@"masmak_010-bl.glb",@"lat":@(24.63125410132941),@"lon":@(46.713372982335976),@"rot":@(0)}, - @{@"modelURL":@"turaif-03-bl.glb",@"lat":@(24.733690223733547),@"lon":@(46.57492745287205),@"rot":@(0)}, - @{@"modelURL":@"tvtower_009.glb",@"lat":@(24.643391710253425),@"lon":@(46.69595652756665),@"rot":@(0)}, -*/ - - //[self loadModel:@"alawwalpark-03.glb" lat:24.729326775575686 lon:46.623841518553355 rotationDeg:90]; - /* - [self loadModel:@"Al_faisaliyah_007.glb" lat:24.69052042910012 lon:46.6856124145449 rotationDeg:-65]; - [self loadModel:@"alnajdoul_004.glb" lat:24.739367517042293 lon:46.65956858776968 rotationDeg:25]; - [self loadModel:@"masmak_010-bl.glb" lat:24.63125410132941 lon:46.713372982335976 rotationDeg:0]; - [self loadModel:@"turaif-03-bl.glb" lat:24.733690223733547 lon:46.57492745287205 rotationDeg:0]; - [self loadModel:@"tvtower_009.glb" lat:24.643391710253425 lon:46.69595652756665 rotationDeg:0]; - - - [self loadModel:@"KAFD_Building01_v01.glb" lat:24.76592011755998 lon:46.64337787824368 rotationDeg:0]; - [self loadModel:@"KAFD_Building02_v01.glb" lat:24.76592011755998 lon:46.64337787824368 rotationDeg:0]; - [self loadModel:@"KAFD_Building06_v02.glb" lat:24.76592011755998 lon:46.64337787824368 rotationDeg:0]; - [self loadModel:@"KAFD_Building07_v01.glb" lat:24.76592011755998 lon:46.64337787824368 rotationDeg:0]; - [self loadModel:@"KAFD_Building09_v01.glb" lat:24.76592011755998 lon:46.64337787824368 rotationDeg:0]; -*/ - -} - --(void)loadModelFromJSON:(NSString *)modelMetadataFilename { - - NSError *error = nil; - NSData *dat = [NSData dataWithContentsOfFile:modelMetadataFilename]; - NSDictionary *d = [NSJSONSerialization JSONObjectWithData:dat - options:0 - error:&error]; - NSArray *models = [d objectForKey:@"models"]; - for (NSDictionary *model in models) { - - NSString *modelFilename = [model objectForKey:@"name"]; - double lat = [[model objectForKey:@"lat"] doubleValue]; - double lon = [[model objectForKey:@"lon"] doubleValue]; - double rot = [[model objectForKey:@"rot"] doubleValue]; - double scale = [[model objectForKey:@"scale_factor"] doubleValue]; - double brightnessCoefficient = [[model objectForKey:@"brightness"] doubleValue]; - if (brightnessCoefficient == 0) { - brightnessCoefficient = 1.0; - } - //NSString *bundleFilename = [[NSBundle mainBundle] pathForResource:modelFilename ofType:nil]; - [self loadModel:modelFilename - lat:lat - lon:lon - rotationDeg:rot - scaleFactor:scale - brightness:brightnessCoefficient]; - } - -} - - --(void)loadModel:(NSString *)appResourceFilename - lat:(double)lat - lon:(double)lon - rotationDeg:(double)rotationDeg - scaleFactor:(float)scaleFactor - brightness:(float)brightness { - - if (brightness == 0) { - brightness = 1.0; - } - - GLTFModelMetadata *modelMetadata = [[GLTFModelMetadata alloc] init]; - modelMetadata.modelPath = appResourceFilename; - modelMetadata.modelCoordinate = CLLocationCoordinate2DMake(lat, lon); - modelMetadata.modelRotation = -rotationDeg; - modelMetadata.modelScale = scaleFactor; - modelMetadata.brightness = brightness; - - [self.models addObject:modelMetadata]; - - if (self.managerCreated) { - [self addModel:modelMetadata]; - } - -} - - - --(void)addModel:(GLTFModelMetadata *)modelMetadata { - - if (modelMetadata.modelLoaded) { - return; - } - - NSURL *fileURL = [[NSBundle mainBundle] URLForResource:modelMetadata.modelPath withExtension:nil]; - - std::string modelURL = [[fileURL absoluteString] UTF8String]; - - std::shared_ptr model = std::make_shared(); - model->_referenceLat = modelMetadata.modelCoordinate.latitude; - model->_referenceLon = modelMetadata.modelCoordinate.longitude; - model->_modelURL = modelURL; - model->_rotationDeg = modelMetadata.modelRotation; - model->_brightness = modelMetadata.brightness; - model->_scaleFactor = modelMetadata.modelScale; -// model->_scaleFactor = 1.0; // Models are in meters - - _manager->addModel(model); - - modelMetadata.modelLoaded = YES; - -} - - -- (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingContext)context { - - MLNBackendResource* resource = [mapView backendResource]; - - bool loadModels = false; - - if (_manager == nullptr) { - - // Setup the metal environment for the model rendering - _metalEnvironment = std::make_shared(); - - if (self.lightSet) { - _metalEnvironment->_lightDirection = simd_make_float3(_lightX, _lightY, _lightZ); - } - - // Create the GLTF Manager - _manager = std::make_shared(RenderingEnvironmentMetal); - _manager->setRenderingEnvironmentVariables(_metalEnvironment); - - _manager->setProjectionCallback(^Cartesian3D(const Coordinate2D & coordinate){ - Cartesian3D tempResult; - - tempResult._x = 5198170.102753558; - tempResult._y = 2832006.4886368043; - tempResult._z = 0; - - tempResult._x = coordinate._lon * DEG_RAD; - double lat = coordinate._lat * DEG_RAD; - tempResult._y = log((1.0f+sin(lat))/cos(lat)); - - double metersScale = 20037508.34; - tempResult._x = tempResult._x * metersScale / M_PI; - tempResult._y = tempResult._y * metersScale / M_PI; - return tempResult; - }); - - loadModels = true; - } - - _metalEnvironment->_currentFOVDEG = context.fieldOfView * RAD_DEG; - _metalEnvironment->_currentProjectionMatrix = toSimdMatrix4D(context.nearClippedProjMatrix); - _metalEnvironment->_currentZoomLevel = context.zoomLevel; - _metalEnvironment->_currentCommandEncoder = self.renderEncoder; - _metalEnvironment->_currentCommandBuffer = resource.commandBuffer; - _metalEnvironment->_metalDevice = resource.mtkView.device; - _metalEnvironment->_currentDrawable = resource.mtkView.currentDrawable; - _metalEnvironment->_currentRenderPassDescriptor = resource.mtkView.currentRenderPassDescriptor; - _metalEnvironment->_depthStencilTexture = resource.mtkView.currentRenderPassDescriptor.depthAttachment.texture; - _metalEnvironment->_colorTexture = resource.mtkView.currentRenderPassDescriptor.colorAttachments[0].texture; - - if (self.lightSet) { - _metalEnvironment->_lightDirection = simd_make_float3(_lightX, _lightY, _lightZ); - } - - // TODO: Remove this.. This is legacy - _manager->setRenderingEnvironmentVariables(_metalEnvironment); - - if (loadModels) { - [self loadModels]; - } - - vector_uint2 _viewportSize; - _viewportSize.x = resource.mtkView.drawableSize.width; - _viewportSize.y = resource.mtkView.drawableSize.height; - _manager->setDrawableSize(_viewportSize.x, _viewportSize.y); - - float timestep = (1 / 60.0f); - _manager->updateScene(timestep); - - // Render the image - _manager->render(); -} - -- (void)willMoveFromMapView:(MLNMapView *)mapView { - // Clean up -} - -@end diff --git a/platform/darwin/src/gltf/GLTFModelLoader.h b/platform/darwin/src/gltf/GLTFModelLoader.h deleted file mode 100644 index d1e3ab9d7874..000000000000 --- a/platform/darwin/src/gltf/GLTFModelLoader.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// GLTFModelLoader.h -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#import -#import "gltfkit/GLTFAsset.h" - -NS_ASSUME_NONNULL_BEGIN - -typedef void (^GLTFModelLoaderCompletionHandler)(GLTFAsset *asset); - -@interface GLTFModelLoader : NSObject - -- (void)loadURL:(NSURL *)assetURL - withCompletionHandler:(GLTFModelLoaderCompletionHandler)completionHandler - bufferAllocator:(id)bufferAllocator; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/GLTFModelLoader.mm b/platform/darwin/src/gltf/GLTFModelLoader.mm deleted file mode 100644 index 66aeba4ec862..000000000000 --- a/platform/darwin/src/gltf/GLTFModelLoader.mm +++ /dev/null @@ -1,74 +0,0 @@ -// -// GLTFModelLoader.m -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/25/24. -// - -#import "GLTFModelLoader.h" -#import "gltfkit/GLTFAsset.h" -#import "gltfkit/GLTFMTLBufferAllocator.h" - -@interface GLTFModelLoader () { - -} - -@property GLTFModelLoaderCompletionHandler completionHandler; - -@end - -@implementation GLTFModelLoader - --(void)loadURL:(NSURL *)assetURL -withCompletionHandler:(GLTFModelLoaderCompletionHandler)completionHandler -bufferAllocator:(id)bufferAllocator { - - self.completionHandler = completionHandler; - [GLTFAsset loadAssetWithURL:assetURL - bufferAllocator:bufferAllocator - delegate:self]; - -} - - -- (void)assetWithURL:(nonnull NSURL *)assetURL didFailToLoadWithError:(nonnull NSError *)error { - NSLog(@"Asset load failed with error: %@", error); -} - -- (void)assetWithURL:(nonnull NSURL *)assetURL - didFinishLoading:(nonnull GLTFAsset *)asset { - dispatch_async(dispatch_get_main_queue(), ^{ - - if (self.completionHandler) { - self.completionHandler(asset); - } - self.completionHandler = nil; - - NSLog(@"INFO: Total live buffer allocation size after document load is %0.2f MB", ([GLTFMTLBufferAllocator liveAllocationSize] / (float)1e6)); - }); -} - -- (void)assetWithURL:(nonnull NSURL *)assetURL -requiresContentsOfURL:(nonnull NSURL *)url - completionHandler:(void (^)(NSData *_Nullable, NSError *_Nullable))completionHandler { - NSURLSessionDataTask *task = [GLTFModelLoader.urlSession dataTaskWithURL:url - completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) - { - completionHandler(data, error); - }]; - [task resume]; -} - -+ (NSURLSession *)urlSession { - static NSURLSession *_urlSession = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; - _urlSession = [NSURLSession sessionWithConfiguration:configuration]; - }); - return _urlSession; -} - - - -@end diff --git a/platform/darwin/src/gltf/GLTFRenderer.cpp b/platform/darwin/src/gltf/GLTFRenderer.cpp deleted file mode 100644 index c308e566f32d..000000000000 --- a/platform/darwin/src/gltf/GLTFRenderer.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// -// GLTFRenderer.cpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#include "GLTFRenderer.hpp" - -using namespace maplibre::gltf; - -GLTFRenderer::GLTFRenderer() { - _camera = std::make_unique(); -} - -// Destructor -GLTFRenderer::~GLTFRenderer() { - // Base class does nothing -} - -// Update any animations -void GLTFRenderer::update(float timeSinceLastDraw) { - // Base class does nothing -} - -// Render -void GLTFRenderer::render() { - // Base class does nothing -} - -// Set the drawable size -void GLTFRenderer::setDrawableSize(int width, int height) { - // Base class does nothing -} - -// Protected items -void GLTFRenderer::loadBloomPipelines() {} - -void GLTFRenderer::loadTonemapPipeline() {} - -void GLTFRenderer::updateFramebufferSize() {} - -// Load a model -void GLTFRenderer::loadGLTFModel(std::shared_ptr model) { - // Base class does nothing -} - -// Set the meters per pixel scale -void GLTFRenderer::setMetersPerPixel(double metersPerPixel) { - _metersPerPixel = metersPerPixel; -} - -// Set tilt -void GLTFRenderer::setTiltDeg(double tiltDeg) { - _tiltDeg = tiltDeg; -} - -// Set the rotation deg -void GLTFRenderer::setRotationDeg(double rotationDeg) { - _rotationDeg = rotationDeg; -} - -// Use bloom pass -void GLTFRenderer::setUseBloomPass(bool useBloomPass) { - _useBloomPass = useBloomPass; -} - -// Set the rendering environemnt variables -void GLTFRenderer::setRenderingEnvironemnt(std::shared_ptr renderingEnvironment) { - _renderingEnvironment = renderingEnvironment; -} diff --git a/platform/darwin/src/gltf/GLTFRenderer.hpp b/platform/darwin/src/gltf/GLTFRenderer.hpp deleted file mode 100644 index dba305678e60..000000000000 --- a/platform/darwin/src/gltf/GLTFRenderer.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// -// GLTFRenderer.hpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#ifndef GLTFRenderer_hpp -#define GLTFRenderer_hpp - -#include -#include "Camera.hpp" -#include "GLTFModel.hpp" -#include "GLTFManagerRenderingEnvironment.hpp" -#include - -namespace maplibre { -namespace gltf { - -class GLTFRenderer { -public: - // Constructor - GLTFRenderer(); - - // Destructor - virtual ~GLTFRenderer(); - - // Update any animations - virtual void update(float timeSinceLastDraw); - - // Render - virtual void render(); - - // Set the drawable size - virtual void setDrawableSize(int width, int height); - - // Load a model - virtual void loadGLTFModel(std::shared_ptr model); - - // Set the meters per pixel scale - void setMetersPerPixel(double metersPerPixel); - - // Set tilt - void setTiltDeg(double tiltDeg); - - // Set the rotation deg - void setRotationDeg(double rotationDeg); - - // Use bloom pass - void setUseBloomPass(bool useBloomPass); - - // Set the rendering environemnt variables - virtual void setRenderingEnvironemnt(std::shared_ptr renderingEnvironment); - -protected: - std::unique_ptr _camera = nullptr; - double _metersPerPixel = 1; - std::shared_ptr _renderingEnvironment = nullptr; - double _tiltDeg = 0; - double _rotationDeg = 0; - bool _useBloomPass = true; - virtual void loadBloomPipelines(); - virtual void loadTonemapPipeline(); - virtual void updateFramebufferSize(); -}; - -} // namespace gltf -} // namespace maplibre - -#endif /* GLTFRenderer_hpp */ diff --git a/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm b/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm deleted file mode 100644 index 89d169ef21a1..000000000000 --- a/platform/darwin/src/gltf/MetalRenderer+GLTFAsset.mm +++ /dev/null @@ -1,561 +0,0 @@ -// -// Untitled.h -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#include "MetalRenderer.hpp" - - -#import "GLTFMath.hpp" -#import "gltfkit/GLTFScene.h" -#import "gltfkit/GLTFMesh.h" -#import "gltfkit/GLTFMaterial.h" -#import "gltfkit/GLTFKHRLight.h" -#import "gltfkit/GLTFMTLUtilities.h" -#import "gltfkit/GLTFSkin.h" -#import "gltfkit/GLTFMTLBufferAllocator.h" -#import "gltfkit/GLTFAccessor.h" -#import "gltfkit/GLTFBufferView.h" -#import "gltfkit/GLTFVertexDescriptor.h" - - - -using namespace maplibre::gltf; - -// Encapsulated in GLTFRenderer+GLTFAsset -void MetalRenderer::setGLTFAsset(GLTFAsset *asset, std::shared_ptr model) { - - _models.clear(); - addGLTFAsset(asset, model); - -// _asset = asset; -// if (_asset != nullptr) { -// computeRegularizationMatrix(); -// computeTransforms(); -// addDefaultLights(); -// } - - -} - -// -void MetalRenderer::addGLTFAsset(GLTFAsset *asset, std::shared_ptr model) { - - auto m = createRenderModel(asset, model); - _models.push_back(m); - -} - -std::shared_ptr MetalRenderer::createRenderModel(GLTFAsset *asset, std::shared_ptr model) { - - std::shared_ptr tempResult = std::make_shared(); - tempResult->_asset = asset; - tempResult->_gltfModel = model; - tempResult->_scaling = model->_scaleFactor; - tempResult->_brightness = model->_brightness; - - computeRegularizationMatrix(tempResult); - computeTransforms(tempResult); - addDefaultLights(tempResult); - - return tempResult; - -} - - - -void MetalRenderer::addDefaultLights(std::shared_ptr model) { -// GLTFNode *lightNode = [[GLTFNode alloc] init]; -// lightNode.translation = (simd_float3){ 0, 0, 1 }; -// lightNode.rotationQuaternion = simd_quaternion(1.0f, 0, 0, 0); -// GLTFKHRLight *light = [[GLTFKHRLight alloc] init]; -// lightNode.light = light; -// [self.asset.defaultScene addNode:lightNode]; -// [self.asset addLight:light]; -// -// GLTFKHRLight *ambientLight = [[GLTFKHRLight alloc] init]; -// ambientLight.type = GLTFKHRLightTypeAmbient; -// ambientLight.intensity = 0.1; -// [self.asset addLight:ambientLight]; -// self.asset.defaultScene.ambientLight = ambientLight; -} - -void MetalRenderer::computeRegularizationMatrix(std::shared_ptr model) { - GLTFBoundingSphere bounds = GLTFBoundingSphereFromBox(model->_asset.defaultScene.approximateBounds); - model->_boundingSphere = bounds; - float scale = (bounds.radius > 0) ? (1 / (bounds.radius)) : 1; - simd_double4x4 centerScale = GLTFMatrixFromUniformScaleD(scale); - simd_double4x4 centerTranslation = GLTFMatrixFromTranslationD(-bounds.center); - - // This regularization matrix centers the model - model->_regularizationMatrix = matrix_multiply(centerScale, centerTranslation); - - - // The regularization matrix just scales it to show in the viewport - model->_regularizationMatrix = centerScale; - -} - -void MetalRenderer::computeTransforms(std::shared_ptr model) { - // New stuff - auto mdlMatrix = matrix_identity_double4x4; - - // Rotation - auto modelRotation = GLTFRotationMatrixFromAxisAngleD(GLTFAxisYD, (model->_gltfModel->_rotationDeg) * DEG_RAD); - auto modelRotated = matrix_multiply(modelRotation, mdlMatrix); - - // Tilt - auto modelTilted = GLTFRotationMatrixFromAxisAngleD(GLTFAxisXD, 90 * DEG_RAD); - modelTilted = matrix_multiply(modelTilted, modelRotated); - - simd_double3 xlateVector = simd_make_double3(model->_gltfModel->_xLateX, - model->_gltfModel->_xLateY, - model->_gltfModel->_xLateZ); - - auto xLateMatrix = GLTFMatrixFromTranslationD(xlateVector); - - auto modelTranslated = matrix_multiply(xLateMatrix, modelTilted); - - model->_modelMatrix = modelTranslated; - - model->_modelViewMatrix = modelTranslated; - - return; -} - -void MetalRenderer::renderScene(std::shared_ptr model, - GLTFScene *scene, - id commandBuffer, - id renderEncoder) { - - if (scene == nil) { - return; - } -/* - long timedOut = dispatch_semaphore_wait(_frameBoundarySemaphore, dispatch_time(0, 1 * NSEC_PER_SEC)); - if (timedOut) { - NSLog(@"Failed to receive frame boundary signal before timing out; calling signalFrameCompletion manually. " - "Remember to call signalFrameCompletion on GLTFMTLRenderer from the completion handler of the command buffer " - "into which you encode the work for drawing assets"); - signalFrameCompletion(); - } - */ - //self.ambientLight = scene.ambientLight; - - for (GLTFNode *rootNode in scene.nodes) { - buildLightListRecursive(rootNode); - } - - for (GLTFNode *rootNode in scene.nodes) { - buildRenderListRecursive(model, - rootNode, matrix_identity_float4x4, scene.ambientLight); - } - - NSMutableArray *renderList = [NSMutableArray arrayWithArray:_opaqueRenderItems]; - [renderList addObjectsFromArray:_transparentRenderItems]; - - drawRenderList(renderList, renderEncoder); - - NSArray *copiedDeferredReusableBuffers = [_deferredReusableBuffers copy]; - [commandBuffer addCompletedHandler:^(id commandBuffer) { - dispatch_async(dispatch_get_main_queue(), ^{ - for (id buffer in copiedDeferredReusableBuffers) { - enqueueReusableBuffer(buffer); - } - }); - }]; - - [_opaqueRenderItems removeAllObjects]; - [_transparentRenderItems removeAllObjects]; - [_currentLightNodes removeAllObjects]; - [_deferredReusableBuffers removeAllObjects]; -} - -void MetalRenderer::buildLightListRecursive(GLTFNode *node) { - if (node.light != nil) { - [_currentLightNodes addObject:node]; - } - - for (GLTFNode *childNode in node.children) { - buildLightListRecursive(childNode); - } -} - -simd_float4x4 matrix_double_to_float(simd_double4x4 input) { - simd_float4x4 tempResult; - tempResult.columns[0][0] = input.columns[0][0]; - tempResult.columns[0][1] = input.columns[0][1]; - tempResult.columns[0][2] = input.columns[0][2]; - tempResult.columns[0][3] = input.columns[0][3]; - - tempResult.columns[1][0] = input.columns[1][0]; - tempResult.columns[1][1] = input.columns[1][1]; - tempResult.columns[1][2] = input.columns[1][2]; - tempResult.columns[1][3] = input.columns[1][3]; - - tempResult.columns[2][0] = input.columns[2][0]; - tempResult.columns[2][1] = input.columns[2][1]; - tempResult.columns[2][2] = input.columns[2][2]; - tempResult.columns[2][3] = input.columns[2][3]; - - tempResult.columns[3][0] = input.columns[3][0]; - tempResult.columns[3][1] = input.columns[3][1]; - tempResult.columns[3][2] = input.columns[3][2]; - tempResult.columns[3][3] = input.columns[3][3]; - - return tempResult; -} - -simd_float3 double3_to_float3(simd_double3 input) { - simd_float3 tempResult; - tempResult.x = input.x; - tempResult.y = input.y; - tempResult.z = input.z; - return tempResult; - -} - -void MetalRenderer::buildRenderListRecursive(std::shared_ptr model, - GLTFNode *node, - simd_float4x4 modelMatrix, - GLTFKHRLight *defaultAmbientLight) { - modelMatrix = matrix_multiply(modelMatrix, node.localTransform); - - GLTFMesh *mesh = node.mesh; - if (mesh) { - for (GLTFSubmesh *submesh in mesh.submeshes) { - GLTFMaterial *material = submesh.material; - - simd_double3x3 viewAffine = simd_inverse(GLTFMatrixUpperLeft3x3D(model->_modelViewMatrix)); - simd_double3 cameraPos = model->_modelViewMatrix.columns[3].xyz; - simd_double3 cameraWorldPos = matrix_multiply(viewAffine, -cameraPos); - simd_float3 cameraWorldPosF = double3_to_float3(cameraWorldPos); - - VertexUniforms vertexUniforms; - vertexUniforms.modelMatrix = modelMatrix; - - // TODO: MT: Review this.. - auto mvp = matrix_multiply(_projectionMatrix, model->_modelMatrix); - auto mvpF = matrix_double_to_float(mvp); - vertexUniforms.modelViewProjectionMatrix = mvpF; - auto normalMatrix = GLTFNormalMatrixFromModelMatrixD(model->_modelMatrix); - vertexUniforms.normalMatrix = matrix_double_to_float(normalMatrix); - - vertexUniforms.scaleFactor = model->_scaling; - vertexUniforms.brightness = model->_brightness; - vertexUniforms.lightDirection = _renderingEnvironment->_lightDirection; - - FragmentUniforms fragmentUniforms; - fragmentUniforms.normalScale = material.normalTextureScale; - fragmentUniforms.emissiveFactor = material.emissiveFactor; - fragmentUniforms.occlusionStrength = material.occlusionStrength; - fragmentUniforms.metallicRoughnessValues = (simd_float2){ material.metalnessFactor, material.roughnessFactor }; - fragmentUniforms.baseColorFactor = material.baseColorFactor; - fragmentUniforms.camera = cameraWorldPosF; - fragmentUniforms.alphaCutoff = material.alphaCutoff; - fragmentUniforms.envIntensity = 2; // self.lightingEnvironment.intensity; - - if (material.baseColorTexture != nil) { - fragmentUniforms.textureMatrices[GLTFTextureBindIndexBaseColor] = GLTFTextureMatrixFromTransform(material.baseColorTexture.transform); - } - if (material.normalTexture != nil) { - fragmentUniforms.textureMatrices[GLTFTextureBindIndexNormal] = GLTFTextureMatrixFromTransform(material.normalTexture.transform); - } - if (material.metallicRoughnessTexture != nil) { - fragmentUniforms.textureMatrices[GLTFTextureBindIndexMetallicRoughness] = GLTFTextureMatrixFromTransform(material.metallicRoughnessTexture.transform); - } - if (material.occlusionTexture != nil) { - fragmentUniforms.textureMatrices[GLTFTextureBindIndexOcclusion] = GLTFTextureMatrixFromTransform(material.occlusionTexture.transform); - } - if (material.emissiveTexture != nil) { - fragmentUniforms.textureMatrices[GLTFTextureBindIndexEmissive] = GLTFTextureMatrixFromTransform(material.emissiveTexture.transform); - } - - if (defaultAmbientLight != nil) { - fragmentUniforms.ambientLight.color = defaultAmbientLight.color; // self.ambientLight.color; - fragmentUniforms.ambientLight.intensity = defaultAmbientLight.intensity; //self.ambientLight.intensity; - } - - // TODO: Make this more efficient. Iterating the light list for every submesh is pretty silly. - for (unsigned int lightIndex = 0; lightIndex < _currentLightNodes.count; ++lightIndex) { - GLTFNode *lightNode = _currentLightNodes[lightIndex]; - GLTFKHRLight *light = lightNode.light; - if (light.type == GLTFKHRLightTypeDirectional) { - fragmentUniforms.lights[lightIndex].position = lightNode.globalTransform.columns[2]; - } else { - fragmentUniforms.lights[lightIndex].position = lightNode.globalTransform.columns[3]; - } - fragmentUniforms.lights[lightIndex].color = light.color; - fragmentUniforms.lights[lightIndex].intensity = light.intensity; - fragmentUniforms.lights[lightIndex].range = light.range; - if (light.type == GLTFKHRLightTypeSpot) { - fragmentUniforms.lights[lightIndex].innerConeAngle = light.innerConeAngle; - fragmentUniforms.lights[lightIndex].outerConeAngle = light.outerConeAngle; - } else { - fragmentUniforms.lights[lightIndex].innerConeAngle = 0; - fragmentUniforms.lights[lightIndex].outerConeAngle = M_PI; - } - fragmentUniforms.lights[lightIndex].spotDirection = lightNode.globalTransform.columns[2]; - } - - GLTFMTLRenderItem *item = [GLTFMTLRenderItem new]; - item.label = [NSString stringWithFormat:@"%@ - %@", node.name ?: @"Unnamed node", submesh.name ?: @"Unnamed primitive"]; - item.node = node; - item.submesh = submesh; - item.vertexUniforms = vertexUniforms; - item.fragmentUniforms = fragmentUniforms; - - if (submesh.material.alphaMode == GLTFAlphaModeBlend) { - [_transparentRenderItems addObject:item]; - } else { - [_opaqueRenderItems addObject:item]; - } - } - } - - for (GLTFNode *childNode in node.children) { - buildRenderListRecursive(model, - childNode, modelMatrix, defaultAmbientLight); - // [self buildRenderListRecursive:childNode modelMatrix:modelMatrix]; - } -} - -void MetalRenderer::drawRenderList(NSArray *renderList, - id renderEncoder) { - for (GLTFMTLRenderItem *item in renderList) { - GLTFNode *node = item.node; - GLTFSubmesh *submesh = item.submesh; - GLTFMaterial *material = submesh.material; - - [renderEncoder pushDebugGroup:[NSString stringWithFormat:@"%@", item.label]]; - - id renderPipelineState = renderPipelineStateForSubmesh(submesh); - - [renderEncoder setRenderPipelineState:renderPipelineState]; - - [renderEncoder setFrontFacingWinding:MTLWindingCounterClockwise]; - - NSDictionary *accessorsForAttributes = submesh.accessorsForAttributes; - - GLTFAccessor *indexAccessor = submesh.indexAccessor; - BOOL useIndexBuffer = (indexAccessor != nil); - - // TODO: Check primitive type for unsupported types (tri fan, line loop), and modify draw calls as appropriate - MTLPrimitiveType primitiveType = GLTFMTLPrimitiveTypeForPrimitiveType(submesh.primitiveType); - - bindTexturesForMaterial(material, renderEncoder); - - VertexUniforms vertexUniforms = item.vertexUniforms; - [renderEncoder setVertexBytes:&vertexUniforms length:sizeof(vertexUniforms) atIndex:GLTFVertexDescriptorMaxAttributeCount + 0]; - - if (node.skin != nil && node.skin.jointNodes != nil && node.skin.jointNodes.count > 0) { - id jointBuffer = dequeueReusableBufferOfLength(node.skin.jointNodes.count * sizeof(simd_float4x4)); - computeJointsForSubmesh(submesh, node, jointBuffer); - [renderEncoder setVertexBuffer:jointBuffer offset:0 atIndex:GLTFVertexDescriptorMaxAttributeCount + 1]; - [_deferredReusableBuffers addObject:jointBuffer]; - } - - FragmentUniforms fragmentUniforms = item.fragmentUniforms; - [renderEncoder setFragmentBytes:&fragmentUniforms length: sizeof(fragmentUniforms) atIndex: 0]; - - GLTFVertexDescriptor *vertexDescriptor = submesh.vertexDescriptor; - for (int i = 0; i < GLTFVertexDescriptorMaxAttributeCount; ++i) { - NSString *semantic = vertexDescriptor.attributes[i].semantic; - if (semantic == nil) { continue; } - GLTFAccessor *accessor = submesh.accessorsForAttributes[semantic]; - - [renderEncoder setVertexBuffer:((GLTFMTLBuffer *)accessor.bufferView.buffer).buffer - offset:accessor.offset + accessor.bufferView.offset - atIndex:i]; - } - - if (material.alphaMode == GLTFAlphaModeBlend){ - id depthStencilState = depthStencilStateForDepthWriteEnabled(YES, YES, MTLCompareFunctionLess); - [renderEncoder setDepthStencilState:depthStencilState]; - } else { - id depthStencilState = depthStencilStateForDepthWriteEnabled(YES,YES,MTLCompareFunctionLess); - [renderEncoder setDepthStencilState:depthStencilState]; - } - - if (material.isDoubleSided) { - [renderEncoder setCullMode:MTLCullModeNone]; - } else { - [renderEncoder setCullMode:MTLCullModeBack]; - } - - if (useIndexBuffer) { - GLTFMTLBuffer *indexBuffer = (GLTFMTLBuffer *)indexAccessor.bufferView.buffer; - - MTLIndexType indexType = (indexAccessor.componentType == GLTFDataTypeUShort) ? MTLIndexTypeUInt16 : MTLIndexTypeUInt32; - - [renderEncoder drawIndexedPrimitives:primitiveType - indexCount:indexAccessor.count - indexType:indexType - indexBuffer:[indexBuffer buffer] - indexBufferOffset:indexAccessor.offset + indexAccessor.bufferView.offset]; - } else { - GLTFAccessor *positionAccessor = accessorsForAttributes[GLTFAttributeSemanticPosition]; - [renderEncoder drawPrimitives:primitiveType vertexStart:0 vertexCount:positionAccessor.count]; - } - - [renderEncoder popDebugGroup]; - } -} - - -void MetalRenderer::bindTexturesForMaterial(GLTFMaterial *material, - id renderEncoder) { - if (material.baseColorTexture != nil) { - id texture = textureForImage(material.baseColorTexture.texture.image, true); - id sampler = samplerStateForSampler(material.baseColorTexture.texture.sampler); - [renderEncoder setFragmentTexture:texture atIndex:GLTFTextureBindIndexBaseColor]; - [renderEncoder setFragmentSamplerState:sampler atIndex:GLTFTextureBindIndexBaseColor]; - } - - if (material.normalTexture != nil) { - id texture = textureForImage(material.normalTexture.texture.image, false); - id sampler = samplerStateForSampler(material.normalTexture.texture.sampler); - [renderEncoder setFragmentTexture:texture atIndex:GLTFTextureBindIndexNormal]; - [renderEncoder setFragmentSamplerState:sampler atIndex:GLTFTextureBindIndexNormal]; - } - - if (material.metallicRoughnessTexture != nil) { - id texture = textureForImage(material.metallicRoughnessTexture.texture.image, false); - id sampler = samplerStateForSampler(material.metallicRoughnessTexture.texture.sampler); - [renderEncoder setFragmentTexture:texture atIndex:GLTFTextureBindIndexMetallicRoughness]; - [renderEncoder setFragmentSamplerState:sampler atIndex:GLTFTextureBindIndexMetallicRoughness]; - } - - if (material.emissiveTexture != nil) { - id texture = textureForImage(material.emissiveTexture.texture.image, true); - id sampler = samplerStateForSampler(material.emissiveTexture.texture.sampler); - [renderEncoder setFragmentTexture:texture atIndex:GLTFTextureBindIndexEmissive]; - [renderEncoder setFragmentSamplerState:sampler atIndex:GLTFTextureBindIndexEmissive]; - } - - if (material.occlusionTexture != nil) { - id texture = textureForImage(material.occlusionTexture.texture.image, false); - id sampler = samplerStateForSampler(material.occlusionTexture.texture.sampler); - [renderEncoder setFragmentTexture:texture atIndex:GLTFTextureBindIndexOcclusion]; - [renderEncoder setFragmentSamplerState:sampler atIndex:GLTFTextureBindIndexOcclusion]; - } -} - -id MetalRenderer::dequeueReusableBufferOfLength(size_t length) { - int indexToReuse = -1; - for (unsigned int i = 0; i < _bufferPool.count; ++i) { - if (_bufferPool[i].length >= length) { - indexToReuse = i; - } - } - - if (indexToReuse >= 0) { - id buffer = _bufferPool[indexToReuse]; - [_bufferPool removeObjectAtIndex:indexToReuse]; - return buffer; - } else { - return [_metalDevice newBufferWithLength:length options:MTLResourceStorageModeShared]; - } -} - -void MetalRenderer::computeJointsForSubmesh(GLTFSubmesh *submesh, - GLTFNode *node, - id jointBuffer) { - GLTFAccessor *jointsAccessor = submesh.accessorsForAttributes[GLTFAttributeSemanticJoints0]; - GLTFSkin *skin = node.skin; - GLTFAccessor *inverseBindingAccessor = node.skin.inverseBindMatricesAccessor; - - if (jointsAccessor != nil && inverseBindingAccessor != nil) { - NSInteger jointCount = skin.jointNodes.count; - simd_float4x4 *jointMatrices = (simd_float4x4 *)jointBuffer.contents; - simd_float4x4 *inverseBindMatrices = (simd_float4x4 *)((char *)inverseBindingAccessor.bufferView.buffer.contents + inverseBindingAccessor.bufferView.offset + inverseBindingAccessor.offset); - for (NSInteger i = 0; i < jointCount; ++i) { - GLTFNode *joint = skin.jointNodes[i]; - simd_float4x4 inverseBindMatrix = inverseBindMatrices[i]; - jointMatrices[i] = matrix_multiply(matrix_invert(node.globalTransform), matrix_multiply(joint.globalTransform, inverseBindMatrix)); - } - } -} - -id MetalRenderer::depthStencilStateForDepthWriteEnabled(bool depthWriteEnabled, - bool depthTestEnabled, - MTLCompareFunction compareFunction) { - - NSInteger depthWriteBit = depthWriteEnabled ? 1 : 0; - NSInteger depthTestBit = depthTestEnabled ? 1 : 0; - - NSInteger hash = (compareFunction << 2) | (depthWriteBit << 1) | depthTestBit; - - id depthStencilState = _depthStencilStateMap[@(hash)]; - if (depthStencilState) { - return depthStencilState; - } - - MTLDepthStencilDescriptor *depthDescriptor = [MTLDepthStencilDescriptor new]; - depthDescriptor.depthCompareFunction = depthTestEnabled ? compareFunction : MTLCompareFunctionAlways; - depthDescriptor.depthWriteEnabled = depthWriteEnabled; - depthStencilState = [_metalDevice newDepthStencilStateWithDescriptor:depthDescriptor]; - - _depthStencilStateMap[@(hash)] = depthStencilState; - - return depthStencilState; -} - - -id MetalRenderer::textureForImage(GLTFImage *image, - bool sRGB) { -// NSParameterAssert(image != nil); - - id texture = _texturesForImageIdentifiers[image.identifier]; - - if (texture) { - return texture; - } - - NSDictionary *options = @{ GLTFMTLTextureLoaderOptionGenerateMipmaps : @YES, - GLTFMTLTextureLoaderOptionSRGB : @(sRGB) - }; - - NSError *error = nil; - if (image.imageData != nil) { - texture = [_textureLoader newTextureWithData:image.imageData options:options error:&error]; - texture.label = image.name; - } else if (image.url != nil) { - texture = [_textureLoader newTextureWithContentsOfURL:image.url options:options error:&error]; - texture.label = image.name ?: image.url.lastPathComponent; - } else if (image.bufferView != nil) { - GLTFBufferView *bufferView = image.bufferView; - NSData *data = [NSData dataWithBytesNoCopy:(char *)bufferView.buffer.contents + bufferView.offset length:bufferView.length freeWhenDone:NO]; - texture = [_textureLoader newTextureWithData:data options:options error:&error]; - texture.label = image.name; - } - - if (!texture) { - NSLog(@"Error occurred while loading texture: %@", error); - } else { - _texturesForImageIdentifiers[image.identifier] = texture; - } - - return texture; -} - -id MetalRenderer::samplerStateForSampler(GLTFTextureSampler *sampler) { -// NSParameterAssert(sampler != nil); - - id samplerState = _samplerStatesForSamplers[sampler]; - if (samplerState == nil) { - MTLSamplerDescriptor *descriptor = [MTLSamplerDescriptor new]; - descriptor.magFilter = GLTFMTLSamplerMinMagFilterForSamplingFilter(sampler.magFilter); - descriptor.minFilter = GLTFMTLSamplerMinMagFilterForSamplingFilter(sampler.minFilter); - descriptor.mipFilter = GLTFMTLSamplerMipFilterForSamplingFilter(sampler.minFilter); - descriptor.sAddressMode = GLTFMTLSamplerAddressModeForSamplerAddressMode(sampler.sAddressMode); - descriptor.tAddressMode = GLTFMTLSamplerAddressModeForSamplerAddressMode(sampler.tAddressMode); - descriptor.normalizedCoordinates = YES; - samplerState = [_metalDevice newSamplerStateWithDescriptor:descriptor]; - _samplerStatesForSamplers[sampler] = samplerState; - } - return samplerState; -} - diff --git a/platform/darwin/src/gltf/MetalRenderer.hpp b/platform/darwin/src/gltf/MetalRenderer.hpp deleted file mode 100644 index 4dae0c37c19e..000000000000 --- a/platform/darwin/src/gltf/MetalRenderer.hpp +++ /dev/null @@ -1,228 +0,0 @@ -// -// GLTFRenderer.hpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#ifndef MetalRenderer_hpp -#define MetalRenderer_hpp - -#include -#include -#include "GLTFRenderer.hpp" -#import "gltfkit/GLTFAsset.h" -#import "gltfkit//GLTFNode.h" -#import "gltfkit/GLTFImage.h" -#import "gltfkit/GLTFTextureSampler.h" -#include "GLTFMTLRenderItem.h" -#import "gltfkit/GLTFMTLTextureLoader.h" -#include "GLTFManagerRenderingEnvironmentMetal.hpp" -#include -#include -#include - -namespace maplibre { -namespace gltf { - -class GLTFRenderModel { -public: - // The model metadata - std::shared_ptr _gltfModel = nullptr; - - // The loaded model - GLTFAsset *_asset = nil; - - // Rendering variables - // Translation Vector is the translation of the model from the - simd_float3 _translationVector; // This might need to be a doubles vector - double _rotationDeg = 0; // Rotation around the zAxis (if applicable) - double _scaling = 1; // Scaling from - float _brightness = 1.0; // Brightness - - // This is the model matrix (rotation, scaling and transformation applied) - simd_double4x4 _modelMatrix; - - // This is the model matrix combined with the camera's view matrix - simd_double4x4 _modelViewMatrix; - - // We probably won't need this in the final thing. Used to normalize the model to the - // viewport size - simd_double4x4 _regularizationMatrix; - - // - GLTFBoundingSphere _boundingSphere; -}; - -// -class MetalRenderer : public GLTFRenderer { -public: - // Constructor - MetalRenderer(); - ~MetalRenderer(); - - void setMetalDevice(id device); - - // Set the drawable size - void setDrawableSize(int width, int height) override; - - // Set the current drawable (used for a metal view) - // void setCurrentDrawable(id drawable); - - // Set the output render pass descriptor (this is for outputting to a metal view) - // void setCurrentOutputRenderPassDescriptor(MTLRenderPassDescriptor *renderPassDescriptor); - - // Update any animations - void update(float timeSinceLastDraw) override; - - // Render - void render() override; - - // Load a model - void loadGLTFModel(std::shared_ptr model) override; - - // Set the rendering environemnt variables - void setRenderingEnvironemnt(std::shared_ptr renderingEnvironment) override; - -private: - // Rendering environment variables - simd_double4x4 _projectionMatrix; - int _sampleCount = 1; - MTLPixelFormat _colorPixelFormat; - MTLPixelFormat _depthStencilPixelFormat; - simd_int2 _drawableSize; - double _globalTime = 0; - int _maxInflightFrames = 3; - - // Current external environment variables - std::shared_ptr _metalRenderingEnvironment = nullptr; - - // id _currentDrawable = nullptr; - // MTLRenderPassDescriptor *_currentOutputRenderPassDescriptor = nullptr; - - dispatch_semaphore_t _frameBoundarySemaphore; - - void encodeMainPass(id commandBuffer); - void encodeBloomPasses(id commandBuffer); - void encodeTonemappingPass(id commandBuffer); - void drawFullscreenPassWithPipeline(id renderPipelineState, - id renderCommandEncoder, - id sourceTexture); - void signalFrameCompletion(); - MTLRenderPassDescriptor *newRenderPassDescriptor(); - -private: - // Per-frame - void computeTransforms(std::shared_ptr model); - -protected: - void loadBloomPipelines() override; - void loadTonemapPipeline() override; - void updateFramebufferSize() override; // Updates the framebuffers based on size - -private: - // Set by the environment - id _metalDevice = nullptr; - - // Created for rendering the model - id _internalMetalCommandQueue = nullptr; - id _metalLibrary = nullptr; - - // Setup the rendering environment. Called after device is set - void setupMetal(); - - // Bloom - id _bloomThresholdPipelineState = nullptr; - id _blurHorizontalPipelineState = nullptr; - id _blurVerticalPipelineState = nullptr; - id _additiveBlendPipelineState = nullptr; - - // Tonemap - id _tonemapPipelineState = nullptr; - - // Render targets - id _multisampleColorTexture = nullptr; - id _colorTexture = nullptr; - id _depthStencilTexture = nullptr; - id _bloomTextureA = nullptr; - id _bloomTextureB = nullptr; - - // Depth Clear - id _depthStencilClearState = nullptr; - id _pipelineDepthClearState = nullptr; - - void loadDepthClearPipeline(); - void clearDepth(id); - -public: - // Encapsulated in GLTFRenderer+GLTFAsset - void setGLTFAsset(GLTFAsset *asset, std::shared_ptr model); - - // - void addGLTFAsset(GLTFAsset *asset, std::shared_ptr model); - - // - id _bufferAllocator; - -private: - std::shared_ptr createRenderModel(GLTFAsset *asset, std::shared_ptr model); - - std::vector> _models; - // GLTFAsset *_asset = nil; - // NSMutableArray *_assets = nil; - - // - void computeRegularizationMatrix(std::shared_ptr model); - void addDefaultLights(std::shared_ptr model); - - void renderScene(std::shared_ptr model, - GLTFScene *scene, - id commandBuffer, - id renderEncoder); - - void buildLightListRecursive(GLTFNode *node); - - void buildRenderListRecursive(std::shared_ptr model, - GLTFNode *node, - simd_float4x4 modelMatrix, - GLTFKHRLight *defaultAmbientLight); - - void drawRenderList(NSArray *renderList, id renderEncoder); - - id renderPipelineStateForSubmesh(GLTFSubmesh *submesh); - - void bindTexturesForMaterial(GLTFMaterial *material, id renderEncoder); - - id dequeueReusableBufferOfLength(size_t length); - - void computeJointsForSubmesh(GLTFSubmesh *submesh, GLTFNode *node, id jointBuffer); - - id depthStencilStateForDepthWriteEnabled(bool depthWriteEnabled, - bool depthTestEnabled, - MTLCompareFunction compareFunction); - - id textureForImage(GLTFImage *image, bool sRGB); - id samplerStateForSampler(GLTFTextureSampler *sampler); - - NSMutableArray *_opaqueRenderItems; - NSMutableArray *_transparentRenderItems; - NSMutableArray *_currentLightNodes; - NSMutableArray> *_deferredReusableBuffers; - NSMutableArray> *_bufferPool; - NSMutableDictionary> *_depthStencilStateMap; - - NSMutableDictionary> *_pipelineStatesForSubmeshes; - NSMutableDictionary> *_texturesForImageIdentifiers; - GLTFMTLTextureLoader *_textureLoader; - NSMutableDictionary> *_samplerStatesForSamplers; - - void enqueueReusableBuffer(id buffer); - - // This is the depth stencil descriptor for overlaying the - id _fullscreenTransfterDepthStencilState = nullptr; -}; - -} // namespace gltf -} // namespace maplibre - -#endif /* MetalRenderer_hpp */ diff --git a/platform/darwin/src/gltf/MetalRenderer.mm b/platform/darwin/src/gltf/MetalRenderer.mm deleted file mode 100644 index 1a21692ea38e..000000000000 --- a/platform/darwin/src/gltf/MetalRenderer.mm +++ /dev/null @@ -1,540 +0,0 @@ -// -// GLTFRenderer.cpp -// GLTFTestRendering -// -// Created by Malcolm Toon on 11/19/24. -// - -#include "MetalRenderer.hpp" -#include -#include - -#import "GLTFModelLoader.h" -#import "gltfkit/GLTFAnimation.h" -#import "gltfkit/GLTFMTLShaderBuilder.h" -#import "gltfkit/GLTFMTLBufferAllocator.h" - - -using namespace maplibre::gltf; - -MetalRenderer::MetalRenderer() { - GLTFRenderer(); -} - -MetalRenderer::~MetalRenderer() { - std::cout << "Destructor\n"; -} - - -void MetalRenderer::setMetalDevice(id device) { - if (_metalDevice == device) { - return; - } - - _metalDevice = device; - setupMetal(); -} - -// Set the drawable size -void MetalRenderer::setDrawableSize(int width, int height) { - if ((_drawableSize.x == width) && (_drawableSize.y == height)) { - return; - } - _drawableSize = {width, height}; - // updateFramebufferSize(); -} - -// Set the current drawable -//void MetalRenderer::setCurrentDrawable(id drawable) { -// _currentDrawable = drawable; -//} - -// Set the output render pass descriptor (this is for outputting to a metal view) -//void MetalRenderer::setCurrentOutputRenderPassDescriptor(MTLRenderPassDescriptor *renderPassDescriptor) { -// _currentOutputRenderPassDescriptor = renderPassDescriptor; -//} - - - -// Update any animations -void MetalRenderer::update(float timeSinceLastDraw) { - - // Update the global time - _globalTime += timeSinceLastDraw; - - // If we don't have an asset, then bail - if (_models.size() == 0) { - return; - } - - double maxAnimDuration = 0; - for (auto m: _models) { - for (GLTFAnimation *animation in m->_asset.animations) { - for (GLTFAnimationChannel *channel in animation.channels) { - if (channel.duration > maxAnimDuration) { - maxAnimDuration = channel.duration; - } - } - } - } - - double animTime = fmod(_globalTime, maxAnimDuration); - for (auto m: _models) { - for (GLTFAnimation *animation in m->_asset.animations) { - [animation runAtTime:animTime]; - } - } - - _camera->updateWithTimestep(timeSinceLastDraw); - for (auto m: _models) { - computeTransforms(m); - } - -} - -// Render -void MetalRenderer::render() { - - auto environmentMVP = _metalRenderingEnvironment->_currentProjectionMatrix; - double tileSize = 256.0; - double zoom = _metalRenderingEnvironment->_currentZoomLevel; - double scaleFactor = (20037508.34); // M_PI - double worldSize = (tileSize / scaleFactor) * pow(2.0, zoom); - simd_double4x4 scaleMatrix = GLTFMatrixFromScaleD(simd_make_double3(worldSize, -worldSize, 1.0)); - simd_double4x4 xlateMatrix = GLTFMatrixFromTranslationD(simd_make_double3(20037508.34,-20037508.34,0.0)); - - auto m1 = matrix_multiply(scaleMatrix, xlateMatrix); - auto m2 = matrix_multiply(environmentMVP, m1); - _projectionMatrix = m2; - - // id internalCommandBuffer = [_internalMetalCommandQueue commandBuffer]; -// -// if (_existingCommandBuffer) { -// commandBuffer = _metalRenderingEnvironment->_currentCommandBuffer; -// } else { -// // Create a command buffer and we're going to be expected to draw to the output -// commandBuffer = [_internalMetalCommandQueue commandBuffer]; -// currentDrawable = _metalRenderingEnvironment->_currentDrawable; -// } -// - encodeMainPass(_metalRenderingEnvironment->_currentCommandBuffer); - // if (_useBloomPass) { - // encodeBloomPasses(internalCommandBuffer); - // } - -// [internalCommandBuffer addCompletedHandler:^(id buffer) { -// dispatch_async(dispatch_get_main_queue(), ^{ -// signalFrameCompletion(); -// }); -// }]; - - - // This will write out the tone mapping - //id externalBuffer = _metalRenderingEnvironment->_currentCommandBuffer; - //encodeTonemappingPass(externalBuffer); -} - -// Load a model -void MetalRenderer::loadGLTFModel(std::shared_ptr model) { - - GLTFModelLoader *modelLoader = [[GLTFModelLoader alloc] init]; - NSURL *u = [NSURL URLWithString:[NSString stringWithCString:model->_modelURL.c_str()]]; - [modelLoader loadURL:u - withCompletionHandler:^(GLTFAsset * _Nonnull asset) { - addGLTFAsset(asset, model); - } - bufferAllocator:_bufferAllocator]; - -} - -// Set the rendering environemnt variables -void MetalRenderer::setRenderingEnvironemnt(std::shared_ptr renderingEnvironment) { - GLTFRenderer::setRenderingEnvironemnt(renderingEnvironment); - - _metalRenderingEnvironment = std::static_pointer_cast(renderingEnvironment); - -} - - -// RENDERING -void MetalRenderer::encodeMainPass(id commandBuffer) { - - id renderEncoder = _metalRenderingEnvironment->_currentCommandEncoder; - - for (auto m: _models) { - [renderEncoder pushDebugGroup:@"Draw glTF Scene"]; - renderScene(m, m->_asset.defaultScene, commandBuffer, renderEncoder); - [renderEncoder popDebugGroup]; - } - - -} - -void MetalRenderer::encodeBloomPasses(id commandBuffer) { - - MTLRenderPassDescriptor *pass = [MTLRenderPassDescriptor renderPassDescriptor]; - pass.colorAttachments[0].texture = _bloomTextureA; - pass.colorAttachments[0].loadAction = MTLLoadActionDontCare; - pass.colorAttachments[0].storeAction = MTLStoreActionStore; - - id renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:pass]; - [renderEncoder pushDebugGroup:@"Post-process (Bloom threshold)"]; - drawFullscreenPassWithPipeline(_bloomThresholdPipelineState,renderEncoder,_colorTexture); - [renderEncoder popDebugGroup]; - [renderEncoder endEncoding]; - - pass = [MTLRenderPassDescriptor renderPassDescriptor]; - pass.colorAttachments[0].texture = _bloomTextureB; - pass.colorAttachments[0].loadAction = MTLLoadActionDontCare; - pass.colorAttachments[0].storeAction = MTLStoreActionStore; - renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:pass]; - [renderEncoder pushDebugGroup:@"Post-process (Bloom blur - horizontal)"]; - drawFullscreenPassWithPipeline(_blurHorizontalPipelineState,renderEncoder,_bloomTextureA); - [renderEncoder popDebugGroup]; - [renderEncoder endEncoding]; - - pass = [MTLRenderPassDescriptor renderPassDescriptor]; - pass.colorAttachments[0].texture = _bloomTextureA; - pass.colorAttachments[0].loadAction = MTLLoadActionDontCare; - pass.colorAttachments[0].storeAction = MTLStoreActionStore; - renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:pass]; - [renderEncoder pushDebugGroup:@"Post-process (Bloom blur - vertical)"]; - drawFullscreenPassWithPipeline(_blurVerticalPipelineState,renderEncoder,_bloomTextureB); - [renderEncoder popDebugGroup]; - [renderEncoder endEncoding]; - - pass = [MTLRenderPassDescriptor renderPassDescriptor]; - pass.colorAttachments[0].texture = _colorTexture; - pass.colorAttachments[0].loadAction = MTLLoadActionLoad; - pass.colorAttachments[0].storeAction = MTLStoreActionStore; - - renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:pass]; - [renderEncoder pushDebugGroup:@"Post-process (Bloom combine)"]; - drawFullscreenPassWithPipeline(_additiveBlendPipelineState,renderEncoder,_bloomTextureA); - [renderEncoder popDebugGroup]; - [renderEncoder endEncoding]; -} - -void MetalRenderer::encodeTonemappingPass(id commandBuffer) { - - if (_metalRenderingEnvironment->_currentRenderPassDescriptor == nil) { - return; - } - - id renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:_metalRenderingEnvironment->_currentRenderPassDescriptor]; - [renderEncoder pushDebugGroup:@"Post-process (Tonemapping)"]; - drawFullscreenPassWithPipeline(_tonemapPipelineState,renderEncoder,_colorTexture); - [renderEncoder popDebugGroup]; - [renderEncoder endEncoding]; - - - -} - -void MetalRenderer::drawFullscreenPassWithPipeline(id renderPipelineState, - id renderCommandEncoder, - id sourceTexture) { - float triangleData[] = { - -1, 3, 0, -1, - -1, -1, 0, 1, - 3, -1, 2, 1 - }; - [renderCommandEncoder setRenderPipelineState:renderPipelineState]; - [renderCommandEncoder setFrontFacingWinding:MTLWindingCounterClockwise]; - [renderCommandEncoder setCullMode:MTLCullModeNone]; - [renderCommandEncoder setVertexBytes:triangleData length:sizeof(float) * 12 atIndex:0]; - [renderCommandEncoder setFragmentTexture:sourceTexture atIndex:0]; - [renderCommandEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:3]; -} - -void MetalRenderer::signalFrameCompletion() { - dispatch_semaphore_signal(_frameBoundarySemaphore); -} - - -MTLRenderPassDescriptor* MetalRenderer::newRenderPassDescriptor() { - MTLRenderPassDescriptor *pass = [MTLRenderPassDescriptor renderPassDescriptor]; - if (_sampleCount > 1) { - pass.colorAttachments[0].texture = _multisampleColorTexture; - pass.colorAttachments[0].resolveTexture = _metalRenderingEnvironment->_colorTexture; - pass.colorAttachments[0].loadAction = MTLLoadActionLoad; - pass.colorAttachments[0].storeAction = MTLStoreActionMultisampleResolve; - pass.colorAttachments[0].clearColor = MTLClearColorMake(1, 0, 0, 0); - } else { - pass.colorAttachments[0].texture = _metalRenderingEnvironment->_colorTexture; - pass.colorAttachments[0].loadAction = MTLLoadActionLoad; - pass.colorAttachments[0].storeAction = MTLStoreActionStore; - pass.colorAttachments[0].clearColor = MTLClearColorMake(1, 0, 0, 0); - - } - pass.depthAttachment.texture = _metalRenderingEnvironment->_depthStencilTexture; - pass.depthAttachment.loadAction = MTLLoadActionLoad; - pass.depthAttachment.storeAction = MTLStoreActionStore; - - return pass; -} - -/* - ------- ------- ----- ----------------------------------------------- - PRIVATE METHODS BELOW - ------- ------- ----- ----------------------------------------------- -*/ - - -void MetalRenderer::setupMetal() { - - _internalMetalCommandQueue = [_metalDevice newCommandQueue]; - _metalLibrary = [_metalDevice newDefaultLibrary]; - - _projectionMatrix = matrix_identity_double4x4; - _colorPixelFormat = MTLPixelFormatBGRA8Unorm; - _depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8; - _sampleCount = 1; - _drawableSize = {1, 1}; - - _frameBoundarySemaphore = dispatch_semaphore_create(_maxInflightFrames); - - loadBloomPipelines(); - loadTonemapPipeline(); - loadDepthClearPipeline(); - - _opaqueRenderItems = [NSMutableArray array]; - _transparentRenderItems = [NSMutableArray array]; - _currentLightNodes = [NSMutableArray array]; - _deferredReusableBuffers = [NSMutableArray array]; - _bufferPool = [NSMutableArray array]; - - _pipelineStatesForSubmeshes = [NSMutableDictionary dictionary]; - _depthStencilStateMap = [NSMutableDictionary dictionary]; - _texturesForImageIdentifiers = [NSMutableDictionary dictionary]; - _samplerStatesForSamplers = [NSMutableDictionary dictionary]; - - _textureLoader = [[GLTFMTLTextureLoader alloc] initWithDevice:_metalDevice]; - _bufferAllocator = [[GLTFMTLBufferAllocator alloc] initWithDevice:_metalDevice]; - //_assets = [NSMutableArray array]; - - - - - MTLDepthStencilDescriptor *fullscreenTransfterDepthStencilDescriptor = [[MTLDepthStencilDescriptor alloc] init]; - fullscreenTransfterDepthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways; // Or another value as needed - fullscreenTransfterDepthStencilDescriptor.depthWriteEnabled = NO; - _fullscreenTransfterDepthStencilState = [_metalDevice newDepthStencilStateWithDescriptor:fullscreenTransfterDepthStencilDescriptor]; - - - -} - -void MetalRenderer::updateFramebufferSize() { - - MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor new]; - textureDescriptor.width = _drawableSize.x; - textureDescriptor.height = _drawableSize.y; - textureDescriptor.depth = 1; - - textureDescriptor.textureType = _sampleCount > 1 ? MTLTextureType2DMultisample : MTLTextureType2D; - textureDescriptor.pixelFormat = _colorPixelFormat; - textureDescriptor.sampleCount = _sampleCount; - textureDescriptor.storageMode = MTLStorageModePrivate; - textureDescriptor.usage = MTLTextureUsageRenderTarget; - _multisampleColorTexture = [_metalDevice newTextureWithDescriptor:textureDescriptor]; - - textureDescriptor.textureType = MTLTextureType2D; - textureDescriptor.pixelFormat = _colorPixelFormat; - textureDescriptor.sampleCount = 1; - textureDescriptor.storageMode = MTLStorageModePrivate; - textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; - _colorTexture = [_metalDevice newTextureWithDescriptor:textureDescriptor]; - - textureDescriptor.textureType = _sampleCount > 1 ? MTLTextureType2DMultisample : MTLTextureType2D; - textureDescriptor.pixelFormat = _depthStencilPixelFormat; - textureDescriptor.sampleCount = _sampleCount; - textureDescriptor.storageMode = MTLStorageModePrivate; - textureDescriptor.usage = MTLTextureUsageRenderTarget; - _depthStencilTexture = [_metalDevice newTextureWithDescriptor:textureDescriptor]; - - textureDescriptor.width = _drawableSize.x / 2; - textureDescriptor.height = _drawableSize.y / 2; - textureDescriptor.textureType = MTLTextureType2D; - textureDescriptor.pixelFormat = _colorPixelFormat; - textureDescriptor.sampleCount = 1; - textureDescriptor.storageMode = MTLStorageModePrivate; - textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; - _bloomTextureA = [_metalDevice newTextureWithDescriptor:textureDescriptor]; - - textureDescriptor.width = _drawableSize.x / 2; - textureDescriptor.height = _drawableSize.y / 2; - textureDescriptor.textureType = MTLTextureType2D; - textureDescriptor.pixelFormat = _colorPixelFormat; - textureDescriptor.sampleCount = 1; - textureDescriptor.storageMode = MTLStorageModePrivate; - textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; - _bloomTextureB = [_metalDevice newTextureWithDescriptor:textureDescriptor]; - - //self.renderer.sampleCount = self.sampleCount; - - -} - - - - - - -void MetalRenderer::loadBloomPipelines() { - - NSError *error = nil; - MTLRenderPipelineDescriptor *descriptor = [MTLRenderPipelineDescriptor new]; - descriptor.vertexFunction = [_metalLibrary newFunctionWithName:@"quad_vertex_main"]; - descriptor.colorAttachments[0].pixelFormat = _colorPixelFormat; - descriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"bloom_threshold_fragment_main"]; - _bloomThresholdPipelineState = [_metalDevice newRenderPipelineStateWithDescriptor:descriptor error:&error]; - if (_bloomThresholdPipelineState == nil) { - NSLog(@"Error occurred when creating render pipeline state: %@", error); - } - - descriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"blur_horizontal7_fragment_main"]; - _blurHorizontalPipelineState = [_metalDevice newRenderPipelineStateWithDescriptor:descriptor error:&error]; - if (_blurHorizontalPipelineState == nil) { - NSLog(@"Error occurred when creating render pipeline state: %@", error); - } - - descriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"blur_vertical7_fragment_main"]; - _blurVerticalPipelineState = [_metalDevice newRenderPipelineStateWithDescriptor:descriptor error:&error]; - if (_blurVerticalPipelineState == nil) { - NSLog(@"Error occurred when creating render pipeline state: %@", error); - } - - descriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"additive_blend_fragment_main"]; - - // Original Values - descriptor.colorAttachments[0].blendingEnabled = YES; - descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; - descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd; - descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne; - descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne; - descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOne; - descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorZero; - - descriptor.colorAttachments[0].blendingEnabled = YES; - descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; - descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationMin; - descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne; - descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha; - descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOne; - descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorDestinationAlpha; - - - _additiveBlendPipelineState = [_metalDevice newRenderPipelineStateWithDescriptor:descriptor error:&error]; - if (_additiveBlendPipelineState == nil) { - NSLog(@"Error occurred when creating render pipeline state: %@", error); - } -} - -void MetalRenderer::loadTonemapPipeline() { - - NSError *error = nil; - MTLRenderPipelineDescriptor *descriptor = [MTLRenderPipelineDescriptor new]; - - - // MT: Added blending - descriptor.colorAttachments[0].blendingEnabled = YES; - descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; - descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd; - descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha; - descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha; - descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha; - descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha; - - - id vertexFunction = [_metalLibrary newFunctionWithName:@"quad_vertex_main"]; - - descriptor.vertexFunction = vertexFunction; - descriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"tonemap_fragment_main"]; - descriptor.sampleCount = _sampleCount; - descriptor.colorAttachments[0].pixelFormat = _colorPixelFormat; - - // TODO: This was hard coded to fix an issue whe moving to ML. Need to sort out - // how these params are set in ML and pass them into here - descriptor.stencilAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; - descriptor.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; - - - _tonemapPipelineState = [_metalDevice newRenderPipelineStateWithDescriptor:descriptor error:&error]; - if (_tonemapPipelineState == nil) { - NSLog(@"Error occurred when creating render pipeline state: %@", error); - } -} - -void MetalRenderer::loadDepthClearPipeline() { - MTLDepthStencilDescriptor *depthStencilDescriptor = [[MTLDepthStencilDescriptor alloc] init]; - - depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways; - depthStencilDescriptor.depthWriteEnabled = YES; - depthStencilDescriptor.label = @"depthStencilClear"; - _depthStencilClearState = [_metalDevice newDepthStencilStateWithDescriptor:depthStencilDescriptor]; - - MTLRenderPipelineDescriptor *renderPipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; - - renderPipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; - renderPipelineDescriptor.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; - renderPipelineDescriptor.stencilAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; - renderPipelineDescriptor.rasterSampleCount = _sampleCount; - - renderPipelineDescriptor.vertexFunction = [_metalLibrary newFunctionWithName:@"vertex_depth_clear"]; - renderPipelineDescriptor.vertexFunction.label = @"vertexDepthClear"; - - renderPipelineDescriptor.fragmentFunction = [_metalLibrary newFunctionWithName:@"fragment_depth_clear"]; - renderPipelineDescriptor.fragmentFunction.label = @"fragmentDepthClear"; - - MTLVertexDescriptor *vertexDescriptor = [[MTLVertexDescriptor alloc] init]; - vertexDescriptor.attributes[0].format = MTLVertexFormatFloat2; - vertexDescriptor.attributes[0].offset = 0; - vertexDescriptor.attributes[0].bufferIndex = 0; - vertexDescriptor.layouts[0].stepRate = 1; - vertexDescriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex; - vertexDescriptor.layouts[0].stride = 8; - - renderPipelineDescriptor.vertexDescriptor = vertexDescriptor; - - NSError* error = NULL; - renderPipelineDescriptor.label = @"pipelineDepthClear"; - _pipelineDepthClearState = [_metalDevice newRenderPipelineStateWithDescriptor:renderPipelineDescriptor error:&error]; -} - -void MetalRenderer::clearDepth(id renderEncoder) { - [renderEncoder setDepthStencilState:_depthStencilClearState]; - [renderEncoder setRenderPipelineState:_pipelineDepthClearState]; - - const float clearCoords[8] = { - -1, -1, - 1, -1, - -1, 1, - 1, 1 - }; - - [renderEncoder setVertexBytes:clearCoords length:sizeof(float) * 8 atIndex:0]; - [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4]; - -} - -void MetalRenderer::enqueueReusableBuffer(id buffer) { - [_bufferPool addObject:buffer]; -} - -id MetalRenderer::renderPipelineStateForSubmesh(GLTFSubmesh *submesh) { - - id pipeline = _pipelineStatesForSubmeshes[submesh.identifier]; - - if (pipeline == nil) { - GLTFMTLShaderBuilder *shaderBuilder = [[GLTFMTLShaderBuilder alloc] init]; - pipeline = [shaderBuilder renderPipelineStateForSubmesh: submesh - colorPixelFormat:_colorPixelFormat - depthStencilPixelFormat:_depthStencilPixelFormat - sampleCount:_sampleCount - device:_metalDevice]; - _pipelineStatesForSubmeshes[submesh.identifier] = pipeline; - } - - return pipeline; -} diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAccessor.h b/platform/darwin/src/gltf/gltfkit/GLTFAccessor.h deleted file mode 100644 index e5bdf0d2f77c..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFAccessor.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFEnums.h" -#import "GLTFObject.h" - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFBufferView; - -typedef struct { - float minValue[16]; - float maxValue[16]; -} GLTFValueRange; - -@interface GLTFAccessor : GLTFObject -@property (nonatomic, weak) GLTFBufferView *bufferView; -@property (nonatomic, assign) GLTFDataType componentType; -@property (nonatomic, assign) GLTFDataDimension dimension; -@property (nonatomic, assign) NSInteger offset; -@property (nonatomic, assign) NSInteger count; -@property (nonatomic, assign) GLTFValueRange valueRange; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAccessor.mm b/platform/darwin/src/gltf/gltfkit/GLTFAccessor.mm deleted file mode 100644 index fdcc77e6c85c..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFAccessor.mm +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFAccessor.h" - -@implementation GLTFAccessor - -- (NSString *)description { - return [NSString stringWithFormat:@"GLTFAccessor: count: %d, component type: %d, dimension: %d, offset: %d, view: %@", - (int)self.count, (int)self.componentType, (int)self.dimension, (int)self.offset, self.bufferView]; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAnimation.h b/platform/darwin/src/gltf/gltfkit/GLTFAnimation.h deleted file mode 100644 index e00693e578f3..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFAnimation.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFEnums.h" -#import "GLTFObject.h" - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFNode, GLTFAccessor; - -@interface GLTFAnimation : GLTFObject -@property (nonatomic, copy) NSArray *channels; -@property (nonatomic, copy) NSDictionary *samplers; - -- (void)runAtTime:(NSTimeInterval)time; -@end - -@interface GLTFAnimationSampler : GLTFObject -@property (nonatomic, weak) GLTFAccessor *inputAccessor; -@property (nonatomic, weak) GLTFAccessor *outputAccessor; -@property (nonatomic, assign) GLTFInterpolationMode interpolationMode; -@end - -@interface GLTFAnimationChannel : NSObject -@property (nonatomic, weak) GLTFNode *targetNode; -@property (nonatomic, weak) NSString *targetPath; -@property (nonatomic, weak) GLTFAnimationSampler *sampler; -@property (nonatomic, readonly, assign) NSTimeInterval duration; -@property (nonatomic, readonly, assign) NSTimeInterval startTime; -@property (nonatomic, readonly, assign) NSTimeInterval endTime; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAnimation.mm b/platform/darwin/src/gltf/gltfkit/GLTFAnimation.mm deleted file mode 100644 index e716fc0113f5..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFAnimation.mm +++ /dev/null @@ -1,173 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFAnimation.h" -#include "GLTFUtilities.h" -#import "GLTFAccessor.h" -#import "GLTFBufferView.h" -#import "GLTFBuffer.h" -#import "GLTFNode.h" - -@implementation GLTFAnimationSampler - -- (NSString *)description { - return [NSString stringWithFormat:@"%@ interpolation: %d", super.description, (int)self.interpolationMode]; -} - -- (const void *)inputValues { - return (uint8_t*)[self.inputAccessor.bufferView.buffer contents] + self.inputAccessor.bufferView.offset + self.inputAccessor.offset; -} - -- (const void *)outputValues { - return (uint8_t*)[self.outputAccessor.bufferView.buffer contents] + self.outputAccessor.bufferView.offset + self.outputAccessor.offset; -} - -- (int)keyFrameCount { - return (int)self.inputAccessor.count; -} - -@end - -@implementation GLTFAnimationChannel - -- (NSString *)description { - return [NSString stringWithFormat:@"%@ target: %@; path: %@; sampler: %@", super.description, self.targetNode, self.targetPath, self.sampler]; -} - -- (NSTimeInterval)startTime { - GLTFAnimationSampler *sampler = self.sampler; - const float *timeValues = (const float*)sampler.inputValues; - float startTime = timeValues[0]; - return startTime; -} - -- (NSTimeInterval)endTime { - GLTFAnimationSampler *sampler = self.sampler; - const float *timeValues = (const float*)sampler.inputValues; - int keyFrameCount = sampler.keyFrameCount; - float endTime = timeValues[keyFrameCount - 1]; - return endTime; -} - -- (NSTimeInterval)duration { - return self.endTime - self.startTime; -} - -@end - -@implementation GLTFAnimation - -- (NSString *)description { - return [NSString stringWithFormat:@"%@ channels: %@", super.description, self.channels]; -} - -- (void)runAtTime:(NSTimeInterval)time { - for (GLTFAnimationChannel *channel in self.channels) { - GLTFNode *target = channel.targetNode; - NSString *path = channel.targetPath; - GLTFAnimationSampler *sampler = channel.sampler; - - int keyFrameCount = sampler.keyFrameCount; - - const float *timeValues = (const float*)sampler.inputValues; - - float minTime = timeValues[0]; - float maxTime = timeValues[keyFrameCount - 1]; - - if (time < minTime || time > maxTime) { - continue; - } - - int previousKeyFrame = 0, nextKeyFrame = 1; - while (timeValues[nextKeyFrame] < time) { - ++previousKeyFrame; - ++nextKeyFrame; - } - - if (previousKeyFrame >= keyFrameCount) { - previousKeyFrame = 0; - } - - if (nextKeyFrame >= keyFrameCount) { - nextKeyFrame = 0; - } - - float frameTimeDelta = timeValues[nextKeyFrame] - timeValues[previousKeyFrame]; - float timeWithinFrame = time - timeValues[previousKeyFrame]; - float frameProgress = timeWithinFrame / frameTimeDelta; - - if ([path isEqualToString:@"rotation"]) { - if(sampler.outputAccessor.componentType != GLTFDataTypeFloat) { - static dispatch_once_t floatRotationsNonce; - dispatch_once(&floatRotationsNonce, ^{ - NSLog(@"WARNING: Only float accessors are supported for rotation animations. This will only be reported once."); - }); - } - const GLTFQuaternion *rotationValues = (const GLTFQuaternion*)sampler.outputValues; - - GLTFQuaternion previousRotation = rotationValues[previousKeyFrame]; - GLTFQuaternion nextRotation = rotationValues[nextKeyFrame]; - GLTFQuaternion interpRotation = simd_slerp(previousRotation, nextRotation, frameProgress); - - target.rotationQuaternion = interpRotation; - } else if ([path isEqualToString:@"translation"]) { - const GLTFVector3 *translationValues = (const GLTFVector3*)sampler.outputValues; - - GLTFVector3 previousTranslation = translationValues[previousKeyFrame]; - GLTFVector3 nextTranslation = translationValues[nextKeyFrame]; - - GLTFVector3 interpTranslation = (GLTFVector3) { - ((1 - frameProgress) * previousTranslation.x) + (frameProgress * nextTranslation.x), - ((1 - frameProgress) * previousTranslation.y) + (frameProgress * nextTranslation.y), - ((1 - frameProgress) * previousTranslation.z) + (frameProgress * nextTranslation.z) - }; - - target.translation = (simd_float3){ interpTranslation.x, interpTranslation.y, interpTranslation.z }; - } else if ([path isEqualToString:@"scale"]) { - const float *scaleValues = (const float*)sampler.outputValues; - - float previousScale = scaleValues[previousKeyFrame]; - float nextScale = scaleValues[nextKeyFrame]; - - float interpScale = ((1 - frameProgress) * previousScale) + (frameProgress * nextScale); - - target.scale = (simd_float3)interpScale; - } else if ([path isEqualToString:@"weights"]) { - if(sampler.outputAccessor.componentType != GLTFDataTypeFloat) { - static dispatch_once_t floatWeightsNonce; - dispatch_once(&floatWeightsNonce, ^{ - NSLog(@"WARNING: Only scalar float accessors are supported for weight animations. This will only be reported once."); - }); - } - const float *weightValues = (const float*)sampler.outputValues; - - long weightCount = sampler.outputAccessor.count / keyFrameCount; - - const float *previousWeights = weightValues + (previousKeyFrame * weightCount); - const float *nextWeights = weightValues + (nextKeyFrame * weightCount); - - NSMutableArray *interpWeights = [NSMutableArray array]; - for (int i = 0; i < weightCount; ++i) { - float interpWeight = ((1 - frameProgress) * previousWeights[i]) + (frameProgress * nextWeights[i]); - [interpWeights addObject:@(interpWeight)]; - } - - target.morphTargetWeights = [interpWeights copy]; - } - } -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAsset.h b/platform/darwin/src/gltf/gltfkit/GLTFAsset.h deleted file mode 100644 index bbd795d35a70..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFAsset.h +++ /dev/null @@ -1,70 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import - -#import "GLTFEnums.h" -#import "GLTFObject.h" - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFAsset; -@class GLTFScene, GLTFCamera, GLTFAnimation; -@class GLTFKHRLight; -@protocol GLTFBufferAllocator; - -@protocol GLTFAssetLoadingDelegate -- (void)assetWithURL:(NSURL *)assetURL - requiresContentsOfURL:(NSURL *)url - completionHandler:(void (^)(NSData *_Nullable, NSError *_Nullable))completionHandler; -- (void)assetWithURL:(NSURL *)assetURL didFinishLoading:(GLTFAsset *)asset; -- (void)assetWithURL:(NSURL *)assetURL didFailToLoadWithError:(NSError *)error; -@end - -@interface GLTFAsset : NSObject - -@property (nonatomic, readonly, strong) NSArray *scenes; -@property (nonatomic, readonly) GLTFScene *_Nullable defaultScene; - -@property (nonatomic, readonly, strong) NSArray *animations; - -@property (nonatomic, readonly, strong) NSArray *lights; - -@property (nonatomic, readonly, strong) NSArray *cameras; - -@property (nonatomic, copy) NSString *_Nullable generator; -@property (nonatomic, copy) NSString *_Nullable copyright; -@property (nonatomic, copy) NSString *_Nullable formatVersion; - -@property (nonatomic, copy) NSArray *extensionsUsed; - -/// Load an asset asynchronously. The asset may either be a local asset or a remote asset; the -/// provided delegate will receive callbacks requesting the contents of remote URLs referenced by -/// the asset. These callbacks will occur on an arbitrary internal queue. -+ (void)loadAssetWithURL:(NSURL *)url - bufferAllocator:(id)bufferAllocator - delegate:(id)delegate; - -/// Load a local asset. The provided URL must be a file URL, or else loading will fail. -- (instancetype)initWithURL:(NSURL *)url bufferAllocator:(id)bufferAllocator; - -- (void)addLight:(GLTFKHRLight *)light; - -- (void)addCamera:(GLTFCamera *)camera; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFAsset.mm b/platform/darwin/src/gltf/gltfkit/GLTFAsset.mm deleted file mode 100644 index ccda5f5ed2d7..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFAsset.mm +++ /dev/null @@ -1,1274 +0,0 @@ - -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFAsset.h" -#include "GLTFEnums.h" -#import "GLTFAnimation.h" -#import "GLTFAccessor.h" -#import "GLTFBinaryChunk.h" -#import "GLTFBuffer.h" -#import "GLTFBufferAllocator.h" -#import "GLTFBufferView.h" -#import "GLTFCamera.h" -#import "GLTFExtensionNames.h" -#import "GLTFImage.h" -#import "GLTFKHRLight.h" -#import "GLTFMaterial.h" -#import "GLTFMesh.h" -#import "GLTFNode.h" -#import "GLTFTexture.h" -#import "GLTFTextureSampler.h" -#import "GLTFScene.h" -#import "GLTFSkin.h" -#import "GLTFUtilities.h" - -#import - -#define USE_AGGRESSIVE_ALIGNMENT 0 - -@interface GLTFAsset () -@property (nonatomic, strong) NSURL *url; -@property (nonatomic, strong) id bufferAllocator; -@property (nonatomic, weak) id delegate; -@property (nonatomic, copy) NSArray *accessors; -@property (nonatomic, copy) NSArray> *buffers; -@property (nonatomic, copy) NSArray *bufferViews; -@property (nonatomic, copy) NSArray *images; -@property (nonatomic, copy) NSArray *samplers; -@property (nonatomic, copy) NSArray *textures; -@property (nonatomic, copy) NSArray *meshes; -@property (nonatomic, copy) NSArray *materials; -@property (nonatomic, strong) NSMutableArray *lights; -@property (nonatomic, strong) NSMutableArray *cameras; -@property (nonatomic, copy) NSArray *nodes; -@property (nonatomic, strong) NSArray *animations; -@property (nonatomic, copy) NSArray *skins; -@property (nonatomic, copy) NSArray *chunks; -@property (nonatomic, strong) GLTFMaterial *defaultMaterial; -@property (nonatomic, strong) GLTFTextureSampler *defaultSampler; -@property (nonatomic, assign) BOOL usesPBRSpecularGlossiness; -@property (nonatomic, assign) BOOL usesEXTPBRAttributes; -@property (nonatomic, assign) BOOL usesKHRLights; -@property (nonatomic, assign) BOOL usesKHRTextureTransform; -@property (nonatomic, assign) BOOL usesKHRMaterialsUnlit; -@end - -@implementation GLTFAsset - -+ (dispatch_queue_t)assetLoaderQueue { - static dispatch_once_t onceToken; - static dispatch_queue_t _assetLoaderQueue; - dispatch_once(&onceToken, ^{ - _assetLoaderQueue = dispatch_queue_create("net.warrenmoore.gltfkit.asset-loader-queue", DISPATCH_QUEUE_CONCURRENT); - }); - return _assetLoaderQueue; -} - -+ (void)loadAssetWithURL:(NSURL *)url bufferAllocator:(id)bufferAllocator delegate:(id)delegate { - dispatch_async(GLTFAsset.assetLoaderQueue, ^{ - (void)[[GLTFAsset alloc] _initWithURL:url bufferAllocator:bufferAllocator delegate:delegate]; - }); -} - -- (instancetype)initWithURL:(NSURL *)url bufferAllocator:(id)bufferAllocator { - return [self _initWithURL:url bufferAllocator:bufferAllocator delegate:nil]; -} - -- (instancetype)_initWithURL:(NSURL *)url bufferAllocator:(id)bufferAllocator delegate:(id)delegate { - if ((self = [super init])) { - _url = url; - _bufferAllocator = bufferAllocator; - _delegate = delegate; - NSError *error = nil; - if (![self loadWithError:&error]) { - [_delegate assetWithURL:_url didFailToLoadWithError:error]; - return nil; - } - } - - [_delegate assetWithURL:_url didFinishLoading:self]; - - return self; -} - -- (void)addLight:(GLTFKHRLight *)light { - [_lights addObject:light]; -} - -- (void)addCamera:(GLTFCamera *)camera { - [_cameras addObject:camera]; -} - -- (NSData *)imageDataForDataURI:(NSString *)uriData { - NSString *prefix = @"data:"; - if ([uriData hasPrefix:prefix]) { - NSInteger prefixEnd = prefix.length; - NSInteger firstComma = [uriData rangeOfString:@","].location; - if (firstComma != NSNotFound) { - NSString *mediaTypeAndTokenString = [uriData substringWithRange:NSMakeRange(prefixEnd, firstComma - prefixEnd)]; - NSArray *mediaTypeAndToken = [mediaTypeAndTokenString componentsSeparatedByString:@";"]; - if (mediaTypeAndToken.count > 0) { - NSString *encodedImageData = [uriData substringFromIndex:firstComma + 1]; - NSData *imageData = [[NSData alloc] initWithBase64EncodedString:encodedImageData - options:NSDataBase64DecodingIgnoreUnknownCharacters]; - return imageData; - } - } - } - return nil; -} - -- (NSData *_Nullable)_contentsOfURL:(NSURL *)url error:(NSError **)error { - __block NSData *urlData = nil; - __block NSError *internalError = nil; - if (![_url isFileURL]) { - dispatch_semaphore_t loadingSemaphore = dispatch_semaphore_create(0); - [_delegate assetWithURL:_url requiresContentsOfURL:url completionHandler:^(NSData *_Nullable data, NSError *_Nullable responseError) { - urlData = data; - internalError = responseError; - dispatch_semaphore_signal(loadingSemaphore); - }]; - dispatch_semaphore_wait(loadingSemaphore, DISPATCH_TIME_FOREVER); - } else { - urlData = [NSData dataWithContentsOfURL:url]; - } - - if (internalError != nil && error != nil) { - *error = internalError; - } - - return urlData; -} - -- (BOOL)loadWithError:(NSError **)errorOrNil { - NSError *error = nil; - NSDictionary *rootObject = nil; - - NSData *assetData = [self _contentsOfURL:_url error:&error]; - if (assetData == nil) { - return NO; - } - - if ([self assetIsGLB:assetData]) { - [self readBinaryChunks:assetData]; - rootObject = [NSJSONSerialization JSONObjectWithData:_chunks.firstObject.data options:0 error:&error]; - } else { - rootObject = [NSJSONSerialization JSONObjectWithData:assetData options:0 error:&error]; - } - - if (!rootObject) { - if (errorOrNil) { *errorOrNil = error; } - return NO; - } - - _extensionsUsed = [rootObject[@"extensionsUsed"] ?: @[] copy]; - - [self toggleExtensionFeatureFlags]; - - _defaultSampler = [GLTFTextureSampler new]; - - _defaultMaterial = [GLTFMaterial new]; - - _lights = [NSMutableArray array]; - - _cameras = [NSMutableArray array]; - - // Since we aren't streaming, we have the properties for all objects in memory - // and we can load in the order that makes the least work for us, i.e. by - // reducing the number of name resolutions we have to do after we deserialize - // everything into glTF objects. The only object subgraph that can't be - // resolved by careful ordering of loading is the subgraph of nodes itself, - // which is stored unordered and may contain arbitrary node-node relationships. - // Therefore, we run a post-load fix-up pass to resolve all node graph edges - // into real object references. Refer to `fixNodeRelationships` below. - - [self loadAssetProperties:rootObject[@"asset"]]; - [self loadBuffers:rootObject[@"buffers"]]; - [self loadBufferViews:rootObject[@"bufferViews"]]; - [self loadAccessors:rootObject[@"accessors"]]; - [self loadSamplers:rootObject[@"samplers"]]; - [self loadImages:rootObject[@"images"]]; - [self loadTextures:rootObject[@"textures"]]; - [self loadMaterials:rootObject[@"materials"]]; - if (_usesKHRLights) { - NSDictionary *extensionProperties = rootObject[@"extensions"][GLTFExtensionKHRLights]; - NSArray *lightsProperties = extensionProperties[@"lights"]; - [self loadLights:lightsProperties]; - } - [self loadCameras:rootObject[@"cameras"]]; - [self loadSkins:rootObject[@"skins"]]; - [self loadMeshes:rootObject[@"meshes"]]; - [self loadNodes:rootObject[@"nodes"]]; - [self loadAnimations:rootObject[@"animations"]]; - [self loadScenes:rootObject[@"scenes"]]; - [self loadDefaultScene:rootObject[@"scene"]]; - - return YES; -} - -- (void)toggleExtensionFeatureFlags { - for (NSString *extension in _extensionsUsed) { - if ([extension isEqualToString:GLTFExtensionKHRMaterialsPBRSpecularGlossiness]) { - NSLog(@"WARNING: Extension \"%@\" is not fully supported", extension); - _usesPBRSpecularGlossiness = YES; - } else if ([extension isEqualToString:GLTFExtensionEXTPBRAttributes]) { - _usesEXTPBRAttributes = YES; - } else if ([extension isEqualToString:GLTFExtensionKHRLights]) { - _usesKHRLights = YES; - } else if ([extension isEqualToString:GLTFExtensionKHRMaterialsUnlit]) { - _usesKHRMaterialsUnlit = YES; - } else if ([extension isEqualToString:GLTFExtensionKHRTextureTransform]) { - _usesKHRTextureTransform = YES; - } else { - NSLog(@"WARNING: Unsupported extension \"%@\" used", extension); - } - } -} - -- (BOOL)assetIsGLB:(NSData *)assetData { - if (assetData.length < sizeof(GLTFBinaryHeader)) { - return NO; - } else { - GLTFBinaryHeader header; - [assetData getBytes:&header length:sizeof(header)]; - return (header.magic == GLTFBinaryMagic); - } -} - -- (void)readBinaryChunks:(NSData *)assetData { - NSMutableArray *chunks = [NSMutableArray array]; - - GLTFBinaryHeader header; - [assetData getBytes:&header length:sizeof(GLTFBinaryHeader)]; - - NSUInteger offset = sizeof(GLTFBinaryHeader); - while (offset < header.length && offset < assetData.length) { - GLTFBinaryChunk *chunk = [GLTFBinaryChunk new]; - struct { - UInt32 length; - UInt32 type; - } chunkHeader; - - [assetData getBytes:&chunkHeader range:NSMakeRange(offset, sizeof(chunkHeader))]; - - NSData *chunkData = [NSData dataWithBytesNoCopy:(void *)((uint8_t*)assetData.bytes + offset + sizeof(chunkHeader)) - length:chunkHeader.length - freeWhenDone:NO]; - chunk.data = chunkData; - chunk.chunkType = (GLTFChunkType)chunkHeader.type; - - [chunks addObject:chunk]; - - offset += sizeof(chunkHeader) + chunkHeader.length; - } - - _chunks = [chunks copy]; - - NSAssert(_chunks.firstObject.chunkType == GLTFChunkTypeJSON, @"First chunk in GLB file had type %u rather than expected %u", - (unsigned int)_chunks.firstObject.chunkType, (unsigned int)GLTFChunkTypeJSON); -} - -- (BOOL)loadAssetProperties:(NSDictionary *)propertiesMap { - _generator = [propertiesMap[@"generator"] copy]; - _copyright = [propertiesMap[@"copyright"] copy]; - _formatVersion = propertiesMap[@"version"] ?: @"2.0"; - return YES; -} - -- (BOOL)loadAccessors:(NSArray *)accessorsMap { - if (accessorsMap.count == 0) { - _accessors = @[]; - return YES; - } - - NSMutableArray *accessors = [NSMutableArray arrayWithCapacity:accessorsMap.count]; - for (NSDictionary *properties in accessorsMap) { - GLTFAccessor *accessor = [[GLTFAccessor alloc] init]; - accessor.componentType = (GLTFDataType)[properties[@"componentType"] integerValue]; - accessor.dimension = GLTFDataDimensionForName(properties[@"type"]); - accessor.offset = [properties[@"byteOffset"] integerValue]; - accessor.count = [properties[@"count"] integerValue]; - NSUInteger bufferViewIndex = [properties[@"bufferView"] intValue]; - if (bufferViewIndex < _bufferViews.count) { - accessor.bufferView = _bufferViews[bufferViewIndex]; -#if USE_AGGRESSIVE_ALIGNMENT - size_t alignment = GLTFSizeOfComponentTypeWithDimension(accessor.componentType, accessor.dimension); -#else - size_t alignment = GLTFSizeOfDataType(accessor.componentType); -#endif - NSInteger dataOffset = accessor.offset + accessor.bufferView.offset; - if (dataOffset % alignment != 0) { - size_t elementSize = GLTFSizeOfComponentTypeWithDimension(accessor.componentType, accessor.dimension); - size_t length = accessor.count * elementSize; - NSLog(@"WARNING: Accessor had misaligned offset %d, which is not a multiple of %d. Building auxiliary buffer of length %d and continuing...", - (int)dataOffset, (int)alignment, (int)length); - id buffer = [_bufferAllocator newBufferWithLength:length]; - memcpy(buffer.contents, (uint8_t*)accessor.bufferView.buffer.contents + accessor.bufferView.offset + accessor.offset, buffer.length); - _buffers = [_buffers arrayByAddingObject:buffer]; - - GLTFBufferView *bufferView = [GLTFBufferView new]; - bufferView.buffer = buffer; - bufferView.offset = 0; - bufferView.stride = 0; - _bufferViews = [_bufferViews arrayByAddingObject:bufferView]; - - accessor.bufferView = bufferView; - accessor.offset = 0; - } - } - - __block GLTFValueRange valueRange = { {}, {} }; - NSArray *minValues = properties[@"min"]; - [minValues enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger index, BOOL *stop) { - valueRange.minValue[index] = num.floatValue; - }]; - NSArray *maxValues = properties[@"max"]; - [maxValues enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger index, BOOL *stop) { - valueRange.maxValue[index] = num.floatValue; - }]; - accessor.valueRange = valueRange; - - [accessors addObject:accessor]; - } - - _accessors = [accessors copy]; - - return YES; -} - -- (BOOL)loadBuffers:(NSArray *)buffersMap { - if (buffersMap.count == 0) { - _buffers = @[]; - } - - NSMutableArray *buffers = [NSMutableArray arrayWithCapacity:buffersMap.count]; - for (NSDictionary *properties in buffersMap) { - NSInteger byteLength = [properties[@"byteLength"] integerValue]; - - NSString *uri = properties[@"uri"]; - NSData *data = nil; - - if ([uri hasPrefix:@"data:"]) { - if ([uri hasPrefix:@"data:application/octet-stream;base64,"]) { - NSString *dataSubstring = [uri substringFromIndex:[@"data:application/octet-stream;base64," length]]; - data = [[NSData alloc] initWithBase64EncodedString:dataSubstring options:0]; - } else { - NSLog(@"WARNING: Encountered URL-encoded buffer that did not have the expected MIME type or encoding. Skipping..."); - continue; - } - } else if (uri.length > 0) { - NSURL *bufferURL = [[_url URLByDeletingLastPathComponent] URLByAppendingPathComponent:uri]; - NSError *error = nil; - data = [self _contentsOfURL:bufferURL error:&error]; - NSAssert(data != nil, @"Unable to load data at URL %@; error %@", bufferURL, error); - } else if (_chunks.count > 1) { - data = _chunks[1].data; - } else { - NSLog(@"WARNING: Encountered buffer which was not URL-encoded, nor a file reference, nor a GLB chunk reference. Skipping..."); - continue; - } - - id buffer = [_bufferAllocator newBufferWithData:data]; - - if (byteLength != [buffer length]) { - NSLog(@"WARNING: Expected to load buffer of length %lu bytes; got %lu bytes", (unsigned long)byteLength, (unsigned long)[buffer length]); - } - [buffers addObject: buffer]; - } - - _buffers = [buffers copy]; - return YES; -} - -- (BOOL)loadBufferViews:(NSArray *)bufferViewsMap { - if (bufferViewsMap.count == 0) { - _bufferViews = @[]; - } - - NSMutableArray *bufferViews = [NSMutableArray arrayWithCapacity:bufferViewsMap.count]; - [bufferViewsMap enumerateObjectsUsingBlock:^(NSDictionary *properties, NSUInteger index, BOOL *stop) { - - GLTFBufferView *bufferView = [[GLTFBufferView alloc] init]; - NSUInteger bufferIndex = [properties[@"buffer"] intValue]; - if (bufferIndex < _buffers.count) { - bufferView.buffer = _buffers[bufferIndex]; - } - bufferView.length = [properties[@"byteLength"] integerValue]; - bufferView.stride = [properties[@"byteStride"] integerValue]; - bufferView.offset = [properties[@"byteOffset"] integerValue]; - bufferView.target = (GLTFTarget)[properties[@"target"] integerValue]; - -// if ((bufferView.buffer != nil) && (bufferView.offset % 16 != 0)) { -// NSLog(@"WARNING: Buffer view %d had misaligned offset of %d. Creating auxilliary buffer of length %d and continuing...", -// (int)index, (int)bufferView.offset, (int)bufferView.length); -// id alignedBuffer = [_bufferAllocator newBufferWithLength:bufferView.length]; -// _buffers = [_buffers arrayByAddingObject:alignedBuffer]; -// memcpy([alignedBuffer contents], bufferView.buffer.contents + bufferView.offset, bufferView.length); -// bufferView.buffer = alignedBuffer; -// bufferView.offset = 0; -// } - - [bufferViews addObject: bufferView]; - }]; - - _bufferViews = [bufferViews copy]; - return YES; -} - -- (BOOL)loadSamplers:(NSArray *)samplersMap { - if (samplersMap.count == 0) { - _samplers = @[]; - } - - NSMutableArray *samplers = [NSMutableArray arrayWithCapacity:samplersMap.count]; - for (NSDictionary *properties in samplersMap) { - GLTFTextureSampler *sampler = [[GLTFTextureSampler alloc] init]; - sampler.minFilter = (GLTFSamplingFilter)([properties[@"minFilter"] integerValue] ?: sampler.minFilter); - sampler.magFilter = (GLTFSamplingFilter)([properties[@"magFilter"] integerValue] ?: sampler.magFilter); - sampler.sAddressMode = (GLTFAddressMode)([properties[@"wrapS"] integerValue] ?: sampler.sAddressMode); - sampler.tAddressMode = (GLTFAddressMode)([properties[@"wrapT"] integerValue] ?: sampler.tAddressMode); - sampler.name = properties[@"name"]; - sampler.extensions = properties[@"extensions"]; - sampler.extras = properties[@"extras"]; - - [samplers addObject:sampler]; - } - - _samplers = [samplers copy]; - return YES; -} - -- (BOOL)loadImages:(NSArray *)imagesMap { - if (imagesMap.count == 0) { - _images = @[]; - } - - NSMutableArray *images = [NSMutableArray arrayWithCapacity:imagesMap.count]; - for (NSDictionary *properties in imagesMap) { - GLTFImage *image = [[GLTFImage alloc] init]; - - NSString *uri = properties[@"uri"]; - - if ([uri hasPrefix:@"data:image/"]) { - image.imageData = [self imageDataForDataURI:uri]; - } else if (uri.length > 0) { - NSURL *resourceURL = [self.url URLByDeletingLastPathComponent]; - image.url = [resourceURL URLByAppendingPathComponent:uri]; - } - - image.mimeType = properties[@"mimeType"]; - - NSString *bufferViewIndexString = properties[@"bufferView"]; - if (bufferViewIndexString) { - NSUInteger bufferViewIndex = bufferViewIndexString.integerValue; - if (bufferViewIndex < _bufferViews.count) { - image.bufferView = _bufferViews[bufferViewIndex]; - } - } - - image.name = properties[@"name"]; - image.extensions = properties[@"extensions"]; - image.extras = properties[@"extras"]; - - [images addObject:image]; - } - - _images = [images copy]; - return YES; -} - -- (BOOL)loadTextures:(NSArray *)texturesMap { - if (texturesMap.count == 0) { - _textures = @[]; - } - - NSMutableArray *textures = [NSMutableArray arrayWithCapacity:texturesMap.count]; - for (NSDictionary *properties in texturesMap) { - GLTFTexture *texture = [[GLTFTexture alloc] init]; - - NSUInteger samplerIndex = [properties[@"sampler"] intValue]; - if (samplerIndex < _samplers.count) { - texture.sampler = _samplers[samplerIndex]; - } else { - texture.sampler = _defaultSampler; - } - - NSUInteger imageIndex = [properties[@"source"] intValue]; - if (imageIndex < _images.count) { - texture.image = _images[imageIndex]; - } - - texture.format = (GLTFTextureFormat)([properties[@"format"] integerValue] ?: texture.format); - texture.internalFormat = (GLTFTextureFormat)([properties[@"internalFormat"] integerValue] ?: texture.internalFormat); - texture.target = (GLTFTextureTarget)([properties[@"target"] integerValue] ?: texture.target); - texture.type = (GLTFTextureType)([properties[@"type"] integerValue] ?: texture.type); - texture.name = properties[@"name"]; - texture.extensions = properties[@"extensions"]; - texture.extras = properties[@"extras"]; - - [textures addObject: texture]; - } - - _textures = [textures copy]; - return YES; -} - - -- (BOOL)loadCameras:(NSArray *)camerasMap { - if (camerasMap.count == 0) { - _cameras = [NSMutableArray array]; - return YES; - } - - _cameras = [NSMutableArray arrayWithCapacity:camerasMap.count]; - for (NSDictionary *properties in camerasMap) { - GLTFCamera *camera = [[GLTFCamera alloc] init]; - - camera.cameraType = [properties[@"type"] isEqualToString:@"orthographic"] ? GLTFCameraTypeOrthographic : GLTFCameraTypePerspective; - - NSDictionary *params = properties[properties[@"type"]]; - - switch (camera.cameraType) { - case GLTFCameraTypeOrthographic: - camera.xmag = [params[@"xmag"] floatValue]; - camera.ymag = [params[@"ymag"] floatValue]; - break; - case GLTFCameraTypePerspective: - default: { - NSNumber *aspectRatioValue = params[@"aspectRatio"]; - camera.aspectRatio = (aspectRatioValue != nil) ? aspectRatioValue.floatValue : 1.0; - camera.yfov = [params[@"yfov"] floatValue]; - break; - } - } - - camera.znear = [params[@"znear"] floatValue]; - - if (camera.cameraType == GLTFCameraTypePerspective && (params[@"zfar"] == nil)) { - camera.zfar = FLT_MAX; - } else { - camera.zfar = [params[@"zfar"] floatValue]; - } - - camera.extensions = properties[@"extensions"]; - camera.extras = properties[@"extras"]; - - [_cameras addObject: camera]; - } - - return YES; -} - -- (BOOL)loadLights:(NSArray *)lightsMap { - if (lightsMap.count == 0) { - return YES; - } - - _lights = [NSMutableArray arrayWithCapacity:lightsMap.count]; - [lightsMap enumerateObjectsUsingBlock:^(NSDictionary *properties, NSUInteger index, BOOL *stop) { - GLTFKHRLight *light = [GLTFKHRLight new]; - NSString *lightTypeName = properties[@"type"]; - if ([lightTypeName isEqualToString:@"ambient"]) { - light.type = GLTFKHRLightTypeAmbient; - } else if ([lightTypeName isEqualToString:@"directional"]) { - light.type = GLTFKHRLightTypeDirectional; - } else if ([lightTypeName isEqualToString:@"point"]) { - light.type = GLTFKHRLightTypePoint; - } else if ([lightTypeName isEqualToString:@"spot"]) { - light.type = GLTFKHRLightTypeSpot; - } - - NSArray *colorArray = properties[@"color"]; - switch ([colorArray count]) { - case 3: // This is out of spec, but it happens in the wild, so be graceful. - light.color = GLTFVectorFloat4FromArray([colorArray arrayByAddingObject:@(1)]); - break; - case 4: - light.color = GLTFVectorFloat4FromArray(colorArray); - break; - } - - NSNumber *intensityValue = properties[@"intensity"]; - if (intensityValue != nil) { - light.intensity = [intensityValue floatValue]; - } - - if (light.type == GLTFKHRLightTypeSpot) { - NSDictionary *spotProperties = properties[@"spot"]; - NSNumber *innerConeAngleValue = spotProperties[@"innerConeAngle"]; - if (innerConeAngleValue != nil) { - light.innerConeAngle = [innerConeAngleValue floatValue]; - } - NSNumber *outerConeAngleValue = spotProperties[@"outerConeAngle"]; - if (outerConeAngleValue != nil) { - light.outerConeAngle = [outerConeAngleValue floatValue]; - } - } - - [_lights addObject:light]; - }]; - - return YES; -} - -- (BOOL)loadMeshes:(NSArray *)meshesMap { - if (meshesMap.count == 0) { - _meshes = @[]; - } - - NSMutableArray *meshes = [NSMutableArray arrayWithCapacity:meshesMap.count]; - for (NSDictionary *properties in meshesMap) { - GLTFMesh *mesh = [[GLTFMesh alloc] init]; - mesh.name = properties[@"name"]; - mesh.extensions = properties[@"extensions"]; - mesh.extras = properties[@"extras"]; - - mesh.defaultMorphTargetWeights = properties[@"weights"] ?: @[]; - - NSArray *submeshesProperties = properties[@"primitives"]; - NSMutableArray *submeshes = [NSMutableArray arrayWithCapacity:submeshesProperties.count]; - for (NSDictionary *submeshProperties in submeshesProperties) { - GLTFSubmesh *submesh = [[GLTFSubmesh alloc] init]; - - NSDictionary *submeshAttributes = submeshProperties[@"attributes"]; - - NSMutableDictionary *attributeAccessors = [NSMutableDictionary dictionaryWithCapacity:submeshAttributes.count]; - [submeshAttributes enumerateKeysAndObjectsUsingBlock:^(NSString *attributeName, NSNumber *accessorIndexValue, BOOL *stop) { - NSUInteger accessorIndex = accessorIndexValue.unsignedIntegerValue; - if (accessorIndex < _accessors.count) { - GLTFAccessor *accessor = _accessors[accessorIndex]; - attributeAccessors[attributeName] = accessor; - } - }]; - - submesh.accessorsForAttributes = attributeAccessors; - - NSUInteger materialIndex = [submeshProperties[@"material"] intValue]; - if (materialIndex < _materials.count) { - submesh.material = _materials[materialIndex]; - } else { - submesh.material = _defaultMaterial; - } - - NSUInteger indexAccessorIndex = [submeshProperties[@"indices"] intValue]; - if (indexAccessorIndex < _accessors.count) { - GLTFAccessor *indexAccessor = _accessors[indexAccessorIndex]; - if (indexAccessor.componentType == (GLTFDataType)GLTFTextureTypeUChar) { - // Fix up 8-bit indices, since they're unsupported in modern APIs - uint8_t *sourceIndices = (uint8_t*)indexAccessor.bufferView.buffer.contents + indexAccessor.offset + indexAccessor.bufferView.offset; - - id shortBuffer = [_bufferAllocator newBufferWithLength:indexAccessor.count * sizeof(uint16_t)]; - uint16_t *destIndices = (uint16_t*)shortBuffer.contents; - for (int i = 0; i < indexAccessor.count; ++i) { - destIndices[i] = (uint16_t)sourceIndices[i]; - } - _buffers = [_buffers arrayByAddingObject:shortBuffer]; - - GLTFBufferView *shortBufferView = [GLTFBufferView new]; - shortBufferView.buffer = shortBuffer; - shortBufferView.offset = 0; - shortBufferView.stride = 0; - _bufferViews = [_bufferViews arrayByAddingObject:shortBufferView]; - - GLTFAccessor *shortAccessor = [GLTFAccessor new]; - shortAccessor.bufferView = shortBufferView; - shortAccessor.componentType = GLTFDataTypeUShort; - shortAccessor.dimension = GLTFDataDimensionScalar; - shortAccessor.count = indexAccessor.count; - shortAccessor.offset = 0; - shortAccessor.valueRange = indexAccessor.valueRange; - _accessors = [_accessors arrayByAddingObject:shortAccessor]; - - indexAccessor = shortAccessor; - } - submesh.indexAccessor = indexAccessor; - } - - if (submeshProperties[@"mode"]) { - submesh.primitiveType = (GLTFPrimitiveType)[submeshProperties[@"mode"] intValue]; - } - - NSMutableArray *morphTargets = [NSMutableArray array]; - for (NSDictionary *targetProperties in submeshProperties[@"targets"]) { - GLTFMorphTarget *morphTarget = [GLTFMorphTarget new]; - NSMutableDictionary *attributeAccessors = [NSMutableDictionary dictionaryWithCapacity:submeshAttributes.count]; - [targetProperties enumerateKeysAndObjectsUsingBlock:^(NSString *attributeName, NSNumber *accessorIndexValue, BOOL *stop) { - NSUInteger accessorIndex = accessorIndexValue.unsignedIntegerValue; - if (accessorIndex < _accessors.count) { - GLTFAccessor *accessor = _accessors[accessorIndex]; - attributeAccessors[attributeName] = accessor; - } - }]; - morphTarget.accessorsForAttributes = [attributeAccessors copy]; - [morphTargets addObject:morphTarget]; - } - submesh.morphTargets = [morphTargets copy]; - - [submeshes addObject:submesh]; - } - - mesh.submeshes = [submeshes copy]; - - [meshes addObject:mesh]; - } - - _meshes = [meshes copy]; - return YES; -} - - -- (BOOL)loadMaterials:(NSArray *)materialsMap { - if (materialsMap.count == 0) { - _materials = @[]; - return YES; - } - - NSMutableArray *materials = [NSMutableArray arrayWithCapacity:materialsMap.count]; - for (NSDictionary *properties in materialsMap) { - GLTFMaterial *material = [[GLTFMaterial alloc] init]; - - NSDictionary *pbrValuesMap = properties[@"pbrMetallicRoughness"]; - if (pbrValuesMap) { - NSDictionary *baseColorTextureMap = pbrValuesMap[@"baseColorTexture"]; - NSNumber *baseColorTextureIndexValue = baseColorTextureMap[@"index"]; - if (baseColorTextureIndexValue != nil) { - material.baseColorTexture = [[GLTFTextureInfo alloc] init]; - NSUInteger baseColorTextureIndex = baseColorTextureIndexValue.integerValue; - if (baseColorTextureIndex < _textures.count) { - material.baseColorTexture.texture = _textures[baseColorTextureIndex]; - } - } - NSNumber *baseColorTexCoordValue = baseColorTextureMap[@"texCoord"]; - if (baseColorTexCoordValue != nil) { - material.baseColorTexture.texCoord = baseColorTexCoordValue.integerValue; - } - - material.baseColorTexture.extras = baseColorTextureMap[@"extras"]; - material.baseColorTexture.extensions = baseColorTextureMap[@"extensions"]; - - NSArray *baseColorFactorComponents = pbrValuesMap[@"baseColorFactor"]; - if (baseColorFactorComponents.count == 4) { - material.baseColorFactor = GLTFVectorFloat4FromArray(baseColorFactorComponents); - } - - NSNumber *metallicFactor = pbrValuesMap[@"metallicFactor"]; - if (metallicFactor != nil) { - material.metalnessFactor = metallicFactor.floatValue; - } - - NSNumber *roughnessFactor = pbrValuesMap[@"roughnessFactor"]; - if (roughnessFactor != nil) { - material.roughnessFactor = roughnessFactor.floatValue; - } - - NSDictionary *metallicRoughnessTextureMap = pbrValuesMap[@"metallicRoughnessTexture"]; - NSNumber *metallicRoughnessTextureIndexValue = metallicRoughnessTextureMap[@"index"]; - if (metallicRoughnessTextureIndexValue != nil) { - material.metallicRoughnessTexture = [[GLTFTextureInfo alloc] init]; - NSUInteger metallicRoughnessTextureIndex = metallicRoughnessTextureIndexValue.integerValue; - if (metallicRoughnessTextureIndex < _textures.count) { - material.metallicRoughnessTexture.texture = _textures[metallicRoughnessTextureIndex]; - } - } - - NSNumber *metallicRoughnessTexCoordValue = metallicRoughnessTextureMap[@"texCoord"]; - if (metallicRoughnessTexCoordValue != nil) { - material.metallicRoughnessTexture.texCoord = metallicRoughnessTexCoordValue.integerValue; - } - - material.metallicRoughnessTexture.extras = metallicRoughnessTextureMap[@"extras"]; - material.metallicRoughnessTexture.extensions = metallicRoughnessTextureMap[@"extensions"]; - } - - NSDictionary *normalTextureMap = properties[@"normalTexture"]; - if (normalTextureMap) { - material.normalTexture = [[GLTFTextureInfo alloc] init]; - NSNumber *normalTextureIndexValue = normalTextureMap[@"index"]; - NSUInteger normalTextureIndex = normalTextureIndexValue.integerValue; - if (normalTextureIndex < _textures.count) { - material.normalTexture.texture = _textures[normalTextureIndex]; - } - NSNumber *normalTextureScaleValue = normalTextureMap[@"scale"]; - material.normalTextureScale = (normalTextureScaleValue != nil) ? normalTextureScaleValue.floatValue : 1.0; - - NSNumber *normalTexCoordValue = normalTextureMap[@"texCoord"]; - if (normalTexCoordValue != nil) { - material.normalTexture.texCoord = normalTexCoordValue.integerValue; - } - - material.normalTexture.extras = normalTextureMap[@"extras"]; - material.normalTexture.extensions = normalTextureMap[@"extensions"]; - } - - NSDictionary *emissiveTextureMap = properties[@"emissiveTexture"]; - if (emissiveTextureMap) { - material.emissiveTexture = [[GLTFTextureInfo alloc] init]; - NSNumber *emissiveTextureIndexValue = emissiveTextureMap[@"index"]; - NSUInteger emissiveTextureIndex = emissiveTextureIndexValue.integerValue; - if (emissiveTextureIndex < _textures.count) { - material.emissiveTexture.texture = _textures[emissiveTextureIndex]; - } - NSNumber *emissiveTexCoordValue = emissiveTextureMap[@"texCoord"]; - if (emissiveTexCoordValue != nil) { - material.emissiveTexture.texCoord = emissiveTexCoordValue.integerValue; - } - - material.emissiveTexture.extras = emissiveTextureMap[@"extras"]; - material.emissiveTexture.extensions = emissiveTextureMap[@"extensions"]; - } - - NSArray *emissiveFactorArray = properties[@"emissiveFactor"]; - if (emissiveFactorArray.count == 3) { - material.emissiveFactor = GLTFVectorFloat3FromArray(emissiveFactorArray); - } - - NSDictionary *occlusionTextureMap = properties[@"occlusionTexture"]; - if (occlusionTextureMap) { - material.occlusionTexture = [[GLTFTextureInfo alloc] init]; - NSNumber *occlusionTextureIndexValue = occlusionTextureMap[@"index"]; - NSUInteger occlusionTextureIndex = occlusionTextureIndexValue.integerValue; - if (occlusionTextureIndex < _textures.count) { - material.occlusionTexture.texture = _textures[occlusionTextureIndex]; - } - NSNumber *occlusionTexCoordValue = occlusionTextureMap[@"texCoord"]; - if (occlusionTexCoordValue != nil) { - material.occlusionTexture.texCoord = occlusionTexCoordValue.integerValue; - } - NSNumber *occlusionStrengthValue = occlusionTextureMap[@"strength"]; - if (occlusionStrengthValue != nil) { - material.occlusionStrength = occlusionStrengthValue.floatValue; - } - - material.occlusionTexture.extras = occlusionTextureMap[@"extras"]; - material.occlusionTexture.extensions = occlusionTextureMap[@"extensions"]; - } - - NSNumber *doubleSidedValue = properties[@"doubleSided"]; - material.doubleSided = (doubleSidedValue == nil) || (doubleSidedValue != nil && doubleSidedValue.boolValue); - - NSString *alphaMode = properties[@"alphaMode"]; - if ([alphaMode isEqualToString:@"BLEND"]) { - material.alphaMode = GLTFAlphaModeBlend; - } else if ([alphaMode isEqualToString:@"MASK"]) { - material.alphaMode = GLTFAlphaModeMask; - } else { - material.alphaMode = GLTFAlphaModeOpaque; - } - - NSNumber *alphaCutoffValue = properties[@"alphaCutoff"]; - if (alphaCutoffValue != nil) { - material.alphaCutoff = alphaCutoffValue.floatValue; - } - - material.name = properties[@"name"]; - material.extensions = properties[@"extensions"]; - material.extras = properties[@"extras"]; - - if (_usesPBRSpecularGlossiness) { - NSDictionary *pbrSpecularGlossinessProperties = material.extensions[GLTFExtensionKHRMaterialsPBRSpecularGlossiness]; - if (pbrSpecularGlossinessProperties != nil) { - NSDictionary *diffuseTextureMap = pbrSpecularGlossinessProperties[@"diffuseTexture"]; - if (diffuseTextureMap != nil) { - material.baseColorTexture = [[GLTFTextureInfo alloc] init]; - - NSNumber *diffuseTextureIndexValue = diffuseTextureMap[@"index"]; - if (diffuseTextureIndexValue != nil) { - NSUInteger diffuseTextureIndex = diffuseTextureIndexValue.integerValue; - if (diffuseTextureIndex < _textures.count) { - material.baseColorTexture.texture = _textures[diffuseTextureIndex]; - } - } - NSNumber *diffuseTexCoordValue = diffuseTextureMap[@"texCoord"]; - if (diffuseTexCoordValue != nil) { - material.baseColorTexture.texCoord = diffuseTexCoordValue.integerValue; - } - } - - // TODO: Support specularGlossinessTexture - - // TODO: Support texture transform of specular-glossiness map - - NSArray *diffuseFactorComponents = pbrSpecularGlossinessProperties[@"diffuseFactor"]; - if (diffuseFactorComponents.count == 4) { - material.baseColorFactor = GLTFVectorFloat4FromArray(diffuseFactorComponents); - } - - NSNumber *glossinessFactorValue = pbrSpecularGlossinessProperties[@"glossinessFactor"]; - material.glossinessFactor = (glossinessFactorValue != nil) ? glossinessFactorValue.floatValue : 0.0; - - NSArray *specularFactorComponents = pbrSpecularGlossinessProperties[@"specularFactor"]; - if (specularFactorComponents.count == 3) { - material.specularFactor = GLTFVectorFloat3FromArray(specularFactorComponents); - } - } - } - - if (_usesKHRMaterialsUnlit) { - NSDictionary *unlitMap = material.extensions[GLTFExtensionKHRMaterialsUnlit]; - if (unlitMap != nil) { - material.unlit = YES; - } - } - - if (_usesKHRTextureTransform) { - [self _fixMaterialTextureTransforms:material]; - } - - [materials addObject: material]; - } - - _materials = [materials copy]; - - return YES; -} - -- (GLTFTextureTransform)_textureTransformWithProperties:(NSDictionary *)properties { - GLTFTextureTransform transform = GLTFTextureTransformMakeIdentity(); - NSArray *offsetArray = properties[@"offset"]; - if (offsetArray != nil && offsetArray.count == 2) { - transform.offset = GLTFVectorFloat2FromArray(offsetArray); - } - NSNumber *rotationValue = properties[@"rotation"]; - if (rotationValue != nil) { - transform.rotation = rotationValue.floatValue; - } - NSArray *scaleArray = properties[@"scale"]; - if (scaleArray != nil && scaleArray.count == 2) { - transform.scale = GLTFVectorFloat2FromArray(scaleArray); - } - return transform; -} - -- (void)_fixMaterialTextureTransforms:(GLTFMaterial *)material { - NSDictionary *baseColorTransformProperties = material.baseColorTexture.extensions[GLTFExtensionKHRTextureTransform]; - if (baseColorTransformProperties != nil) { - material.baseColorTexture.transform = [self _textureTransformWithProperties:baseColorTransformProperties]; - NSNumber *texCoordValue = baseColorTransformProperties[@"texCoord"]; - if (texCoordValue != nil) { - material.baseColorTexture.texCoord = texCoordValue.intValue; - } - } - NSDictionary *normalTransformProperties = material.normalTexture.extensions[GLTFExtensionKHRTextureTransform]; - if (normalTransformProperties != nil) { - material.normalTexture.transform = [self _textureTransformWithProperties:normalTransformProperties]; - NSNumber *texCoordValue = normalTransformProperties[@"texCoord"]; - if (texCoordValue != nil) { - material.normalTexture.texCoord = texCoordValue.intValue; - } - } - NSDictionary *metallicRoughnessTransformProperties = material.metallicRoughnessTexture.extensions[GLTFExtensionKHRTextureTransform]; - if (metallicRoughnessTransformProperties != nil) { - material.metallicRoughnessTexture.transform = [self _textureTransformWithProperties:metallicRoughnessTransformProperties]; - NSNumber *texCoordValue = metallicRoughnessTransformProperties[@"texCoord"]; - if (texCoordValue != nil) { - material.metallicRoughnessTexture.texCoord = texCoordValue.intValue; - } - } - NSDictionary *occlusionTransformProperties = material.occlusionTexture.extensions[GLTFExtensionKHRTextureTransform]; - if (occlusionTransformProperties != nil) { - material.occlusionTexture.transform = [self _textureTransformWithProperties:occlusionTransformProperties]; - NSNumber *texCoordValue = occlusionTransformProperties[@"texCoord"]; - if (texCoordValue != nil) { - material.occlusionTexture.texCoord = texCoordValue.intValue; - } - } - NSDictionary *emissiveTransformProperties = material.emissiveTexture.extensions[GLTFExtensionKHRTextureTransform]; - if (emissiveTransformProperties != nil) { - material.emissiveTexture.transform = [self _textureTransformWithProperties:emissiveTransformProperties]; - NSNumber *texCoordValue = emissiveTransformProperties[@"texCoord"]; - if (texCoordValue != nil) { - material.emissiveTexture.texCoord = texCoordValue.intValue; - } - } - - material.hasTextureTransforms = YES; -} - -- (BOOL)loadNodes:(NSArray *)nodesMap { - if (nodesMap.count == 0) { - _nodes = @[]; - return YES; - } - - NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:nodesMap.count]; - for (NSDictionary *properties in nodesMap) { - GLTFNode *node = [[GLTFNode alloc] init]; - - NSString *cameraIdentifierString = properties[@"camera"]; - if (cameraIdentifierString) { - NSUInteger cameraIndex = cameraIdentifierString.integerValue; - if (cameraIndex < _cameras.count) { - GLTFCamera *camera = _cameras[cameraIndex]; - node.camera = camera; - camera.referencingNodes = [camera.referencingNodes arrayByAddingObject:node]; - } - } - - // Copy array of indices for now; we fix this up later in another pass once all nodes are in memory. - node.children = [properties[@"children"] copy]; - - NSNumber *skinIndexValue = properties[@"skin"]; - if (skinIndexValue != nil) { - NSUInteger skinIndex = skinIndexValue.integerValue; - if (skinIndex < _skins.count) { - node.skin = _skins[skinIndex]; - } - } - - node.jointName = properties[@"jointName"]; - - NSNumber *meshIndexValue = properties[@"mesh"]; - if (meshIndexValue != nil) { - NSUInteger meshIndex = meshIndexValue.integerValue; - if (meshIndex < _meshes.count) { - node.mesh = _meshes[meshIndex]; - } - } - - NSArray *matrixArray = properties[@"matrix"]; - if (matrixArray) { - node.localTransform = GLTFMatrixFloat4x4FromArray(matrixArray); - } - - NSArray *rotationArray = properties[@"rotation"]; - if (rotationArray) { - node.rotationQuaternion = GLTFQuaternionFromArray(rotationArray); - } - - NSArray *scaleArray = properties[@"scale"]; - if (scaleArray) { - node.scale = GLTFVectorFloat3FromArray(scaleArray); - } - - NSArray *translationArray = properties[@"translation"]; - if (translationArray) { - node.translation = GLTFVectorFloat3FromArray(translationArray); - } - - node.name = properties[@"name"]; - node.extensions = properties[@"extensions"]; - node.extras = properties[@"extras"]; - - if (_usesKHRLights) { - NSDictionary *lightProperties = node.extensions[GLTFExtensionKHRLights]; - NSNumber *lightIdentifierValue = lightProperties[@"light"]; - if (lightIdentifierValue && lightIdentifierValue.unsignedIntValue < _lights.count) { - node.light = _lights[lightIdentifierValue.integerValue]; - } - } - - [nodes addObject: node]; - } - - _nodes = [nodes copy]; - - return [self fixNodeRelationships]; -} - -- (BOOL)fixNodeRelationships { - for (GLTFNode *node in _nodes) { - NSArray *childIdentifiers = node.children; - NSMutableArray *children = [NSMutableArray arrayWithCapacity:childIdentifiers.count]; - for (NSNumber *childIndexValue in childIdentifiers) { - NSUInteger childIndex = childIndexValue.integerValue; - if (childIndex < _nodes.count) { - GLTFNode *child = _nodes[childIndex]; - child.parent = node; - [children addObject:child]; - } - } - node.children = children; - } - - for (GLTFSkin *skin in _skins) { - NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:skin.jointNodes.count]; - for (NSUInteger i = 0; i < skin.jointNodes.count; ++i) { - NSNumber *jointIndexValue = (NSNumber *)skin.jointNodes[i]; - if (jointIndexValue != nil && jointIndexValue.unsignedIntegerValue < _nodes.count) { - [nodes addObject:_nodes[jointIndexValue.intValue]]; - } - } - skin.jointNodes = [nodes copy]; - - NSNumber *skeletonIndexValue = (NSNumber *)skin.skeletonRootNode; - if (skeletonIndexValue != nil && skeletonIndexValue.unsignedIntegerValue < _nodes.count) { - skin.skeletonRootNode = _nodes[skeletonIndexValue.intValue]; - } - } - - return YES; -} - -- (BOOL)loadAnimations:(NSArray *)animationsMap { - if (animationsMap.count == 0) { - _animations = @[]; - return YES; - } - - NSArray *interpolationModes = @[ @"STEP", @"LINEAR", @"CUBICSPLINE" ]; - - NSMutableArray *animations = [NSMutableArray arrayWithCapacity:animationsMap.count]; - - for (NSDictionary *properties in animationsMap) { - GLTFAnimation *animation = [[GLTFAnimation alloc] init]; - - NSArray *samplersProperties = properties[@"samplers"]; - NSMutableArray *samplers = [NSMutableArray arrayWithCapacity:samplersProperties.count]; - [samplersProperties enumerateObjectsUsingBlock:^(NSDictionary *samplerProperties, NSUInteger index, BOOL *stop) { - GLTFAnimationSampler *sampler = [[GLTFAnimationSampler alloc] init]; - NSNumber *inputIndexValue = samplerProperties[@"input"]; - if (inputIndexValue && inputIndexValue.unsignedIntegerValue < _accessors.count) { - sampler.inputAccessor = _accessors[inputIndexValue.integerValue]; - } - NSNumber *outputIndexValue = samplerProperties[@"output"]; - if (outputIndexValue && outputIndexValue.unsignedIntegerValue < _accessors.count) { - sampler.outputAccessor = _accessors[outputIndexValue.integerValue]; - } - if (samplerProperties[@"interpolation"]) { - sampler.interpolationMode = (GLTFInterpolationMode)[interpolationModes indexOfObject:samplerProperties[@"interpolation"]]; - } - [samplers addObject:sampler]; - }]; - - animation.samplers = [samplers copy]; - - NSArray *channelsProperties = properties[@"channels"]; - NSMutableArray *channels = [NSMutableArray arrayWithCapacity:channelsProperties.count]; - [channelsProperties enumerateObjectsUsingBlock:^(NSDictionary *channelProperties, NSUInteger index, BOOL *stop) { - GLTFAnimationChannel *channel = [GLTFAnimationChannel new]; - NSNumber *samplerIndexValue = channelProperties[@"sampler"]; - if (samplerIndexValue && samplerIndexValue.unsignedIntegerValue < samplers.count) { - channel.sampler = samplers[samplerIndexValue.integerValue]; - } - NSDictionary *targetProperties = channelProperties[@"target"]; - NSNumber *targetNodeIndexValue = targetProperties[@"node"]; - if (targetNodeIndexValue && targetNodeIndexValue.unsignedIntegerValue < _nodes.count) { - channel.targetNode = _nodes[targetNodeIndexValue.integerValue]; - } - channel.targetPath = targetProperties[@"path"]; - [channels addObject:channel]; - }]; - - animation.channels = [channels copy]; - - animation.name = properties[@"name"]; - animation.extensions = properties[@"extensions"]; - animation.extras = properties[@"extras"]; - - [animations addObject: animation]; - } - - _animations = [animations copy]; - - return YES; -} - -- (BOOL)loadSkins:(NSArray *)skinsMap { - if (skinsMap.count == 0) { - _skins = @[]; - return YES; - } - - NSMutableArray *skins = [NSMutableArray arrayWithCapacity:skinsMap.count]; - for (NSDictionary *properties in skinsMap) { - GLTFSkin *skin = [[GLTFSkin alloc] init]; - - NSNumber *inverseBindMatricesAccessorIndexValue = properties[@"inverseBindMatrices"]; - if (inverseBindMatricesAccessorIndexValue != nil) { - NSUInteger inverseBindMatricesAccessorIndex = inverseBindMatricesAccessorIndexValue.unsignedIntegerValue; - if (inverseBindMatricesAccessorIndex < _accessors.count) { - skin.inverseBindMatricesAccessor = _accessors[inverseBindMatricesAccessorIndex]; - } - } - - NSArray *jointIndices = properties[@"joints"]; - if (jointIndices.count > 0) { - skin.jointNodes = [jointIndices copy]; - } - - NSNumber *skeletonIndexValue = properties[@"skeleton"]; - if (skeletonIndexValue != nil) { - skin.skeletonRootNode = (id)skeletonIndexValue; - } - - skin.name = properties[@"name"]; - skin.extensions = properties[@"extensions"]; - skin.extras = properties[@"extras"]; - - [skins addObject:skin]; - } - - _skins = [skins copy]; - - return YES; -} - -- (BOOL)loadScenes:(NSArray *)scenesMap { - if (scenesMap.count == 0) { - _scenes = @[]; - return YES; - } - - NSMutableArray *scenes = [NSMutableArray arrayWithCapacity:scenesMap.count]; - for (NSDictionary *properties in scenesMap) { - GLTFScene *scene = [[GLTFScene alloc] init]; - - NSArray *rootNodeIndices = properties[@"nodes"]; - NSMutableArray *rootNodes = [NSMutableArray arrayWithCapacity:rootNodeIndices.count]; - for (NSNumber *nodeIndexValue in rootNodeIndices) { - NSUInteger nodeIndex = nodeIndexValue.integerValue; - if (nodeIndex < _nodes.count) { - GLTFNode *node = _nodes[nodeIndex]; - [rootNodes addObject:node]; - } - } - scene.nodes = [rootNodes copy]; - - scene.name = properties[@"name"]; - scene.extensions = properties[@"extensions"]; - scene.extras = properties[@"extras"]; - - if (_usesKHRLights) { - NSDictionary *lightProperties = scene.extensions[GLTFExtensionKHRLights]; - NSNumber *lightIdentifierValue = lightProperties[@"light"]; - if (lightIdentifierValue != nil && lightIdentifierValue.unsignedIntegerValue < _lights.count) { - scene.ambientLight = _lights[lightIdentifierValue.integerValue]; - } - } - - [scenes addObject:scene]; - } - - _scenes = [scenes copy]; - - return YES; -} - -- (BOOL)loadDefaultScene:(NSNumber *)defaultSceneIndexValue -{ - if (defaultSceneIndexValue != nil) { - NSUInteger defaultSceneIndex = defaultSceneIndexValue.integerValue; - if (defaultSceneIndex < _scenes.count) { - _defaultScene = _scenes[defaultSceneIndex]; - } - } else { - _defaultScene = _scenes.firstObject; - } - - return YES; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.h b/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.h deleted file mode 100644 index cb4fd22591c4..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import - -extern const UInt32 GLTFBinaryMagic; - -typedef NS_ENUM(NSInteger, GLTFChunkType) { - GLTFChunkTypeJSON = 0x4E4F534A, - GLTFChunkTypeBinary = 0x004E4942 -}; - -typedef struct { - UInt32 magic; - UInt32 version; - UInt32 length; -} GLTFBinaryHeader; - -@interface GLTFBinaryChunk : NSObject -@property (nonatomic, assign) GLTFChunkType chunkType; -@property (nonatomic, strong) NSData *data; -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.mm b/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.mm deleted file mode 100644 index 415273fddf3c..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFBinaryChunk.mm +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFBinaryChunk.h" - -const UInt32 GLTFBinaryMagic = 0x46546C67; - -@implementation GLTFBinaryChunk -@end - diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBuffer.h b/platform/darwin/src/gltf/gltfkit/GLTFBuffer.h deleted file mode 100644 index a91cd8fda245..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFBuffer.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFObject.h" - -NS_ASSUME_NONNULL_BEGIN - -@protocol GLTFBuffer - -@property (nonatomic, readonly) NSInteger length; - -/// The actual data associated with this buffer. If uri is a data URI, this is populated when -/// loading; else it is nil -@property (nonatomic, readonly) void *contents; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBufferAllocator.h b/platform/darwin/src/gltf/gltfkit/GLTFBufferAllocator.h deleted file mode 100644 index 126168d7032b..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFBufferAllocator.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFBuffer.h" - -#import - -NS_ASSUME_NONNULL_BEGIN - -@protocol GLTFBufferAllocator -+ (uint64_t)liveAllocationSize; -- (id)newBufferWithLength:(NSInteger)length; -- (id)newBufferWithData:(NSData *)data; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBufferView.h b/platform/darwin/src/gltf/gltfkit/GLTFBufferView.h deleted file mode 100644 index 3f83f265f350..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFBufferView.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFEnums.h" -#import "GLTFObject.h" - -NS_ASSUME_NONNULL_BEGIN - -@protocol GLTFBuffer; - -@interface GLTFBufferView : GLTFObject -@property (nonatomic, weak) id buffer; -@property (nonatomic, assign) GLTFTarget target; -@property (nonatomic, assign) NSInteger length; -@property (nonatomic, assign) NSInteger offset; -@property (nonatomic, assign) NSInteger stride; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFBufferView.mm b/platform/darwin/src/gltf/gltfkit/GLTFBufferView.mm deleted file mode 100644 index 3d4ba74ec15a..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFBufferView.mm +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFBufferView.h" - -@implementation GLTFBufferView - -- (NSString *)description { - return [NSString stringWithFormat:@"GLTFBufferView: length: %d, offset: %d, stride: %d, target: %d, buffer: %@", - (int)self.length, (int)self.offset, (int)self.stride, (int)self.target, self.buffer]; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFCamera.h b/platform/darwin/src/gltf/gltfkit/GLTFCamera.h deleted file mode 100644 index 67d729b85c95..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFCamera.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFEnums.h" -#import "GLTFObject.h" - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFNode; - -@interface GLTFCamera : GLTFObject -@property (nonatomic, assign) GLTFCameraType cameraType; - -@property (nonatomic, assign) float aspectRatio; // Only applicable when type is perspective -@property (nonatomic, assign) float yfov; // Only applicable when type is perspective -@property (nonatomic, assign) float xmag; // Only applicable when type is orthographic -@property (nonatomic, assign) float ymag; // Only applicable when type is orthographic -@property (nonatomic, assign) float znear; -@property (nonatomic, assign) float zfar; - -@property (nonatomic, assign) simd_float4x4 projectionMatrix; - -@property (nonatomic, copy) NSArray *referencingNodes; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFCamera.mm b/platform/darwin/src/gltf/gltfkit/GLTFCamera.mm deleted file mode 100644 index fd2d9c27a169..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFCamera.mm +++ /dev/null @@ -1,115 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFCamera.h" - -@interface GLTFCamera () -@property (nonatomic, assign, getter=projectionMatrixIsDirty) BOOL projectionMatrixDirty; -@end - -@implementation GLTFCamera - -@synthesize projectionMatrix=_projectionMatrix; - -- (instancetype)init { - if ((self = [super init])) { - _referencingNodes = @[]; - } - return self; -} - -- (void)setCameraType:(GLTFCameraType)cameraType { - _cameraType = cameraType; - _projectionMatrixDirty = YES; -} - -- (void)setAspectRatio:(float)aspectRatio { - _aspectRatio = aspectRatio; - _projectionMatrixDirty = YES; -} - -- (void)setYfov:(float)yfov { - _yfov = yfov; - _projectionMatrixDirty = YES; -} - -- (void)setXmag:(float)xmag { - _xmag = xmag; - _projectionMatrixDirty = YES; -} - -- (void)setYmag:(float)ymag { - _ymag = ymag; - _projectionMatrixDirty = YES; -} - -- (void)setZnear:(float)znear { - _znear = znear; - _projectionMatrixDirty = YES; -} - -- (void)setZfar:(float)zfar { - _zfar = zfar; - _projectionMatrixDirty = YES; -} - -- (void)setProjectionMatrix:(simd_float4x4)projectionMatrix { - _projectionMatrix = projectionMatrix; - _projectionMatrixDirty = NO; -} - -- (simd_float4x4)projectionMatrix { - if (self.projectionMatrixIsDirty) { - [self _buildProjectionMatrix]; - } - return _projectionMatrix; -} - -- (void)_buildProjectionMatrix { - switch (_cameraType) { - case GLTFCameraTypeOrthographic: { - simd_float4 X = (simd_float4){ 1 / _xmag, 0, 0, 0 }; - simd_float4 Y = (simd_float4){ 0, 1 / _ymag, 0, 0 }; - simd_float4 Z = (simd_float4){ 0, 0, 2 / (_znear - _zfar), 0 }; - simd_float4 W = (simd_float4){ 0, 0, (_zfar + _znear) / (_znear - _zfar), 1 }; - _projectionMatrix = (simd_float4x4){ { X, Y, Z, W } }; - break; - } - case GLTFCameraTypePerspective: - default: { - simd_float4 X = (simd_float4){ 1 / (_aspectRatio * tanf(0.5 * _yfov)), 0, 0, 0 }; - simd_float4 Y = (simd_float4){ 0, 1 / tanf(0.5 * _yfov), 0, 0 }; - simd_float4 Z = (simd_float4){ 0, 0, -1, -1 }; - simd_float4 W = (simd_float4){ 0, 0, -2 * _znear, 0 }; - if (_zfar != FLT_MAX) { - Z = (simd_float4){ 0, 0, (_zfar + _znear) / (_znear - _zfar), -1 }; - W = (simd_float4){ 0, 0, (2 * _zfar * _znear) / (_znear - _zfar), 0 }; - } - _projectionMatrix = (simd_float4x4){ { X, Y, Z, W } }; - break; - } - } - simd_float4x4 glToMetal = (simd_float4x4){{ - { 1, 0, 0, 0 }, - { 0, 1, 0, 0 }, - { 0, 0, 0.5, 0 }, - { 0, 0, 0.5, 1 }, - }}; - _projectionMatrix = simd_mul(glToMetal, _projectionMatrix); - _projectionMatrixDirty = NO; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.h b/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.h deleted file mode 100644 index 8382ba773a9f..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import - -#import "GLTFBufferAllocator.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface GLTFDefaultBufferAllocator : NSObject - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.mm b/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.mm deleted file mode 100644 index d27ceba2cbfb..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFDefaultBufferAllocator.mm +++ /dev/null @@ -1,93 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFDefaultBufferAllocator.h" - -static uint64_t _liveAllocationSize; - -@interface GLTFDefaultBufferAllocator () -+ (void)incrementLiveAllocationSizeByLength:(uint64_t)length; -+ (void)decrementLiveAllocationSizeByLength:(uint64_t)length; -@end - -@interface GLTFMemoryBuffer: NSObject -@property (nonatomic, assign) void *bytes; -@property (nonatomic, assign) NSInteger length; -- (instancetype)initWithLength:(NSInteger)length; -- (instancetype)initWithData:(NSData *)data; -@end - -@implementation GLTFMemoryBuffer - -@synthesize name; -@synthesize extras; -@synthesize extensions; - -- (instancetype)initWithLength:(NSInteger)length { - if ((self = [super init])) { - _bytes = malloc(length); - _length = length; - [GLTFDefaultBufferAllocator incrementLiveAllocationSizeByLength:_length]; - } - return self; -} - -- (instancetype)initWithData:(NSData *)data { - if ((self = [super init])) { - _length = data.length; - _bytes = malloc(_length); - memcpy(_bytes, data.bytes, _length); - [GLTFDefaultBufferAllocator incrementLiveAllocationSizeByLength:_length]; - } - return self; -} - -- (void)dealloc { - free(_bytes); - [GLTFDefaultBufferAllocator decrementLiveAllocationSizeByLength:_length]; -} - -- (void *)contents NS_RETURNS_INNER_POINTER { - return self.bytes; -} - -@end - -@implementation GLTFDefaultBufferAllocator - -+ (void)incrementLiveAllocationSizeByLength:(uint64_t)length { - _liveAllocationSize += length; -} - -+ (void)decrementLiveAllocationSizeByLength:(uint64_t)length { - _liveAllocationSize -= length; -} - -+ (uint64_t)liveAllocationSize { - return _liveAllocationSize; -} - -- (id)newBufferWithLength:(NSInteger)length { - GLTFMemoryBuffer *buffer = [[GLTFMemoryBuffer alloc] initWithLength:length]; - return buffer; -} - -- (id)newBufferWithData:(NSData *)data { - GLTFMemoryBuffer *buffer = [[GLTFMemoryBuffer alloc] initWithData:data]; - return buffer; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFEnums.h b/platform/darwin/src/gltf/gltfkit/GLTFEnums.h deleted file mode 100644 index 76bffbc8779a..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFEnums.h +++ /dev/null @@ -1,178 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import - -typedef NS_ENUM(NSInteger, GLTFDataType) { - GLTFBaseTypeUnknown, - GLTFDataTypeChar = 0x1400, - GLTFDataTypeUChar = 0x1401, - GLTFDataTypeShort = 0x1402, - GLTFDataTypeUShort = 0x1403, - GLTFDataTypeInt = 0x1404, - GLTFDataTypeUInt = 0x1405, - GLTFDataTypeFloat = 0x1406, - - GLTFDataTypeFloat2 = 0x8B50, - GLTFDataTypeFloat3 = 0x8B51, - GLTFDataTypeFloat4 = 0x8B52, - GLTFDataTypeInt2 = 0x8B53, - GLTFDataTypeInt3 = 0x8B54, - GLTFDataTypeInt4 = 0x8B55, - GLTFDataTypeBool = 0x8B56, - GLTFDataTypeBool2 = 0x8B57, - GLTFDataTypeBool3 = 0x8B58, - GLTFDataTypeBool4 = 0x8B59, - GLTFDataTypeFloat2x2 = 0x8B5A, - GLTFDataTypeFloat3x3 = 0x8B5B, - GLTFDataTypeFloat4x4 = 0x8B5C, - GLTFDataTypeSampler2D = 0x8B5E, -}; - -typedef NS_ENUM(NSInteger, GLTFDataDimension) { - GLTFDataDimensionUnknown, - GLTFDataDimensionScalar, - GLTFDataDimensionVector2, - GLTFDataDimensionVector3, - GLTFDataDimensionVector4, - GLTFDataDimensionMatrix2x2, - GLTFDataDimensionMatrix3x3, - GLTFDataDimensionMatrix4x4, -}; - -typedef NS_ENUM(NSInteger, GLTFTarget) { - GLTFTargetUnknown, - GLTFTargetArrayBuffer = 0x8892, - GLTFTargetElementArrayBuffer = 0x8893, -}; - -typedef NS_ENUM(NSInteger, GLTFPrimitiveType) { - GLTFPrimitiveTypePoints, - GLTFPrimitiveTypeLines, - GLTFPrimitiveTypeLineLoop, - GLTFPrimitiveTypeLineStrip, - GLTFPrimitiveTypeTriangles, - GLTFPrimitiveTypeTriangleStrip, - GLTFPrimitiveTypeTriangleFan, -}; - -typedef NS_ENUM(NSInteger, GLTFCameraType) { - GLTFCameraTypePerspective, - GLTFCameraTypeOrthographic, -}; - -typedef NS_ENUM(NSInteger, GLTFTextureTarget) { - GLTFTextureTargetTexture2D = 0x0DE1, -}; - -typedef NS_ENUM(NSInteger, GLTFTextureFormat) { - GLTFTextureFormatUnknown, - GLTFTextureFormatAlpha = 0x1906, - GLTFTextureFormatRGB = 0x1907, - GLTFTextureFormatRGBA = 0x1908, - GLTFTextureFormatLuminance = 0x1909, - GLTFTextureFormatLuminanceAlpha = 0x190A, -}; - -typedef NS_ENUM(NSInteger, GLTFTextureType) { - GLTFTextureTypeUnknown, - GLTFTextureTypeUChar = 0x1401, - GLTFTextureTypeUShort565 = 0x8363, - GLTFTextureTypeUShort4444 = 0x8033, - GLTFTextureTypeUShort5551 = 0x8034, -}; - -typedef NS_ENUM(NSInteger, GLTFShaderType) { - GLTFShaderTypeVertex = 0x8B31, - GLTFShaderTypeFragment = 0x8B30, -}; - -typedef NS_ENUM(NSInteger, GLTFSamplingFilter) { - GLTFSamplingFilterUnknown, - GLTFSamplingFilterNearest = 0x2600, - GLTFSamplingFilterLinear = 0x2601, - GLTFSamplingFilterNearestMipNearest = 0x2700, - GLTFSamplingFilterLinearMipNearest = 0x2701, - GLTFSamplingFilterNearestMipLinear = 0x2702, - GLTFSamplingLinearMipLinear = 0x2703, -}; - -typedef NS_ENUM(NSInteger, GLTFAddressMode) { - GLTFAddressModeUnknown, - GLTFAddressModeClampToEdge = 0x812F, - GLTFAddressModeMirroredRepeat = 0x8370, - GLTFAddressModeRepeat = 0x2901, -}; - -typedef NS_ENUM(NSInteger, GLTFComparisonFunc) { - GLTFComparisonFuncLess = 0x0201, - GLTFComparisonFuncEqual = 0x0202, - GLTFComparisonFuncLessEqual = 0x0203, - GLTFComparisonFuncGreater = 0x0204, - GLTFComparisonFuncNotEqual = 0x0205, - GLTFComparisonFuncGreaterEqual = 0x0206, - GLTFComparisonFuncAlways = 0x0207, -}; - -typedef NS_ENUM(NSInteger, GLTFFace) { - GLTFFaceFront = 0x0404, - GLTFFaceBack = 0x405, - GLTFFaceFrontAndBack = 0x408, -}; - -typedef NS_ENUM(NSInteger, GLTFWinding) { - GLTFWindingClockwise = 0x900, - GLTFWindingCounterclockwise = 0x0901, -}; - -typedef NS_ENUM(NSInteger, GLTFState) { - GLTFStateBlendingEnabled = 0x0BE2, - GLTFStateCullFaceEnabled = 0x0B44, - GLTFStateDepthTestEnabled = 0x0B71, - GLTFStatePolygonOffsetFillEnabled = 0x8037, - GLTFStateAlphaToCoverageEnabled = 0x809E, - GLTFStateScissorTestEnabled = 0x0C11, -}; - -typedef NS_ENUM(NSInteger, GLTFBlendFunction) { - GLTFBlendFunctionAdd = 0x8006, - GLTFBlendFunctionSubtract = 0x800A, - GLTFBlendFunctionReverseSubtract = 0x800B, -}; - -typedef NS_ENUM(NSInteger, GLTFBlendEquation) { - GLTFBlendEquationZero = 0x0000, - GLTFBlendEquationOne = 0x0001, - GLTFBlendEquationSrcColor = 0x0300, - GLTFBlendEquationOneMinusSrcColor = 0x0301, - GLTFBlendEquationSrcAlpha = 0x0302, - GLTFBlendEquationOneMinusSrcAlpha = 0x0303, - GLTFBlendEquationDestAlpha = 0x0304, - GLTFBlendEquationOneMinusDestAlpha = 0x0305, - GLTFBlendEquationDestColor = 0x0306, - GLTFBlendEquationOneMinusDestColor = 0x0307, - GLTFBlendEquationSrcAlphaSaturate = 0x0308, - GLTFBlendEquationConstantColor = 0x8001, - GLTFBlendEquationOneMinusConstColor = 0x8002, - GLTFBlendEquationConstantAlpha = 0x8003, - GLTFBlendEquationOneMinusConstAlpha = 0x8004, -}; - -typedef NS_ENUM(NSInteger, GLTFInterpolationMode) { - GLTFInterpolationModeStep, - GLTFInterpolationModeLinear, - GLTFInterpolationModeCubic, -}; diff --git a/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.h b/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.h deleted file mode 100644 index b219b6c004dd..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import - -extern NSString *const GLTFExtensionKHRMaterialsPBRSpecularGlossiness; -extern NSString *const GLTFExtensionKHRLights; -extern NSString *const GLTFExtensionKHRMaterialsUnlit; -extern NSString *const GLTFExtensionKHRTextureTransform; -extern NSString *const GLTFExtensionEXTPBRAttributes; diff --git a/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.mm b/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.mm deleted file mode 100644 index a531b33a8987..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFExtensionNames.mm +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFExtensionNames.h" - -NSString *const GLTFExtensionKHRMaterialsPBRSpecularGlossiness = @"KHR_materials_pbrSpecularGlossiness"; -NSString *const GLTFExtensionKHRLights = @"KHR_lights"; -NSString *const GLTFExtensionKHRMaterialsUnlit = @"KHR_materials_unlit"; -NSString *const GLTFExtensionKHRTextureTransform = @"KHR_texture_transform"; -NSString *const GLTFExtensionEXTPBRAttributes = @"EXT_pbr_attributes"; diff --git a/platform/darwin/src/gltf/gltfkit/GLTFImage.h b/platform/darwin/src/gltf/gltfkit/GLTFImage.h deleted file mode 100644 index fe621ff196b6..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFImage.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFBufferView.h" -#import "GLTFObject.h" - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface GLTFImage : GLTFObject - -/// A reference to a buffer view containing image data, if url is nil -@property (nonatomic, strong) GLTFBufferView *_Nullable bufferView; - -/// The MIME type of the data contained in this image's buffer view -@property (nonatomic, copy) NSString *_Nullable mimeType; - -/// A file URL, if the URI was not a decodable data-uri; otherwise nil -@property (nonatomic, copy) NSURL *_Nullable url; - -/// A data object containing the data encoded in the image's data-uri, if present; otherwise nil -@property (nonatomic, strong) NSData *imageData; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFImage.mm b/platform/darwin/src/gltf/gltfkit/GLTFImage.mm deleted file mode 100644 index b45f287d95e1..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFImage.mm +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFImage.h" - -#import - -@implementation GLTFImage - -+ (CGImageRef)newImageForData:(NSData *)data mimeType:(NSString *)mimeType { - CGImageRef image = NULL; - CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data); - if ([mimeType isEqualToString:@"image/jpeg"]) { - image = CGImageCreateWithJPEGDataProvider(provider, NULL, false, kCGRenderingIntentDefault); - } else if ([mimeType isEqualToString:@"image/png"]) { - image = CGImageCreateWithPNGDataProvider(provider, NULL, false, kCGRenderingIntentDefault); - } else { - NSLog(@"Unknown MIME type encountered when decoding image: %@", mimeType); - } - CGDataProviderRelease(provider); - return image; -} - -+ (CGImageRef)newImageForDataURI:(NSString *)uriData { - NSString *prefix = @"data:"; - if ([uriData hasPrefix:prefix]) { - NSInteger prefixEnd = prefix.length; - NSInteger firstComma = [uriData rangeOfString:@","].location; - if (firstComma != NSNotFound) { - NSString *mediaTypeAndTokenString = [uriData substringWithRange:NSMakeRange(prefixEnd, firstComma - prefixEnd)]; - NSArray *mediaTypeAndToken = [mediaTypeAndTokenString componentsSeparatedByString:@";"]; - if (mediaTypeAndToken.count > 0) { - NSString *mediaType = mediaTypeAndToken.firstObject; - NSString *encodedImageData = [uriData substringFromIndex:firstComma + 1]; - NSData *imageData = [[NSData alloc] initWithBase64EncodedString:encodedImageData - options:NSDataBase64DecodingIgnoreUnknownCharacters]; - return [self newImageForData:imageData mimeType:mediaType]; - } - } - } - return NULL; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.h b/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.h deleted file mode 100644 index 9139bacf582d..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.h +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFObject.h" - -#import - -typedef NS_ENUM(NSInteger, GLTFKHRLightType) { - GLTFKHRLightTypeAmbient, - GLTFKHRLightTypeDirectional, - GLTFKHRLightTypePoint, - GLTFKHRLightTypeSpot, -}; - -@interface GLTFKHRLight : GLTFObject - -@property (nonatomic, assign) GLTFKHRLightType type; - -/// Color of light in a linear RGB color space -@property (nonatomic, assign) simd_float4 color; - -/// Brightness of light. Point and spot lights use luminous intensity in candela (lm/sr), -/// while directional lights use illuminance in lux (lm/m^2). -@property (nonatomic, assign) float intensity; - -/// Distance threshold at which the light's intensity may be considered to have reached zero, -/// expressed in meters. Default is 0, signifying effectively infinite range. -@property (nonatomic, assign) float range; - -/// Angle, in radians, from the center of a spotlight to where falloff begins. -/// Must be greater than or equal to 0, less than or equal to `outerConeAngle`, -/// and less than pi / 2. Default value is 0. -@property (nonatomic, assign) float innerConeAngle; - -/// Angle, in radians, from the center of a spotlight to where falloff ends. -/// Must be greater than or equal to 0, greater than or equal to `innerConeAngle`, -/// and less than pi / 2. Default value is pi / 4. -@property (nonatomic, assign) float outerConeAngle; - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.mm b/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.mm deleted file mode 100644 index eff3be6aeff2..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFKHRLight.mm +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFKHRLight.h" - -@implementation GLTFKHRLight - -- (instancetype)init { - if ((self = [super init])) { - _type = GLTFKHRLightTypeDirectional; - _color = (simd_float4){ 1, 1, 1, 1 }; - _intensity = 1; - _range = 0; - _innerConeAngle = 0; - _outerConeAngle = M_PI_4; - } - return self; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.h b/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.h deleted file mode 100644 index 07abe678380d..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import -#import -#import "GLTFBuffer.h" -#import "GLTFBufferAllocator.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface GLTFMTLBuffer : NSObject - -@property (nonatomic, readonly) id buffer; - -@end - -@interface GLTFMTLBufferAllocator : NSObject - -- (instancetype)initWithDevice:(id)device; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.mm b/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.mm deleted file mode 100644 index c1bf44f1387d..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLBufferAllocator.mm +++ /dev/null @@ -1,101 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFMTLBufferAllocator.h" - -#import - -static uint64_t _liveAllocationSize; - -@interface GLTFMTLBufferAllocator () -+ (void)incrementLiveAllocationSizeByLength:(uint64_t)length; -+ (void)decrementLiveAllocationSizeByLength:(uint64_t)length; -@end - -@interface GLTFMTLBuffer () -@property (nonatomic, strong) id buffer; - -- (instancetype)initWithBuffer:(id)buffer; - -@end - -@implementation GLTFMTLBuffer - -@synthesize name; -@synthesize extras; -@synthesize extensions; - -- (instancetype)initWithBuffer:(id)buffer { - if ((self = [super init])) { - _buffer = buffer; - [GLTFMTLBufferAllocator incrementLiveAllocationSizeByLength:_buffer.length]; - } - return self; -} - -- (void)dealloc { - [GLTFMTLBufferAllocator decrementLiveAllocationSizeByLength:_buffer.length]; -} - -- (NSInteger)length { - return [self.buffer length]; -} - -- (void *)contents { - return [self.buffer contents]; -} - -@end - -@interface GLTFMTLBufferAllocator () -@property (nonatomic, strong) id device; -@end - -@implementation GLTFMTLBufferAllocator - -+ (void)incrementLiveAllocationSizeByLength:(uint64_t)length { - _liveAllocationSize += length; -} - -+ (void)decrementLiveAllocationSizeByLength:(uint64_t)length { - _liveAllocationSize -= length; -} - -+ (uint64_t)liveAllocationSize { - return _liveAllocationSize; -} - -- (instancetype)initWithDevice:(id)device { - if ((self = [super init])) { - _device = device; - } - return self; -} - -- (id)newBufferWithLength:(NSInteger)length { - MTLResourceOptions options = MTLResourceCPUCacheModeDefaultCache | MTLResourceStorageModeShared; - id underlying = [self.device newBufferWithLength:length options:options]; - return [[GLTFMTLBuffer alloc] initWithBuffer:underlying]; -} - - -- (id)newBufferWithData:(NSData *)data { - MTLResourceOptions options = MTLResourceCPUCacheModeDefaultCache | MTLResourceStorageModeShared; - id underlying = [self.device newBufferWithBytes:data.bytes length:data.length options:options]; - return [[GLTFMTLBuffer alloc] initWithBuffer:underlying]; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.h b/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.h deleted file mode 100644 index 4c664894ad71..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFMTLUtilities.h" -#import "GLTFMesh.h" - -#import - -// Maximum number of textures supplied by a material; excludes IBL textures, etc. - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFMTLLightingEnvironment; - -@interface GLTFMTLShaderBuilder : NSObject - -- (id) - renderPipelineStateForSubmesh:(GLTFSubmesh *)submesh - // lightingEnvironment:(GLTFMTLLightingEnvironment * _Nullable)lightingEnvironment - colorPixelFormat:(MTLPixelFormat)colorPixelFormat - depthStencilPixelFormat:(MTLPixelFormat)depthStencilPixelFormat - sampleCount:(int)sampleCount - device:(id)device; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.mm b/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.mm deleted file mode 100644 index 8045d13e9f1c..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLShaderBuilder.mm +++ /dev/null @@ -1,246 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - - -#import "GLTFMTLShaderBuilder.h" -#import "GLTFMesh.h" -#import "GLTFMaterial.h" -#import "GLTFVertexDescriptor.h" -#import "GLTFAccessor.h" -#import "../GLTFMath.hpp" - -@implementation GLTFMTLShaderBuilder - -- (id)renderPipelineStateForSubmesh:(GLTFSubmesh *)submesh - // lightingEnvironment:(GLTFMTLLightingEnvironment *)lightingEnvironment - colorPixelFormat:(MTLPixelFormat)colorPixelFormat - depthStencilPixelFormat:(MTLPixelFormat)depthStencilPixelFormat - sampleCount:(int)sampleCount - device:(id)device -{ - NSParameterAssert(submesh); - NSParameterAssert(submesh.material); - NSParameterAssert(submesh.vertexDescriptor); - - NSError *error = nil; - NSString *shaderSource = [self shaderSource]; - - shaderSource = [self rewriteSource:shaderSource forSubmesh:submesh]; - - id library = [device newLibraryWithSource:shaderSource options:nil error:&error]; - if (!library) { - NSLog(@"Error occurred while creating library for material : %@", error); - return nil; - } - - id vertexFunction = nil; - id fragmentFunction = nil; - - for (NSString *functionName in [library functionNames]) { - id function = [library newFunctionWithName:functionName]; - if ([function functionType] == MTLFunctionTypeVertex) { - vertexFunction = function; - } else if ([function functionType] == MTLFunctionTypeFragment) { - fragmentFunction = function; - } - } - - if (!vertexFunction || !fragmentFunction) { - NSLog(@"Failed to find a vertex and fragment function in library source"); - return nil; - } - - MTLVertexDescriptor *vertexDescriptor = [self vertexDescriptorForSubmesh: submesh]; - - MTLRenderPipelineDescriptor *pipelineDescriptor = [MTLRenderPipelineDescriptor new]; - pipelineDescriptor.vertexFunction = vertexFunction; - pipelineDescriptor.fragmentFunction = fragmentFunction; - pipelineDescriptor.vertexDescriptor = vertexDescriptor; - - pipelineDescriptor.colorAttachments[0].pixelFormat = colorPixelFormat; - pipelineDescriptor.sampleCount = sampleCount; - - if (submesh.material.alphaMode == GLTFAlphaModeBlend) { - pipelineDescriptor.colorAttachments[0].blendingEnabled = YES; - pipelineDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; - pipelineDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd; - pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne; - pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne; - pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha; - pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha; - } - - pipelineDescriptor.depthAttachmentPixelFormat = depthStencilPixelFormat; - pipelineDescriptor.stencilAttachmentPixelFormat = depthStencilPixelFormat; - - id pipeline = [device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:&error]; - if (!pipeline) { - NSLog(@"Error occurred when creating render pipeline state: %@", error); - } - - return pipeline; -} - -- (NSString *)shaderSource { - NSError *error = nil; - // TODO: Figure out why Bazel won't embed the .metal files - NSURL *shaderURL = [[NSBundle mainBundle] URLForResource:@"pbr" withExtension:@"txt"]; - if (shaderURL == nil) { - NSLog(@"ERROR: Shader source not found in main bundle; pipeline states cannot be generated"); - } - return [NSString stringWithContentsOfURL:shaderURL encoding:NSUTF8StringEncoding error:&error]; -} - -- (NSString *)rewriteSource:(NSString *)source - forSubmesh:(GLTFSubmesh *)submesh -{ - GLTFMaterial *material = submesh.material; - - BOOL usePBR = YES; - BOOL useIBL = NO; // lightingEnvironment != nil; - BOOL useDoubleSided = material.isDoubleSided; - BOOL hasTexCoord0 = submesh.accessorsForAttributes[GLTFAttributeSemanticTexCoord0] != nil; - BOOL hasTexCoord1 = submesh.accessorsForAttributes[GLTFAttributeSemanticTexCoord1] != nil; - BOOL hasNormals = submesh.accessorsForAttributes[GLTFAttributeSemanticNormal] != nil; - BOOL hasTangents = submesh.accessorsForAttributes[GLTFAttributeSemanticTangent] != nil; - BOOL hasBaseColorMap = material.baseColorTexture != nil; - BOOL hasOcclusionMap = material.occlusionTexture != nil; - BOOL hasEmissiveMap = material.emissiveTexture != nil; - BOOL hasNormalMap = material.normalTexture != nil; - BOOL hasMetallicRoughnessMap = material.metallicRoughnessTexture != nil; - BOOL hasTextureTransforms = material.hasTextureTransforms; - BOOL hasSkinningData = submesh.accessorsForAttributes[GLTFAttributeSemanticJoints0] != nil && - submesh.accessorsForAttributes[GLTFAttributeSemanticWeights0] != nil; - BOOL hasExtendedSkinning = submesh.accessorsForAttributes[GLTFAttributeSemanticJoints1] != nil && - submesh.accessorsForAttributes[GLTFAttributeSemanticWeights1] != nil; - BOOL hasVertexColor = submesh.accessorsForAttributes[GLTFAttributeSemanticColor0] != nil; - BOOL vertexColorIsRGB = submesh.accessorsForAttributes[GLTFAttributeSemanticColor0].dimension == GLTFDataDimensionVector3; - BOOL hasVertexRoughness = submesh.accessorsForAttributes[GLTFAttributeSemanticRoughness] != nil; - BOOL hasVertexMetallic = submesh.accessorsForAttributes[GLTFAttributeSemanticMetallic] != nil; - BOOL premultiplyBaseColor = material.alphaMode == GLTFAlphaModeBlend; - BOOL materialIsUnlit = material.isUnlit; - BOOL useAlphaTest = material.alphaMode == GLTFAlphaModeMask; - - NSMutableString *shaderFeatures = [NSMutableString string]; - [shaderFeatures appendFormat:@"#define USE_PBR %d\n", usePBR]; - [shaderFeatures appendFormat:@"#define USE_IBL %d\n", useIBL]; - [shaderFeatures appendFormat:@"#define USE_ALPHA_TEST %d\n", useAlphaTest]; - [shaderFeatures appendFormat:@"#define USE_VERTEX_SKINNING %d\n", hasSkinningData]; - [shaderFeatures appendFormat:@"#define USE_EXTENDED_VERTEX_SKINNING %d\n", hasExtendedSkinning]; - [shaderFeatures appendFormat:@"#define USE_DOUBLE_SIDED_MATERIAL %d\n", useDoubleSided]; - [shaderFeatures appendFormat:@"#define HAS_TEXCOORD_0 %d\n", hasTexCoord0]; - [shaderFeatures appendFormat:@"#define HAS_TEXCOORD_1 %d\n", hasTexCoord1]; - [shaderFeatures appendFormat:@"#define HAS_NORMALS %d\n", hasNormals]; - [shaderFeatures appendFormat:@"#define HAS_TANGENTS %d\n", hasTangents]; - [shaderFeatures appendFormat:@"#define HAS_VERTEX_COLOR %d\n", hasVertexColor]; - [shaderFeatures appendFormat:@"#define VERTEX_COLOR_IS_RGB %d\n", vertexColorIsRGB]; - [shaderFeatures appendFormat:@"#define HAS_BASE_COLOR_MAP %d\n", hasBaseColorMap]; - [shaderFeatures appendFormat:@"#define HAS_NORMAL_MAP %d\n", hasNormalMap]; - [shaderFeatures appendFormat:@"#define HAS_METALLIC_ROUGHNESS_MAP %d\n", hasMetallicRoughnessMap]; - [shaderFeatures appendFormat:@"#define HAS_OCCLUSION_MAP %d\n", hasOcclusionMap]; - [shaderFeatures appendFormat:@"#define HAS_EMISSIVE_MAP %d\n", hasEmissiveMap]; - [shaderFeatures appendFormat:@"#define HAS_VERTEX_ROUGHNESS %d\n", hasVertexRoughness]; - [shaderFeatures appendFormat:@"#define HAS_VERTEX_METALLIC %d\n", hasVertexMetallic]; - [shaderFeatures appendFormat:@"#define HAS_TEXTURE_TRANSFORM %d\n", hasTextureTransforms]; - [shaderFeatures appendFormat:@"#define PREMULTIPLY_BASE_COLOR %d\n", premultiplyBaseColor]; - [shaderFeatures appendFormat:@"#define MATERIAL_IS_UNLIT %d\n", materialIsUnlit]; - [shaderFeatures appendFormat:@"#define SPECULAR_ENV_MIP_LEVELS %d\n", 0]; // lightingEnvironment.specularMipLevelCount]; - [shaderFeatures appendFormat:@"#define MAX_LIGHTS %d\n", (int)GLTFMTLMaximumLightCount]; - [shaderFeatures appendFormat:@"#define MAX_MATERIAL_TEXTURES %d\n\n", (int)GLTFMTLMaximumTextureCount]; - - [shaderFeatures appendFormat:@"#define BaseColorTexCoord texCoord%d\n", (int)material.baseColorTexture.texCoord]; - [shaderFeatures appendFormat:@"#define NormalTexCoord texCoord%d\n", (int)material.normalTexture.texCoord]; - [shaderFeatures appendFormat:@"#define MetallicRoughnessTexCoord texCoord%d\n", (int)material.metallicRoughnessTexture.texCoord]; - [shaderFeatures appendFormat:@"#define EmissiveTexCoord texCoord%d\n", (int)material.emissiveTexture.texCoord]; - [shaderFeatures appendFormat:@"#define OcclusionTexCoord texCoord%d\n\n", (int)material.occlusionTexture.texCoord]; - - NSString *preamble = @"struct VertexIn {\n"; - NSString *epilogue = @"\n};"; - - NSMutableArray *attribs = [NSMutableArray array]; - int i = 0; - for (GLTFVertexAttribute *attribute in submesh.vertexDescriptor.attributes) { - if (attribute.componentType == GLTFBaseTypeUnknown) { continue; } - if ([attribute.semantic isEqualToString:GLTFAttributeSemanticPosition]) { - [attribs addObject:[NSString stringWithFormat:@" %@ position [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticNormal]) { - [attribs addObject:[NSString stringWithFormat:@" %@ normal [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticTangent]) { - [attribs addObject:[NSString stringWithFormat:@" %@ tangent [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticTexCoord0]) { - [attribs addObject:[NSString stringWithFormat:@" %@ texCoord0 [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticTexCoord1]) { - [attribs addObject:[NSString stringWithFormat:@" %@ texCoord1 [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticColor0]) { - [attribs addObject:[NSString stringWithFormat:@" %@ color [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticJoints0]) { - [attribs addObject:[NSString stringWithFormat:@" %@ joints0 [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticJoints1]) { - [attribs addObject:[NSString stringWithFormat:@" %@ joints1 [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticWeights0]) { - [attribs addObject:[NSString stringWithFormat:@" %@ weights0 [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticWeights1]) { - [attribs addObject:[NSString stringWithFormat:@" %@ weights1 [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticRoughness]) { - [attribs addObject:[NSString stringWithFormat:@" %@ roughness [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } else if ([attribute.semantic isEqualToString:GLTFAttributeSemanticMetallic]) { - [attribs addObject:[NSString stringWithFormat:@" %@ metalness [[attribute(%d)]];", GLTFMTLTypeNameForType(attribute.componentType, attribute.dimension, false), i]]; - } - - ++i; - } - - NSString *decls = [NSString stringWithFormat:@"%@%@%@%@", - shaderFeatures, preamble, [attribs componentsJoinedByString:@"\n"], epilogue]; - - NSRange startSigilRange = [source rangeOfString:@"/*%begin_replace_decls%*/"]; - NSRange endSigilRange = [source rangeOfString:@"/*%end_replace_decls%*/"]; - - NSRange declRange = NSUnionRange(startSigilRange, endSigilRange); - - source = [source stringByReplacingCharactersInRange:declRange withString:decls]; - - return source; -} - -- (MTLVertexDescriptor *)vertexDescriptorForSubmesh:(GLTFSubmesh *)submesh { - MTLVertexDescriptor *vertexDescriptor = [MTLVertexDescriptor new]; - - GLTFVertexDescriptor *descriptor = submesh.vertexDescriptor; - - for (NSInteger attributeIndex = 0; attributeIndex < GLTFVertexDescriptorMaxAttributeCount; ++attributeIndex) { - GLTFVertexAttribute *attribute = descriptor.attributes[attributeIndex]; - GLTFBufferLayout *layout = descriptor.bufferLayouts[attributeIndex]; - - if (attribute.componentType == 0) { - continue; - } - - MTLVertexFormat vertexFormat = GLTFMTLVertexFormatForComponentTypeAndDimension(attribute.componentType, attribute.dimension); - - vertexDescriptor.attributes[attributeIndex].offset = 0; - vertexDescriptor.attributes[attributeIndex].format = vertexFormat; - vertexDescriptor.attributes[attributeIndex].bufferIndex = attributeIndex; - - vertexDescriptor.layouts[attributeIndex].stride = layout.stride; - vertexDescriptor.layouts[attributeIndex].stepRate = 1; - vertexDescriptor.layouts[attributeIndex].stepFunction = MTLVertexStepFunctionPerVertex; // MTLStepFunctionPerVertex; - } - - return vertexDescriptor; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.h b/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.h deleted file mode 100644 index 286838dda5fa..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -extern NSString *const GLTFMTLTextureLoaderOptionGenerateMipmaps; -extern NSString *const GLTFMTLTextureLoaderOptionUsageFlags; -extern NSString *const GLTFMTLTextureLoaderOptionSRGB; - -@interface GLTFMTLTextureLoader : NSObject -- (instancetype)initWithDevice:(id)device; -- (id _Nullable)newTextureWithContentsOfURL:(NSURL *)url - options:(NSDictionary *_Nullable)options - error:(NSError **)error; -- (id _Nullable)newTextureWithData:(NSData *)data - options:(NSDictionary *_Nullable)options - error:(NSError **)error; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.mm b/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.mm deleted file mode 100644 index 95c113d17c1e..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLTextureLoader.mm +++ /dev/null @@ -1,244 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFMTLTextureLoader.h" -#import -#import -#import - -NSString *const GLTFMTLTextureLoaderOptionGenerateMipmaps = @"GLTFMTLTextureLoaderOptionGenerateMipmaps"; -NSString *const GLTFMTLTextureLoaderOptionUsageFlags = @"GLTFMTLTextureLoaderOptionUsageFlags"; -NSString *const GLTFMTLTextureLoaderOptionSRGB = @"GLTFMTLTextureLoaderOptionSRGB"; - -__fp16 *GLTFMTLConvertImageToRGBA16F(CGImageRef image) -{ - size_t width = CGImageGetWidth(image); - size_t height = CGImageGetHeight(image); - - void *dstPixels = malloc(sizeof(__fp16) * 4 * width * height); - size_t dstBytesPerRow = sizeof(__fp16) * 4 * width; - vImage_Buffer dstBuffer = { - .data = dstPixels, - .height = height, - .width = width, - .rowBytes = dstBytesPerRow - }; - - vImage_CGImageFormat srcFormat = { - .bitsPerComponent = (uint32_t)CGImageGetBitsPerComponent(image), - .bitsPerPixel = (uint32_t)CGImageGetBitsPerPixel(image), - .colorSpace = CGImageGetColorSpace(image), - .bitmapInfo = CGImageGetBitmapInfo(image) - }; - - vImage_CGImageFormat dstFormat = { - .bitsPerComponent = sizeof(__fp16) * 8, - .bitsPerPixel = sizeof(__fp16) * 8 * 4, - .colorSpace = CGImageGetColorSpace(image), - .bitmapInfo = kCGBitmapByteOrder16Little | kCGBitmapFloatComponents | kCGImageAlphaLast - }; - - vImage_Error error = kvImageNoError; - CGFloat background[] = { 0, 0, 0, 1 }; - vImageConverterRef converter = vImageConverter_CreateWithCGImageFormat(&srcFormat, - &dstFormat, - background, - kvImageNoFlags, - &error); - - CGDataProviderRef dataProvider = CGImageGetDataProvider(image); - CFDataRef srcData = CGDataProviderCopyData(dataProvider); - - const void *srcPixels = CFDataGetBytePtr(srcData); - size_t srcBytesPerRow = CGImageGetBytesPerRow(image); - - vImage_Buffer srcBuffer = { - .data = (void *)srcPixels, - .height = height, - .width = width, - .rowBytes = srcBytesPerRow - }; - - error = vImageConvert_AnyToAny(converter, &srcBuffer, &dstBuffer, NULL, kvImageNoFlags); - - vImageConverter_Release(converter); - CFRelease(srcData); - - return (__fp16*)dstPixels; -} - -unsigned char *GLTFMTLConvertImageToRGBA8U(CGImageRef image) -{ - size_t width = CGImageGetWidth(image); - size_t height = CGImageGetHeight(image); - - CGColorSpaceRef srcColorSpace = CGImageGetColorSpace(image); - - vImage_CGImageFormat srcFormat = { - .bitsPerComponent = (uint32_t)CGImageGetBitsPerComponent(image), - .bitsPerPixel = (uint32_t)CGImageGetBitsPerPixel(image), - .colorSpace = srcColorSpace, - .bitmapInfo = CGImageGetBitmapInfo(image) - }; - - void *dstPixels = malloc(sizeof(unsigned char) * 4 * width * height); - vImage_Buffer dstBuffer = { - .data = dstPixels, - .height = height, - .width = width, - .rowBytes = sizeof(unsigned char) * 4 * width - }; - - CGColorSpaceRef dstColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); - - vImage_CGImageFormat dstFormat = { - .bitsPerComponent = sizeof(unsigned char) * 8, - .bitsPerPixel = sizeof(unsigned char) * 8 * 4, - .colorSpace = dstColorSpace, - .bitmapInfo = (CGBitmapInfo)kCGBitmapByteOrder32Big | (CGBitmapInfo)kCGImageAlphaLast - }; - - vImage_Error error = kvImageNoError; - CGFloat background[] = { 0, 0, 0, 1 }; - vImageConverterRef converter = vImageConverter_CreateWithCGImageFormat(&srcFormat, - &dstFormat, - background, - kvImageNoFlags, - &error); - - CGDataProviderRef dataProvider = CGImageGetDataProvider(image); - CFDataRef srcData = CGDataProviderCopyData(dataProvider); - - const void *srcPixels = CFDataGetBytePtr(srcData); - - size_t srcBytesPerPixel = CGImageGetBitsPerPixel(image) / 8; - - vImage_Buffer srcBuffer = { - .data = (void *)srcPixels, - .height = height, - .width = width, - .rowBytes = srcBytesPerPixel * width - }; - - vImageConvert_AnyToAny(converter, &srcBuffer, &dstBuffer, NULL, kvImageNoFlags); - - vImageConverter_Release(converter); - CFRelease(srcData); - - return (unsigned char*)dstPixels; -} - -@interface GLTFMTLTextureLoader () -@property (nonatomic, strong) id device; -@property (nonatomic, strong) id commandQueue; -@end - -@implementation GLTFMTLTextureLoader - -- (instancetype)initWithDevice:(id)device { - if ((self = [super init])) { - _device = device; - _commandQueue = [device newCommandQueue]; - } - return self; -} - -- (id)newTextureWithContentsOfURL:(NSURL *)url options:(NSDictionary *)options error:(NSError **)error { - if (url == nil) { - return nil; - } - - NSData *data = [NSData dataWithContentsOfURL:url]; - - return [self newTextureWithData:data options:options error:error]; -} - -- (id)newTextureWithData:(NSData *)data options:(NSDictionary *)options error:(NSError **)error { - if (data == nil) { - return nil; - } - - NSNumber *sRGBOption = options[GLTFMTLTextureLoaderOptionSRGB]; - BOOL sRGB = (sRGBOption != nil) ? sRGBOption.boolValue : NO; - - CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, nil); - CGImageRef image = CGImageSourceCreateImageAtIndex(imageSource, 0, nil); - size_t width = CGImageGetWidth(image); - size_t height = CGImageGetHeight(image); - size_t bitsPerComponent = CGImageGetBitsPerComponent(image); - - void *dstBytes = NULL; - MTLPixelFormat pixelFormat = MTLPixelFormatInvalid; - if (bitsPerComponent == 8) { - pixelFormat = sRGB ? MTLPixelFormatRGBA8Unorm_sRGB : MTLPixelFormatRGBA8Unorm; - dstBytes = GLTFMTLConvertImageToRGBA8U(image); - bitsPerComponent = 8; - } else if (bitsPerComponent == 16 || bitsPerComponent == 32) { - pixelFormat = MTLPixelFormatRGBA16Float; - dstBytes = GLTFMTLConvertImageToRGBA16F(image); - bitsPerComponent = 16; - } - - size_t bytesPerRow = (bitsPerComponent / 8) * 4 * width; - NSNumber *mipmapOption = options[GLTFMTLTextureLoaderOptionGenerateMipmaps]; - BOOL mipmapped = (mipmapOption != nil) ? mipmapOption.boolValue : NO; - - MTLTextureDescriptor *descriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pixelFormat - width:width - height:height - mipmapped:mipmapped]; - - id texture = [self newTextureWithBytes:(const unsigned char*)dstBytes - bytesPerRow:bytesPerRow - descriptor:descriptor - options:options - error:error]; - - free(dstBytes); - CGImageRelease(image); - CFRelease(imageSource); - - return texture; -} - -- (id _Nullable)newTextureWithBytes:(const unsigned char *)bytes - bytesPerRow:(size_t)bytesPerRow - descriptor:(MTLTextureDescriptor *)descriptor - options:(NSDictionary * _Nullable)options - error:(NSError **)error -{ - NSNumber *usageOption = options[GLTFMTLTextureLoaderOptionUsageFlags]; - descriptor.usage = (usageOption != nil) ? usageOption.integerValue : MTLTextureUsageShaderRead; - - id texture = [self.device newTextureWithDescriptor:descriptor]; - - [texture replaceRegion:MTLRegionMake2D(0, 0, texture.width, texture.height) - mipmapLevel:0 - withBytes:bytes - bytesPerRow:bytesPerRow]; - - if (texture != nil && (texture.mipmapLevelCount > 1)) { - id commandBuffer = [self.commandQueue commandBuffer]; - id commandEncoder = [commandBuffer blitCommandEncoder]; - [commandEncoder generateMipmapsForTexture:texture]; - [commandEncoder endEncoding]; - [commandBuffer commit]; - } - - return texture; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.h b/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.h deleted file mode 100644 index 774e113d4c51..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.h +++ /dev/null @@ -1,56 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFEnums.h" - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -#ifdef __cplusplus -extern "C" { -#endif - -extern MTLPrimitiveType GLTFMTLPrimitiveTypeForPrimitiveType(GLTFPrimitiveType gltfType); - -extern MTLBlendOperation GLTFMTLBlendOperationForBlendFunction(GLTFBlendFunction f); - -extern MTLBlendFactor GLTFBlendFactorForBlendEquation(GLTFBlendEquation e); - -extern MTLCompareFunction GLTFMTLCompareFunctionForComparisonFunc(GLTFComparisonFunc f); - -extern MTLWinding GLTFMTLWindingForWinding(GLTFWinding w); - -extern MTLCullMode GLTFMTLCullModeForCullFace(GLTFFace face); - -extern MTLSamplerMinMagFilter GLTFMTLSamplerMinMagFilterForSamplingFilter(GLTFSamplingFilter mode); - -extern MTLSamplerMipFilter GLTFMTLSamplerMipFilterForSamplingFilter(GLTFSamplingFilter mode); - -extern MTLSamplerAddressMode GLTFMTLSamplerAddressModeForSamplerAddressMode(GLTFAddressMode mode); - -extern NSString *GLTFMTLTypeNameForType(GLTFDataType baseType, GLTFDataDimension dimension, - BOOL packedIfPossible); - -extern MTLVertexFormat GLTFMTLVertexFormatForComponentTypeAndDimension(GLTFDataType baseType, - GLTFDataDimension dimension); - -#ifdef __cplusplus -} -#endif - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.mm b/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.mm deleted file mode 100644 index 1dc446902fb5..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMTLUtilities.mm +++ /dev/null @@ -1,291 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFMTLUtilities.h" - -MTLPrimitiveType GLTFMTLPrimitiveTypeForPrimitiveType(GLTFPrimitiveType gltfType) { - switch (gltfType) { - case GLTFPrimitiveTypePoints: - return MTLPrimitiveTypePoint; - case GLTFPrimitiveTypeLines: - return MTLPrimitiveTypeLine; - case GLTFPrimitiveTypeLineStrip: - return MTLPrimitiveTypeLineStrip; - case GLTFPrimitiveTypeTriangles: - return MTLPrimitiveTypeTriangle; - case GLTFPrimitiveTypeTriangleStrip: - return MTLPrimitiveTypeTriangleStrip; - - // Not supported; need to duplicate first element and restitch into tri strip, respectively - case GLTFPrimitiveTypeLineLoop: - case GLTFPrimitiveTypeTriangleFan: - default: - NSLog(@"Unsupported primitive type function %d", (int)gltfType); - return MTLPrimitiveTypePoint; - } -} - -MTLBlendOperation GLTFMTLBlendOperationForBlendFunction(GLTFBlendFunction f) { - switch (f) { - case GLTFBlendFunctionAdd: - return MTLBlendOperationAdd; - case GLTFBlendFunctionSubtract: - return MTLBlendOperationSubtract; - case GLTFBlendFunctionReverseSubtract: - return MTLBlendOperationReverseSubtract; - } -} - -MTLBlendFactor GLTFBlendFactorForBlendEquation(GLTFBlendEquation e) { - switch (e) { - case GLTFBlendEquationOne: - return MTLBlendFactorOne; - case GLTFBlendEquationZero: - return MTLBlendFactorZero; - case GLTFBlendEquationSrcAlpha: - return MTLBlendFactorSourceAlpha; - case GLTFBlendEquationSrcColor: - return MTLBlendFactorSourceColor; - case GLTFBlendEquationDestAlpha: - return MTLBlendFactorDestinationAlpha; - case GLTFBlendEquationDestColor: - return MTLBlendFactorDestinationColor; - case GLTFBlendEquationOneMinusSrcAlpha: - return MTLBlendFactorOneMinusSourceAlpha; - case GLTFBlendEquationOneMinusSrcColor: - return MTLBlendFactorOneMinusSourceColor; - case GLTFBlendEquationSrcAlphaSaturate: - return MTLBlendFactorSourceAlphaSaturated; - case GLTFBlendEquationOneMinusDestAlpha: - return MTLBlendFactorOneMinusDestinationAlpha; - case GLTFBlendEquationOneMinusDestColor: - return MTLBlendFactorOneMinusDestinationColor; - case GLTFBlendEquationOneMinusConstAlpha: - return MTLBlendFactorOneMinusDestinationColor; - default: - NSLog(@"Unsupported blend equation %d", (int)e); - return MTLBlendFactorOne; - } -} - -MTLCompareFunction GLTFMTLCompareFunctionForComparisonFunc(GLTFComparisonFunc f) { - switch (f) { - case GLTFComparisonFuncLess: - return MTLCompareFunctionLess; - case GLTFComparisonFuncEqual: - return MTLCompareFunctionEqual; - case GLTFComparisonFuncAlways: - return MTLCompareFunctionAlways; - case GLTFComparisonFuncGreater: - return MTLCompareFunctionGreater; - case GLTFComparisonFuncNotEqual: - return MTLCompareFunctionNotEqual; - case GLTFComparisonFuncLessEqual: - return MTLCompareFunctionLessEqual; - case GLTFComparisonFuncGreaterEqual: - return MTLCompareFunctionGreaterEqual; - default: - NSLog(@"Unsupported comparison function %d", (int)f); - return MTLCompareFunctionLess; - } -} - -MTLWinding GLTFMTLWindingForWinding(GLTFWinding w) { - switch (w) { - case GLTFWindingCounterclockwise: - return MTLWindingCounterClockwise; - case GLTFWindingClockwise: - default: - return MTLWindingClockwise; - } -} - -MTLCullMode GLTFMTLCullModeForCullFace(GLTFFace face) { - switch (face) { - case GLTFFaceBack: - return MTLCullModeBack; - case GLTFFaceFront: - return MTLCullModeFront; - default: - return MTLCullModeBack; - } -} - -MTLSamplerMinMagFilter GLTFMTLSamplerMinMagFilterForSamplingFilter(GLTFSamplingFilter mode) { - switch (mode) { - case GLTFSamplingFilterNearest: - return MTLSamplerMinMagFilterNearest; - default: - return MTLSamplerMinMagFilterLinear; - } -} - -MTLSamplerMipFilter GLTFMTLSamplerMipFilterForSamplingFilter(GLTFSamplingFilter mode) { - switch (mode) { - case GLTFSamplingFilterNearest: - case GLTFSamplingFilterLinear: - return MTLSamplerMipFilterNotMipmapped; - case GLTFSamplingFilterNearestMipNearest: - case GLTFSamplingFilterLinearMipNearest: - return MTLSamplerMipFilterNearest; - default: - return MTLSamplerMipFilterLinear; - } -} - -MTLSamplerAddressMode GLTFMTLSamplerAddressModeForSamplerAddressMode(GLTFAddressMode mode) { - switch (mode) { - case GLTFAddressModeClampToEdge: - return MTLSamplerAddressModeClampToEdge; - case GLTFAddressModeMirroredRepeat: - return MTLSamplerAddressModeMirrorRepeat; - default: - return MTLSamplerAddressModeRepeat; - } -} - -NSString *GLTFMTLTypeNameForType(GLTFDataType baseType, GLTFDataDimension dimension, BOOL packed) { - NSString *typeName = @"float"; - NSString *packingPrefix = @""; - NSString *dimensionSuffix = @""; - - if (packed && (dimension != GLTFDataDimensionScalar)) { - packingPrefix = @"packed_"; - } - - switch (baseType) { - case GLTFDataTypeBool: typeName = @"bool"; break; - case GLTFDataTypeChar: typeName = @"char"; break; - case GLTFDataTypeUChar: typeName = @"uchar"; break; - case GLTFDataTypeShort: typeName = @"short"; break; - case GLTFDataTypeUShort: typeName = @"ushort"; break; - case GLTFDataTypeInt: typeName = @"int"; break; - case GLTFDataTypeUInt: typeName = @"uint"; break; - case GLTFDataTypeFloat: typeName = @"float"; break; - case GLTFDataTypeSampler2D: typeName = @"texture2d"; break; - default: - return @"__UNKNOWN_TYPE__"; - } - - switch (dimension) { - case GLTFDataDimensionScalar: dimensionSuffix = @""; break; - case GLTFDataDimensionVector2: dimensionSuffix = @"2"; break; - case GLTFDataDimensionVector3: dimensionSuffix = @"3"; break; - case GLTFDataDimensionVector4: dimensionSuffix = @"4"; break; - case GLTFDataDimensionMatrix2x2: dimensionSuffix = @"float2x2"; break; - case GLTFDataDimensionMatrix3x3: dimensionSuffix = @"float3x3"; break; - case GLTFDataDimensionMatrix4x4: dimensionSuffix = @"float4x4"; break; - default: - return @"__UNKNOWN_TYPE__"; - } - - return [NSString stringWithFormat:@"%@%@%@", packingPrefix, typeName, dimensionSuffix]; -} - -MTLVertexFormat GLTFMTLVertexFormatForComponentTypeAndDimension(GLTFDataType baseType, GLTFDataDimension dimension) -{ - switch (baseType) { - case GLTFDataTypeChar: - switch (dimension) { - case GLTFDataDimensionVector2: - return MTLVertexFormatChar2; - case GLTFDataDimensionVector3: - return MTLVertexFormatChar3; - case GLTFDataDimensionVector4: - return MTLVertexFormatChar4; - default: - break; - } - case GLTFDataTypeUChar: - switch (dimension) { - case GLTFDataDimensionVector2: - return MTLVertexFormatUChar2; - case GLTFDataDimensionVector3: - return MTLVertexFormatUChar3; - case GLTFDataDimensionVector4: - return MTLVertexFormatUChar4; - default: - break; - } - case GLTFDataTypeShort: - switch (dimension) { - case GLTFDataDimensionVector2: - return MTLVertexFormatShort2; - case GLTFDataDimensionVector3: - return MTLVertexFormatShort3; - case GLTFDataDimensionVector4: - return MTLVertexFormatShort4; - default: - break; - } - case GLTFDataTypeUShort: - switch (dimension) { - case GLTFDataDimensionVector2: - return MTLVertexFormatUShort2; - case GLTFDataDimensionVector3: - return MTLVertexFormatUShort3; - case GLTFDataDimensionVector4: - return MTLVertexFormatUShort4; - default: - break; - } - case GLTFDataTypeInt: - switch (dimension) { - case GLTFDataDimensionScalar: - return MTLVertexFormatInt; - case GLTFDataDimensionVector2: - return MTLVertexFormatInt2; - case GLTFDataDimensionVector3: - return MTLVertexFormatInt3; - case GLTFDataDimensionVector4: - return MTLVertexFormatInt4; - default: - break; - } - case GLTFDataTypeUInt: - switch (dimension) { - case GLTFDataDimensionScalar: - return MTLVertexFormatUInt; - case GLTFDataDimensionVector2: - return MTLVertexFormatUInt2; - case GLTFDataDimensionVector3: - return MTLVertexFormatUInt3; - case GLTFDataDimensionVector4: - return MTLVertexFormatUInt4; - default: - break; - } - case GLTFDataTypeFloat: - switch (dimension) { - case GLTFDataDimensionScalar: - return MTLVertexFormatFloat; - case GLTFDataDimensionVector2: - return MTLVertexFormatFloat2; - case GLTFDataDimensionVector3: - return MTLVertexFormatFloat3; - case GLTFDataDimensionVector4: - return MTLVertexFormatFloat4; - default: - break; - } - default: - break; - } - - return MTLVertexFormatInvalid; -} - - diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMaterial.h b/platform/darwin/src/gltf/gltfkit/GLTFMaterial.h deleted file mode 100644 index cc8a889ab828..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMaterial.h +++ /dev/null @@ -1,65 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFObject.h" -#import "GLTFTexture.h" - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFParameter; - -typedef NS_ENUM(NSInteger, GLTFAlphaMode) { - GLTFAlphaModeOpaque, - GLTFAlphaModeMask, - GLTFAlphaModeBlend, -}; - -@interface GLTFMaterial : GLTFObject - -@property (nonatomic, assign) simd_float4 baseColorFactor; -@property (nonatomic, assign) float metalnessFactor; -@property (nonatomic, assign) float roughnessFactor; -@property (nonatomic, assign) float normalTextureScale; -@property (nonatomic, assign) float occlusionStrength; -@property (nonatomic, assign) simd_float3 emissiveFactor; - -@property (nonatomic, assign) - float glossinessFactor; // Only used by KHR_materials_pbrSpecularGlossiness extension -@property (nonatomic, assign) - simd_float3 specularFactor; // Only used by KHR_materials_pbrSpecularGlossiness extension - -@property (nonatomic, strong) GLTFTextureInfo* _Nullable baseColorTexture; -@property (nonatomic, strong) GLTFTextureInfo* _Nullable metallicRoughnessTexture; -@property (nonatomic, strong) GLTFTextureInfo* _Nullable normalTexture; -@property (nonatomic, strong) GLTFTextureInfo* _Nullable emissiveTexture; -@property (nonatomic, strong) GLTFTextureInfo* _Nullable occlusionTexture; - -@property (nonatomic, assign) - BOOL hasTextureTransforms; // Only used when KHR_texture_transform extension is present - -@property (nonatomic, assign, getter=isDoubleSided) BOOL doubleSided; - -@property (nonatomic, assign) GLTFAlphaMode alphaMode; -@property (nonatomic, assign) float alphaCutoff; // Only used when `alphaMode` == GLTFAlphaModeMask - -@property (nonatomic, assign, getter=isUnlit) - BOOL unlit; // Only used when KHR_materials_unlit extension is present - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMaterial.mm b/platform/darwin/src/gltf/gltfkit/GLTFMaterial.mm deleted file mode 100644 index e8f78a4700ed..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMaterial.mm +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFMaterial.h" - -@implementation GLTFMaterial - -- (instancetype)init { - if ((self = [super init])) { - _baseColorFactor = (simd_float4){ 1, 1, 1, 1 }; - _metalnessFactor = 1.0; - _roughnessFactor = 1.0; - _occlusionStrength = 1.0; - _emissiveFactor = (simd_float3) { 0.0, 0.0, 0.0 }; - _normalTextureScale = 1.0; - _alphaMode = GLTFAlphaModeOpaque; - _alphaCutoff = 0.5; - } - return self; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMesh.h b/platform/darwin/src/gltf/gltfkit/GLTFMesh.h deleted file mode 100644 index 19d4ea6f9ee7..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMesh.h +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFEnums.h" -#import "GLTFObject.h" - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFAccessor, GLTFVertexDescriptor, GLTFSubmesh, GLTFMaterial; - -@interface GLTFMesh : GLTFObject -@property (nonatomic, copy) NSArray *submeshes; -@property (nonatomic, copy) NSArray *defaultMorphTargetWeights; -@end - -@interface GLTFMorphTarget : GLTFObject -@property (nonatomic, copy) NSDictionary *accessorsForAttributes; -@end - -@interface GLTFSubmesh : GLTFObject -@property (nonatomic, copy) NSDictionary *accessorsForAttributes; -@property (nonatomic, weak) GLTFAccessor *indexAccessor; -@property (nonatomic, weak) GLTFMaterial *material; -@property (nonatomic, assign) GLTFPrimitiveType primitiveType; -@property (nonatomic, copy) NSArray *morphTargets; - -@property (nonatomic, readonly) GLTFVertexDescriptor *vertexDescriptor; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFMesh.mm b/platform/darwin/src/gltf/gltfkit/GLTFMesh.mm deleted file mode 100644 index bc6ae3a88407..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFMesh.mm +++ /dev/null @@ -1,69 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFMesh.h" -#import "GLTFVertexDescriptor.h" -#import "GLTFAccessor.h" -#import "GLTFBufferView.h" -#import "GLTFUtilities.h" - -@implementation GLTFMesh -@end - -@implementation GLTFMorphTarget -@end - -@interface GLTFSubmesh () -@property (nonatomic, strong) GLTFVertexDescriptor *cachedVertexDescriptor; -@end - -@implementation GLTFSubmesh - -- (instancetype)init { - if ((self = [super init])) { - _primitiveType = GLTFPrimitiveTypeTriangles; - } - return self; -} - -- (void)setAccessorsForAttributes:(NSDictionary *)accessorsForAttributes { - _accessorsForAttributes = accessorsForAttributes; - _cachedVertexDescriptor = nil; -} - -- (GLTFVertexDescriptor *)vertexDescriptor { - if (self.cachedVertexDescriptor == nil) { - GLTFVertexDescriptor *descriptor = [GLTFVertexDescriptor new]; - __block NSUInteger index = 0; - [self.accessorsForAttributes enumerateKeysAndObjectsUsingBlock:^(NSString *name, GLTFAccessor *accessor, BOOL *stop) { - descriptor.attributes[index].componentType = accessor.componentType; - descriptor.attributes[index].dimension = accessor.dimension; - descriptor.attributes[index].offset = accessor.offset; - descriptor.attributes[index].semantic = name; - if (accessor.bufferView.stride > 0) { - descriptor.bufferLayouts[index].stride = accessor.bufferView.stride; - } else { - descriptor.bufferLayouts[index].stride = GLTFSizeOfComponentTypeWithDimension(accessor.componentType, accessor.dimension); - } - ++index; - }]; - self.cachedVertexDescriptor = descriptor; - } - - return self.cachedVertexDescriptor; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFNode.h b/platform/darwin/src/gltf/gltfkit/GLTFNode.h deleted file mode 100644 index f370d0299095..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFNode.h +++ /dev/null @@ -1,49 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import -#import "GLTFNodeVisitor.h" -#import "GLTFObject.h" -#import "GLTFUtilities.h" - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFCamera, GLTFSkin, GLTFMesh; -@class GLTFKHRLight; - -@interface GLTFNode : GLTFObject -@property (nonatomic, weak) GLTFCamera *_Nullable camera; -@property (nonatomic, weak) GLTFKHRLight *_Nullable light; -@property (nonatomic, weak) GLTFNode *_Nullable parent; -@property (nonatomic, copy) NSArray *children; -@property (nonatomic, weak) GLTFSkin *_Nullable skin; -@property (nonatomic, copy) NSString *_Nullable jointName; -@property (nonatomic, weak) GLTFMesh *_Nullable mesh; -@property (nonatomic, copy) NSArray *morphTargetWeights; -@property (nonatomic, assign) GLTFQuaternion rotationQuaternion; -@property (nonatomic, assign) simd_float3 scale; -@property (nonatomic, assign) simd_float3 translation; -@property (nonatomic, assign) simd_float4x4 localTransform; -@property (nonatomic, readonly, assign) simd_float4x4 globalTransform; -@property (nonatomic, readonly, assign) - GLTFBoundingBox approximateBounds; // axis-aligned; in local coordinates - -- (void)addChildNode:(GLTFNode *)node; -- (void)removeFromParent; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFNode.mm b/platform/darwin/src/gltf/gltfkit/GLTFNode.mm deleted file mode 100644 index 2630d49960c5..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFNode.mm +++ /dev/null @@ -1,171 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFNode.h" -#import "GLTFAccessor.h" -#import "GLTFMesh.h" -#import "GLTFVertexDescriptor.h" - -@interface GLTFNode () -@property (nonatomic, assign, getter=localTransformIsDirty) BOOL localTransformDirty; -@property (nonatomic, strong) NSMutableArray *mutableChildren; -@end - -@implementation GLTFNode - -@synthesize localTransform=_localTransform; - -- (instancetype)init { - if ((self = [super init])) { - _localTransform = matrix_identity_float4x4; - _rotationQuaternion = simd_quaternion(0.f, 0.f, 0.f, 1.f); - _scale = vector3(1.0f, 1.0f, 1.0f); - _translation = vector3(0.0f, 0.0f, 0.0f); - _morphTargetWeights = @[]; - } - return self; -} - -- (void)setChildren:(NSArray *)children { - _mutableChildren = [children mutableCopy]; -} - -- (NSArray *)children { - return [_mutableChildren copy]; -} - -- (void)addChildNode:(GLTFNode *)node { - if (node.parent) { - [node removeFromParent]; - } - node.parent = self; - [self.mutableChildren addObject:node]; -} - -- (void)removeFromParent { - [self.parent _removeChildNode:self]; -} - -- (void)_removeChildNode:(GLTFNode *)child { - [self.mutableChildren removeObject:child]; - child.parent = nil; -} - -- (void)setScale:(simd_float3)scale { - _scale = scale; - _localTransformDirty = YES; -} - -- (void)setRotationQuaternion:(GLTFQuaternion)rotationQuaternion { - _rotationQuaternion = rotationQuaternion; - _localTransformDirty = YES; -} - -- (void)setTranslation:(simd_float3)translation { - _translation = translation; - _localTransformDirty = YES; -} - -- (simd_float4x4)globalTransform { - simd_float4x4 localTransform = self.localTransform; - simd_float4x4 ancestorTransform = self.parent ? self.parent.globalTransform : matrix_identity_float4x4; - return matrix_multiply(ancestorTransform, localTransform); -} - -- (void)setLocalTransform:(simd_float4x4)localTransform { - _localTransform = localTransform; -} - -- (simd_float4x4)localTransform { - if (self.localTransformIsDirty) { - [self computeLocalTransform]; - } - - return _localTransform; -} - -- (void)computeLocalTransform { - simd_float4x4 translationMatrix = matrix_identity_float4x4; - translationMatrix.columns[3][0] = _translation[0]; - translationMatrix.columns[3][1] = _translation[1]; - translationMatrix.columns[3][2] = _translation[2]; - - simd_float4x4 rotationMatrix = simd_matrix4x4(_rotationQuaternion); - - simd_float4x4 scaleMatrix = matrix_identity_float4x4; - scaleMatrix.columns[0][0] = _scale[0]; - scaleMatrix.columns[1][1] = _scale[1]; - scaleMatrix.columns[2][2] = _scale[2]; - - _localTransform = matrix_multiply(matrix_multiply(translationMatrix, rotationMatrix), scaleMatrix); - _localTransformDirty = NO; -} - -- (GLTFBoundingBox)approximateBounds { - return [self _approximateBoundsRecursive:matrix_identity_float4x4]; -} - -- (GLTFBoundingBox)_approximateBoundsRecursive:(simd_float4x4)transform { - GLTFBoundingBox bounds = { 0, 0 }; - - if (self.mesh != nil) { - for (GLTFSubmesh *submesh in self.mesh.submeshes) { - GLTFBoundingBox submeshBounds = { 0, 0 }; - GLTFAccessor *positionAccessor = submesh.accessorsForAttributes[GLTFAttributeSemanticPosition]; - GLTFValueRange positionRange = positionAccessor.valueRange; - submeshBounds.minPoint.x = positionRange.minValue[0]; - submeshBounds.minPoint.y = positionRange.minValue[1]; - submeshBounds.minPoint.z = positionRange.minValue[2]; - submeshBounds.maxPoint.x = positionRange.maxValue[0]; - submeshBounds.maxPoint.y = positionRange.maxValue[1]; - submeshBounds.maxPoint.z = positionRange.maxValue[2]; - GLTFBoundingBoxUnion(&bounds, submeshBounds); - } - } - - simd_float4x4 globalTransform = matrix_multiply(transform, self.localTransform); - - GLTFBoundingBoxTransform(&bounds, globalTransform); - - for (GLTFNode *child in self.children) { - GLTFBoundingBox childBounds = [child _approximateBoundsRecursive:globalTransform]; - GLTFBoundingBoxUnion(&bounds, childBounds); - } - - return bounds; -} - -- (void)acceptVisitor:(GLTFNodeVisitor)visitor strategy:(GLTFVisitationStrategy)strategy { - [self _acceptVisitor:visitor depth:0 strategy:strategy]; -} - -- (void)_acceptVisitor:(GLTFNodeVisitor)visitor depth:(int)depth strategy:(GLTFVisitationStrategy)strategy { - switch (strategy) { - case GLTFVisitationStrategyDepthFirst: - default: - { - BOOL recurse = YES; - visitor(self, depth, &recurse); - if (recurse) { - for (GLTFNode *child in self.children) { - [child _acceptVisitor:visitor depth:(depth + 1) strategy:strategy]; - } - } - } - } -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFNodeVisitor.h b/platform/darwin/src/gltf/gltfkit/GLTFNodeVisitor.h deleted file mode 100644 index ee3ce2b5de46..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFNodeVisitor.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFNode; - -typedef NS_ENUM(NSInteger, GLTFVisitationStrategy) { GLTFVisitationStrategyDepthFirst }; - -typedef void (^GLTFNodeVisitor)(GLTFNode *node, int depth, BOOL *stop); - -@protocol GLTFNodeVisitable -- (void)acceptVisitor:(GLTFNodeVisitor)visitor strategy:(GLTFVisitationStrategy)strategy; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFObject.h b/platform/darwin/src/gltf/gltfkit/GLTFObject.h deleted file mode 100644 index 146d6c82a300..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFObject.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@protocol GLTFObject - -/// The user-defined name of this object. Need not be unique. -@property (nonatomic, copy) NSString *_Nullable name; -/// Data specific to any extensions used in this document -@property (nonatomic, copy) NSDictionary *extensions; -/// Contains application-specific information that is passed through but not parsed -@property (nonatomic, copy) NSDictionary *extras; - -@end - -@interface GLTFObject : NSObject - -/// A unique identifier for this object -@property (nonatomic, readonly) NSUUID *identifier; -/// The user-defined name of this object. Need not be unique. -@property (nonatomic, copy) NSString *_Nullable name; -/// Data specific to any extensions used in this document -@property (nonatomic, copy) NSDictionary *extensions; -/// Contains application-specific information that is passed through but not parsed -@property (nonatomic, copy) NSDictionary *extras; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFObject.mm b/platform/darwin/src/gltf/gltfkit/GLTFObject.mm deleted file mode 100644 index 42e9e79127aa..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFObject.mm +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFObject.h" - -@implementation GLTFObject - -- (instancetype)init { - if ((self = [super init])) { - _identifier = [NSUUID new]; - } - return self; -} - -- (NSString *)description { - return [NSString stringWithFormat:@"%@; name = %@", super.description, self.name]; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFScene.h b/platform/darwin/src/gltf/gltfkit/GLTFScene.h deleted file mode 100644 index 6abf39c6c92f..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFScene.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFNodeVisitor.h" -#import "GLTFObject.h" -#import "GLTFUtilities.h" - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFNode; -@class GLTFKHRLight; - -@interface GLTFScene : GLTFObject -@property (nonatomic, copy) NSArray *nodes; -@property (nonatomic, weak) GLTFKHRLight *_Nullable ambientLight; -@property (nonatomic, readonly, assign) GLTFBoundingBox approximateBounds; - -- (void)addNode:(GLTFNode *)node; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFScene.mm b/platform/darwin/src/gltf/gltfkit/GLTFScene.mm deleted file mode 100644 index b3f0a6901277..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFScene.mm +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFScene.h" -#import "GLTFNode.h" - -@interface GLTFScene () -@property (nonatomic, strong) NSMutableArray *mutableNodes; -@end - -@implementation GLTFScene - -- (void)setNodes:(NSArray *)nodes { - _mutableNodes = [nodes mutableCopy]; -} - -- (NSArray *)nodes { - return [_mutableNodes copy]; -} - -- (void)addNode:(GLTFNode *)node { - if (node.parent) { - [node removeFromParent]; - } - - [_mutableNodes addObject:node]; -} - -- (GLTFBoundingBox)approximateBounds { - GLTFBoundingBox sceneBounds = { 0, 0 }; - for (GLTFNode *node in self.nodes) { - GLTFBoundingBox nodeBounds = node.approximateBounds; - GLTFBoundingBoxUnion(&sceneBounds, nodeBounds); - } - return sceneBounds; -} - -- (void)acceptVisitor:(GLTFNodeVisitor)visitor strategy:(GLTFVisitationStrategy)strategy { - for (GLTFNode *node in self.nodes) { - [node acceptVisitor:visitor strategy:strategy]; - } -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFSkin.h b/platform/darwin/src/gltf/gltfkit/GLTFSkin.h deleted file mode 100644 index fa5a8aee553e..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFSkin.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import -#import "GLTFObject.h" - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFAccessor, GLTFNode; - -@interface GLTFSkin : GLTFObject -@property (nonatomic, strong) GLTFAccessor *inverseBindMatricesAccessor; -@property (nonatomic, copy) NSArray *jointNodes; -@property (nonatomic, assign) GLTFNode *skeletonRootNode; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFSkin.mm b/platform/darwin/src/gltf/gltfkit/GLTFSkin.mm deleted file mode 100644 index c6c5dfbfbdc2..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFSkin.mm +++ /dev/null @@ -1,20 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFSkin.h" - -@implementation GLTFSkin -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFTexture.h b/platform/darwin/src/gltf/gltfkit/GLTFTexture.h deleted file mode 100644 index 7b7a9f97bb0d..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFTexture.h +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import -#import "../GLTFMath.hpp" -#import "GLTFEnums.h" -#import "GLTFObject.h" - -NS_ASSUME_NONNULL_BEGIN - -@class GLTFTextureSampler, GLTFImage; - -@interface GLTFTexture : GLTFObject - -@property (nonatomic, weak) GLTFTextureSampler *sampler; - -@property (nonatomic, weak) GLTFImage *image; - -// GLTFTextureFormatRGBA -@property (nonatomic, assign) GLTFTextureFormat format; - -// GLTFTextureFormatRGBA -@property (nonatomic, assign) GLTFTextureFormat internalFormat; - -// GLTFTextureTypeUChar -@property (nonatomic, assign) GLTFTextureType type; - -// GLTFTextureTargetTexture2D -@property (nonatomic, assign) GLTFTextureTarget target; - -@end - -@interface GLTFTextureInfo : NSObject - -@property (nonatomic, strong) GLTFTexture *texture; - -@property (nonatomic, assign) NSInteger texCoord; - -// The transform to apply to texture coordinates before sampling from this texture. -// Defaults to the identity transform. Only populated if KHR_texture_transform is included -// as an optional or required extension for the containing asset. -@property (nonatomic, assign) GLTFTextureTransform transform; - -@property (nonatomic, strong) NSDictionary *_Nullable extensions; - -@property (nonatomic, strong) NSDictionary *_Nullable extras; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFTexture.mm b/platform/darwin/src/gltf/gltfkit/GLTFTexture.mm deleted file mode 100644 index 0f5d77fdeb82..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFTexture.mm +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFTexture.h" -#import "GLTFUtilities.h" - - -@implementation GLTFTexture - -- (instancetype)init { - if ((self = [super init])) { - _format = GLTFTextureFormatRGBA; - _internalFormat = GLTFTextureFormatRGBA; - _type = GLTFTextureTypeUChar; - _target = GLTFTextureTargetTexture2D; - } - return self; -} - -@end - -@implementation GLTFTextureInfo - -- (instancetype)init { - if ((self = [super init])) { - _transform = GLTFTextureTransformMakeIdentity(); - } - return self; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.h b/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.h deleted file mode 100644 index fbe3b026f529..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFEnums.h" -#import "GLTFObject.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface GLTFTextureSampler : GLTFObject - -// GLTFSamplingFilterLinear -@property (nonatomic, assign) GLTFSamplingFilter magFilter; -// GLTFSamplingFilterNearestMipLinear -@property (nonatomic, assign) GLTFSamplingFilter minFilter; -// GLTFAddressModeRepeat -@property (nonatomic, assign) GLTFAddressMode sAddressMode; -// GLTFAddressModeRepeat -@property (nonatomic, assign) GLTFAddressMode tAddressMode; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.mm b/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.mm deleted file mode 100644 index 2078acb52ea4..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFTextureSampler.mm +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFTextureSampler.h" - -@implementation GLTFTextureSampler - -- (instancetype)init { - if ((self = [super init])) { - _magFilter = GLTFSamplingFilterLinear; - _minFilter = GLTFSamplingFilterNearestMipLinear; - _sAddressMode = GLTFAddressModeRepeat; - _tAddressMode = GLTFAddressModeRepeat; - } - return self; -} - -- (BOOL)isEqual:(id)other { - if (![other isKindOfClass:[GLTFTextureSampler class]]) { - return NO; - } - - GLTFTextureSampler *otherSampler = (GLTFTextureSampler *)other; - BOOL areEqual = - (otherSampler.magFilter == self.magFilter) && - (otherSampler.minFilter == self.minFilter) && - (otherSampler.sAddressMode == self.sAddressMode) && - (otherSampler.tAddressMode == self.tAddressMode); - return areEqual; -} - -- (NSUInteger)hash { - NSUInteger hashValue = ((_sAddressMode << 16) | _tAddressMode) + ((_magFilter << 16) | _minFilter); - return hashValue; -} - -- (id)copyWithZone:(NSZone *)zone { - GLTFTextureSampler *copy = [[GLTFTextureSampler allocWithZone:zone] init]; - copy.magFilter = self.magFilter; - copy.minFilter = self.minFilter; - copy.sAddressMode = self.sAddressMode; - copy.tAddressMode = self.tAddressMode; - return copy; -} - -@end - diff --git a/platform/darwin/src/gltf/gltfkit/GLTFUtilities.h b/platform/darwin/src/gltf/gltfkit/GLTFUtilities.h deleted file mode 100644 index db7a39064ce5..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFUtilities.h +++ /dev/null @@ -1,72 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFEnums.h" - -#import -#import -#import "../GLTFMath.hpp" - -NS_ASSUME_NONNULL_BEGIN - -typedef struct __attribute__((packed)) { - float x, y, z; -} GLTFVector3; - -typedef struct __attribute__((packed)) { - float x, y, z, w; -} GLTFVector4; - -typedef struct __attribute__((packed)) { - GLTFVector4 columns[4]; -} GLTFMatrix4; - -typedef simd_quatf GLTFQuaternion; - -extern bool GLTFBoundingBoxIsEmpty(GLTFBoundingBox b); - -extern GLTFBoundingBox *GLTFBoundingBoxUnion(GLTFBoundingBox *a, GLTFBoundingBox b); - -extern void GLTFBoundingBoxTransform(GLTFBoundingBox *b, simd_float4x4 transform); - -extern GLTFQuaternion GLTFQuaternionFromEulerAngles(float pitch, float yaw, float roll); - -extern simd_float3x3 GLTFMatrixUpperLeft3x3(simd_float4x4); - -extern simd_float4x4 GLTFNormalMatrixFromModelMatrix(simd_float4x4); - -extern GLTFDataDimension GLTFDataDimensionForName(NSString *name); - -extern size_t GLTFSizeOfDataType(GLTFDataType type); - -extern size_t GLTFSizeOfComponentTypeWithDimension(GLTFDataType baseType, - GLTFDataDimension dimension); - -extern NSInteger GLTFComponentCountForDimension(GLTFDataDimension dimension); - -extern BOOL GLTFDataTypeComponentsAreFloats(GLTFDataType type); - -extern simd_float2 GLTFVectorFloat2FromArray(NSArray *array); - -extern simd_float3 GLTFVectorFloat3FromArray(NSArray *array); - -extern simd_float4 GLTFVectorFloat4FromArray(NSArray *array); - -extern GLTFQuaternion GLTFQuaternionFromArray(NSArray *array); - -extern simd_float4x4 GLTFMatrixFloat4x4FromArray(NSArray *array); - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFUtilities.mm b/platform/darwin/src/gltf/gltfkit/GLTFUtilities.mm deleted file mode 100644 index ecce6e6fc0bc..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFUtilities.mm +++ /dev/null @@ -1,262 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFUtilities.h" -#include "GLTFEnums.h" - -bool GLTFBoundingBoxIsEmpty(GLTFBoundingBox b) { - return (b.minPoint.x == b.maxPoint.x) && (b.minPoint.y == b.maxPoint.y) && (b.minPoint.z == b.maxPoint.z); -} - -GLTFBoundingBox *GLTFBoundingBoxUnion(GLTFBoundingBox *a, GLTFBoundingBox b) { - bool leftEmpty = GLTFBoundingBoxIsEmpty(*a); - bool rightEmpty = GLTFBoundingBoxIsEmpty(b); - - if (leftEmpty) { - if (!rightEmpty) { - *a = b; - } - } else if (!rightEmpty) { - if (b.minPoint.x < a->minPoint.x) { a->minPoint.x = b.minPoint.x; } - if (b.minPoint.y < a->minPoint.y) { a->minPoint.y = b.minPoint.y; } - if (b.minPoint.z < a->minPoint.z) { a->minPoint.z = b.minPoint.z; } - if (b.maxPoint.x > a->maxPoint.x) { a->maxPoint.x = b.maxPoint.x; } - if (b.maxPoint.y > a->maxPoint.y) { a->maxPoint.y = b.maxPoint.y; } - if (b.maxPoint.z > a->maxPoint.z) { a->maxPoint.z = b.maxPoint.z; } - } - - return a; -} - -void GLTFBoundingBoxTransform(GLTFBoundingBox *b, simd_float4x4 transform) { - simd_float4 ltf = (simd_float4) { b->minPoint.x, b->maxPoint.y, b->maxPoint.z, 1 }; - simd_float4 rtf = (simd_float4) { b->maxPoint.x, b->maxPoint.y, b->maxPoint.z, 1 }; - simd_float4 lbf = (simd_float4) { b->minPoint.x, b->minPoint.y, b->maxPoint.z, 1 }; - simd_float4 rbf = (simd_float4) { b->maxPoint.x, b->minPoint.y, b->maxPoint.z, 1 }; - simd_float4 ltb = (simd_float4) { b->minPoint.x, b->maxPoint.y, b->minPoint.z, 1 }; - simd_float4 rtb = (simd_float4) { b->maxPoint.x, b->maxPoint.y, b->minPoint.z, 1 }; - simd_float4 lbb = (simd_float4) { b->minPoint.x, b->minPoint.y, b->minPoint.z, 1 }; - simd_float4 rbb = (simd_float4) { b->maxPoint.x, b->minPoint.y, b->minPoint.z, 1 }; - - ltf = matrix_multiply(transform, ltf); - rtf = matrix_multiply(transform, rtf); - lbf = matrix_multiply(transform, lbf); - rbf = matrix_multiply(transform, rbf); - ltb = matrix_multiply(transform, ltb); - rtb = matrix_multiply(transform, rtb); - lbb = matrix_multiply(transform, lbb); - rbb = matrix_multiply(transform, rbb); - - b->minPoint.x = fmin(fmin(fmin(fmin(fmin(fmin(fmin(ltf.x, rtf.x), lbf.x), rbf.x), ltb.x), rtb.x), lbb.x), rbb.x); - b->minPoint.y = fmin(fmin(fmin(fmin(fmin(fmin(fmin(ltf.y, rtf.y), lbf.y), rbf.y), ltb.y), rtb.y), lbb.y), rbb.y); - b->minPoint.z = fmin(fmin(fmin(fmin(fmin(fmin(fmin(ltf.z, rtf.z), lbf.z), rbf.z), ltb.z), rtb.z), lbb.z), rbb.z); - b->maxPoint.x = fmax(fmax(fmax(fmax(fmax(fmax(fmax(ltf.x, rtf.x), lbf.x), rbf.x), ltb.x), rtb.x), lbb.x), rbb.x); - b->maxPoint.y = fmax(fmax(fmax(fmax(fmax(fmax(fmax(ltf.y, rtf.y), lbf.y), rbf.y), ltb.y), rtb.y), lbb.y), rbb.y); - b->maxPoint.z = fmax(fmax(fmax(fmax(fmax(fmax(fmax(ltf.z, rtf.z), lbf.z), rbf.z), ltb.z), rtb.z), lbb.z), rbb.z); -} - - - -GLTFQuaternion GLTFQuaternionFromEulerAngles(float pitch, float yaw, float roll) { - float cx = cos(pitch / 2); - float sx = sin(pitch / 2); - float cy = cos(yaw / 2); - float sy = sin(yaw / 2); - float cz = cos(roll / 2); - float sz = sin(roll / 2); - - GLTFQuaternion q = simd_quaternion( - sx*cy*cz + cx*sy*sz, - cx*sy*cz + sx*cy*sz, - cx*cy*sz - sx*sy*cz, - cx*cy*cz - sx*sy*sz - ); - return q; -} - - - - - - - - - - - -GLTFDataDimension GLTFDataDimensionForName(NSString *name) { - if ([name isEqualToString:@"SCALAR"]) { - return GLTFDataDimensionScalar; - } else if ([name isEqualToString:@"VEC2"]) { - return GLTFDataDimensionVector2; - } else if ([name isEqualToString:@"VEC2"]) { - return GLTFDataDimensionVector2; - } else if ([name isEqualToString:@"VEC3"]) { - return GLTFDataDimensionVector3; - } else if ([name isEqualToString:@"VEC4"]) { - return GLTFDataDimensionVector4; - } else if ([name isEqualToString:@"MAT2"]) { - return GLTFDataDimensionMatrix2x2; - } else if ([name isEqualToString:@"MAT3"]) { - return GLTFDataDimensionMatrix3x3; - } else if ([name isEqualToString:@"MAT4"]) { - return GLTFDataDimensionMatrix4x4; - } - - return GLTFDataDimensionUnknown; -} - -size_t GLTFSizeOfDataType(GLTFDataType type) { - - switch (type) { - case GLTFDataTypeChar: return sizeof(char); - case GLTFDataTypeUChar: return sizeof(unsigned char); - case GLTFDataTypeShort: return sizeof(short); - case GLTFDataTypeUShort: return sizeof(unsigned short); - case GLTFDataTypeInt: return sizeof(int); - case GLTFDataTypeUInt: return sizeof(unsigned int); - case GLTFDataTypeFloat: return sizeof(float); - case GLTFDataTypeFloat2: return sizeof(float) * 2; - case GLTFDataTypeFloat3: return sizeof(float) * 3; - case GLTFDataTypeFloat4: return sizeof(float) * 4; - case GLTFDataTypeInt2: return sizeof(int) * 2; - case GLTFDataTypeInt3: return sizeof(int) * 3; - case GLTFDataTypeInt4: return sizeof(int) * 4; - case GLTFDataTypeBool: return sizeof(bool); - case GLTFDataTypeBool2: return sizeof(bool) * 2; - case GLTFDataTypeBool3: return sizeof(bool) * 3; - case GLTFDataTypeBool4: return sizeof(bool) * 4; - case GLTFDataTypeFloat2x2: return sizeof(float) * 4; - case GLTFDataTypeFloat3x3: return sizeof(float) * 9; - case GLTFDataTypeFloat4x4: return sizeof(float) * 16; - case GLTFDataTypeSampler2D: return sizeof(size_t); - default: return 0; - } -} - -size_t GLTFSizeOfComponentTypeWithDimension(GLTFDataType baseType, GLTFDataDimension dimension) -{ - switch (baseType) { - case GLTFDataTypeChar: - case GLTFDataTypeUChar: - switch (dimension) { - case GLTFDataDimensionVector2: - return 2; - case GLTFDataDimensionVector3: - return 3; - case GLTFDataDimensionVector4: - return 4; - default: - break; - } - case GLTFDataTypeShort: - case GLTFDataTypeUShort: - switch (dimension) { - case GLTFDataDimensionVector2: - return 4; - case GLTFDataDimensionVector3: - return 6; - case GLTFDataDimensionVector4: - return 8; - default: - break; - } - case GLTFDataTypeInt: - case GLTFDataTypeUInt: - case GLTFDataTypeFloat: - switch (dimension) { - case GLTFDataDimensionScalar: - return 4; - case GLTFDataDimensionVector2: - return 8; - case GLTFDataDimensionVector3: - return 12; - case GLTFDataDimensionVector4: - case GLTFDataDimensionMatrix2x2: - return 16; - case GLTFDataDimensionMatrix3x3: - return 36; - case GLTFDataDimensionMatrix4x4: - return 64; - default: - break; - } - default: - break; - } - return 0; -} - -NSInteger GLTFComponentCountForDimension(GLTFDataDimension dimension) { - switch (dimension) { - case GLTFDataDimensionScalar: - return 1; - case GLTFDataDimensionVector2: - return 2; - case GLTFDataDimensionVector3: - return 3; - case GLTFDataDimensionVector4: - return 4; - case GLTFDataDimensionMatrix2x2: - return 4; - case GLTFDataDimensionMatrix3x3: - return 9; - case GLTFDataDimensionMatrix4x4: - return 16; - default: - return 0; - } -} - -BOOL GLTFDataTypeComponentsAreFloats(GLTFDataType type) { - switch (type) { - case GLTFDataTypeFloat: - case GLTFDataTypeFloat2: - case GLTFDataTypeFloat3: - case GLTFDataTypeFloat4: - case GLTFDataTypeFloat2x2: - case GLTFDataTypeFloat3x3: - case GLTFDataTypeFloat4x4: - return YES; - default: - return NO; - } -} - -simd_float2 GLTFVectorFloat2FromArray(NSArray *array) { - return (simd_float2){ [array[0] floatValue], [array[1] floatValue] }; -} - -simd_float3 GLTFVectorFloat3FromArray(NSArray *array) { - return (simd_float3){ [array[0] floatValue], [array[1] floatValue], [array[2] floatValue] }; -} - -simd_float4 GLTFVectorFloat4FromArray(NSArray *array) { - return (simd_float4){ [array[0] floatValue], [array[1] floatValue], [array[2] floatValue], [array[3] floatValue] }; -} - -GLTFQuaternion GLTFQuaternionFromArray(NSArray *array) { - return simd_quaternion([array[0] floatValue], [array[1] floatValue], [array[2] floatValue], [array[3] floatValue]); -} - -simd_float4x4 GLTFMatrixFloat4x4FromArray(NSArray *array) { - return (simd_float4x4){ { - { [array[0] floatValue], [array[1] floatValue], [array[2] floatValue], [array[3] floatValue] }, - { [array[4] floatValue], [array[5] floatValue], [array[6] floatValue], [array[7] floatValue] }, - { [array[8] floatValue], [array[9] floatValue], [array[10] floatValue], [array[11] floatValue] }, - { [array[12] floatValue], [array[13] floatValue], [array[14] floatValue], [array[15] floatValue] } - } }; -} diff --git a/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.h b/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.h deleted file mode 100644 index beaf2bf9d093..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.h +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import -#import "GLTFEnums.h" - -NS_ASSUME_NONNULL_BEGIN - -extern const NSInteger GLTFVertexDescriptorMaxAttributeCount; -extern const NSInteger GLTFVertexDescriptorMaxBufferLayoutCount; - -extern NSString *const GLTFAttributeSemanticPosition; -extern NSString *const GLTFAttributeSemanticTangent; -extern NSString *const GLTFAttributeSemanticNormal; -extern NSString *const GLTFAttributeSemanticTexCoord0; -extern NSString *const GLTFAttributeSemanticTexCoord1; -extern NSString *const GLTFAttributeSemanticColor0; -extern NSString *const GLTFAttributeSemanticJoints0; -extern NSString *const GLTFAttributeSemanticJoints1; -extern NSString *const GLTFAttributeSemanticWeights0; -extern NSString *const GLTFAttributeSemanticWeights1; -extern NSString *const GLTFAttributeSemanticRoughness; -extern NSString *const GLTFAttributeSemanticMetallic; - -@interface GLTFVertexAttribute : NSObject -@property (nonatomic, copy) NSString *semantic; -@property (nonatomic, assign) GLTFDataType componentType; -@property (nonatomic, assign) GLTFDataDimension dimension; -@property (nonatomic, assign) NSInteger offset; -@end - -@interface GLTFBufferLayout : NSObject -@property (nonatomic, assign) NSInteger stride; -@end - -@interface GLTFVertexDescriptor : NSObject -@property (nonatomic, copy) NSArray *attributes; -@property (nonatomic, copy) NSArray *bufferLayouts; -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.mm b/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.mm deleted file mode 100644 index 599d8706baa9..000000000000 --- a/platform/darwin/src/gltf/gltfkit/GLTFVertexDescriptor.mm +++ /dev/null @@ -1,71 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#import "GLTFVertexDescriptor.h" - -const NSInteger GLTFVertexDescriptorMaxAttributeCount = 16; -const NSInteger GLTFVertexDescriptorMaxBufferLayoutCount = 16; - -NSString *const GLTFAttributeSemanticPosition = @"POSITION"; -NSString *const GLTFAttributeSemanticTangent = @"TANGENT"; -NSString *const GLTFAttributeSemanticNormal = @"NORMAL"; -NSString *const GLTFAttributeSemanticTexCoord0 = @"TEXCOORD_0"; -NSString *const GLTFAttributeSemanticTexCoord1 = @"TEXCOORD_1"; -NSString *const GLTFAttributeSemanticColor0 = @"COLOR_0"; -NSString *const GLTFAttributeSemanticJoints0 = @"JOINTS_0"; -NSString *const GLTFAttributeSemanticJoints1 = @"JOINTS_1"; -NSString *const GLTFAttributeSemanticWeights0 = @"WEIGHTS_0"; -NSString *const GLTFAttributeSemanticWeights1 = @"WEIGHTS_1"; -NSString *const GLTFAttributeSemanticRoughness = @"ROUGHNESS"; -NSString *const GLTFAttributeSemanticMetallic = @"METALLIC"; - -@implementation GLTFVertexAttribute - -- (NSString *)description { - return [NSString stringWithFormat:@"GLTFVertexAttribute: component type: %d, count: %d, offset %d [[%@]]", - (int)self.componentType, (int)self.dimension, (int)self.offset, self.semantic]; -} - -@end - -@implementation GLTFBufferLayout -@end - -@implementation GLTFVertexDescriptor - -- (instancetype)init { - if ((self = [super init])) { - NSMutableArray *mutableAttributes = [NSMutableArray arrayWithCapacity:GLTFVertexDescriptorMaxAttributeCount]; - for (int i = 0; i < GLTFVertexDescriptorMaxAttributeCount; ++i) { - [mutableAttributes addObject: [GLTFVertexAttribute new]]; - } - _attributes = [mutableAttributes copy]; - - NSMutableArray *mutableLayouts = [NSMutableArray arrayWithCapacity:GLTFVertexDescriptorMaxBufferLayoutCount]; - for (int i = 0; i < GLTFVertexDescriptorMaxBufferLayoutCount; ++i) { - [mutableLayouts addObject: [GLTFBufferLayout new]]; - } - _bufferLayouts = [mutableLayouts copy]; - } - return self; -} - -- (NSString *)description { - return [NSString stringWithFormat:@"GLTFVertexDescriptor:\nattributes: %@\nlayouts: %@", - self.attributes, self.bufferLayouts]; -} - -@end diff --git a/platform/darwin/src/gltf/gltfkit/shaders/brdf.metal b/platform/darwin/src/gltf/gltfkit/shaders/brdf.metal deleted file mode 100644 index 1f4e6b732872..000000000000 --- a/platform/darwin/src/gltf/gltfkit/shaders/brdf.metal +++ /dev/null @@ -1,230 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#include -using namespace metal; - -// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html -static float RadicalInverse_VdC(uint bits) -{ - bits = (bits << 16u) | (bits >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - return float(bits) * 2.3283064365386963e-10; // / 0x100000000 -} - -static float2 Hammersley(uint i, uint N) { - return float2(float(i) / float(N), RadicalInverse_VdC(i)); -} - -// http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf -static float GeometrySchlickGGX(float NdotV, float roughness) { - float a = roughness; - float k = (a * a) / 2.0; - return NdotV / (NdotV * (1.0 - k) + k); -} - -static float GeometrySmith(float NdotL, float NdotV, float roughness) { - float ggx2 = GeometrySchlickGGX(NdotV, roughness); - float ggx1 = GeometrySchlickGGX(NdotL, roughness); - return ggx1 * ggx2; -} - -static float3 ImportanceSampleGGX(float2 xi, float3 N, float roughness) { - float a = roughness * roughness; - float phi = 2 * M_PI_F * xi.x; - float cosTheta = sqrt((1 - xi.y) / (1 + (a * a - 1) * xi.y)); - float sinTheta = sqrt(1 - cosTheta * cosTheta); - - float3 H(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); - - float3 up = fabs(N.z) < 0.999 ? float3(0, 0, 1) : float3(1, 0, 0); - float3 tangent = normalize(cross(up, N)); - float3 bitangent = cross(N, tangent); - - return normalize(tangent * H.x + bitangent * H.y + N * H.z); -} - -static float2 IntegrateBRDF(float roughness, float NdotV) { - float3 N(0, 0, 1); - float3 V(sqrt(1.0 - NdotV * NdotV), 0, NdotV); - float A = 0; - float B = 0; - - const uint sampleCount = 1024; - for(uint i = 0; i < sampleCount; ++i) { - float2 x = Hammersley(i, sampleCount); - float3 H = ImportanceSampleGGX(x, N, roughness); - float3 L = normalize(2 * dot(V, H) * H - V); - - float NdotL = saturate(L.z); - float NdotH = saturate(H.z); - float VdotH = saturate(dot(V, H)); - - if(NdotL > 0) { - float G = GeometrySmith(NdotL, NdotV, roughness); - float G_Vis = G * VdotH / (NdotH * NdotV); - float Fc = powr(1 - VdotH, 5); - A += (1 - Fc) * G_Vis; - B += Fc * G_Vis; - } - } - - return float2(A, B) / float(sampleCount); -} - -kernel void integrate_brdf(texture2d lookup [[texture(0)]], - uint2 tpig [[thread_position_in_grid]]) -{ - float NdotV = (tpig.x + 1) / float(lookup.get_width()); - float roughness = (tpig.y + 1) / float(lookup.get_height()); - float2 scaleAndBias = IntegrateBRDF(roughness, NdotV); - half4 color(scaleAndBias.x, scaleAndBias.y, 0, 0); - lookup.write(color, tpig); -} - -static float2 CubeToEquirectCoords(float3 v) { - const float2 invAtan(0.1591, 0.3183); - float2 uv = float2(atan2(v.z, v.x), asin(v.y)) * invAtan + 0.5; - return uv; -} - -static float3 CubeDirectionFromUVAndFace(float2 uv, int face) { - float u = uv.x; - float v = uv.y; - float3 dir = float3(0); - switch (face) { - case 0: - dir = float3(-1, v, -u); break; // +X - case 1: - dir = float3( 1, v, u); break; // -X - case 2: - dir = float3(-u, -1, v); break; // +Y - case 3: - dir = float3(-u, 1, -v); break; // -Y - case 4: - dir = float3(-u, v, 1); break; // +Z - case 5: - dir = float3( u, v, -1); break; // -Z - } - - dir = normalize(dir); - return dir; -} - -kernel void equirect_to_cube(texture2d equirectangularMap, - texturecube cubeMap, - uint3 tpig [[thread_position_in_grid]]) -{ - constexpr sampler sampler2d(coord::normalized, filter::linear, address::repeat); - - float cubeSize = cubeMap.get_width(); - float2 cubeUV = ((float2(tpig.xy) / cubeSize) * 2 - 1); - int face = tpig.z; - float3 dir = CubeDirectionFromUVAndFace(cubeUV, face); - float2 rectUV = CubeToEquirectCoords(dir); - half4 color = equirectangularMap.sample(sampler2d, rectUV); - uint2 coords = tpig.xy; - cubeMap.write(color, coords, face); -} - -static float3 ComputeIrradiance(float3 N, texturecube environmentTexture) { - constexpr sampler cubeSampler(coord::normalized, filter::linear); - float3 irradiance = float3(0.0); - - float3 up(0.0, 1.0, 0.0); - float3 right = cross(up, N); - up = cross(N, right); - - float sampleDelta = 0.025; - float sampleCount = 0; - for (float phi = 0.0; phi < M_PI_F * 2; phi += sampleDelta) { - for (float theta = 0.0; theta < M_PI_F * 0.5; theta += sampleDelta) { - // spherical to cartesian (in tangent space) - float3 tangentSample(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); - // tangent space to world - float3 dir = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N; - - irradiance += float3(environmentTexture.sample(cubeSampler, dir).rgb) * cos(theta) * sin(theta); - sampleCount += 1; - } - } - - irradiance = M_PI_F * irradiance * (1.0 / sampleCount); - return irradiance; -} - -kernel void compute_irradiance(texturecube environmentMap, - texturecube irradianceMap, - uint3 tpig [[thread_position_in_grid]]) -{ - float cubeSize = irradianceMap.get_width(); - float2 cubeUV = ((float2(tpig.xy) / cubeSize) * 2 - 1); - int face = tpig.z; - float3 dir = CubeDirectionFromUVAndFace(cubeUV, face); - dir *= float3(-1, -1, 1); - float3 irrad = ComputeIrradiance(dir, environmentMap); - uint2 coords = tpig.xy; - irradianceMap.write(half4(half3(irrad), 1), coords, face); -} - -static float3 PrefilterEnvMap(float roughness, float3 R, texturecube environmentTexture) { - constexpr sampler cubeSampler(coord::normalized, filter::linear, mip_filter::linear); - - float3 N = R; - float3 V = R; - - float3 prefilteredColor(0); - float totalWeight = 0; - float resolution = environmentTexture.get_width(); - float saTexel = 4.0 * M_PI_F / (6.0 * resolution * resolution); - - const uint sampleCount = 512; - for(uint i = 0; i < sampleCount; ++i) { - float2 xi = Hammersley(i, sampleCount); - float3 H = ImportanceSampleGGX(xi, N, roughness); - float3 L = normalize(2 * dot(V, H) * H - V); - float NdotL = saturate(dot(N, L)); - if(NdotL > 0) { - float NdotH = saturate(dot(N, H)); - float HdotV = saturate(dot(H, V)); - float D = GeometrySchlickGGX(NdotH, roughness); - float pdf = (D * NdotH / (4.0 * HdotV)) + 0.0001; - float saSample = 1.0 / (float(sampleCount) * pdf + 0.0001); - float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel); - prefilteredColor += NdotL * float3(environmentTexture.sample(cubeSampler, L, level(mipLevel)).rgb); - totalWeight += NdotL; - } - } - return prefilteredColor / totalWeight; -} - -kernel void compute_prefiltered_specular(texturecube environmentMap, - texturecube specularMap, - constant float &roughness [[buffer(0)]], - uint3 tpig [[thread_position_in_grid]]) -{ - float cubeSize = specularMap.get_width(); - float2 cubeUV = ((float2(tpig.xy) / cubeSize) * 2 - 1); - int face = tpig.z; - float3 dir = CubeDirectionFromUVAndFace(cubeUV, face); - dir *= float3(-1, -1, 1); - float3 irrad = PrefilterEnvMap(roughness, dir, environmentMap); - uint2 coords = tpig.xy; - specularMap.write(half4(half3(irrad), 1), coords, face); -} diff --git a/platform/darwin/src/gltf/gltfkit/shaders/hdr.metal b/platform/darwin/src/gltf/gltfkit/shaders/hdr.metal deleted file mode 100644 index bb7f505a1a9f..000000000000 --- a/platform/darwin/src/gltf/gltfkit/shaders/hdr.metal +++ /dev/null @@ -1,123 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#include -using namespace metal; - -constexpr sampler linearSampler(coord::normalized, min_filter::linear, mag_filter::linear); -constexpr sampler nearestSampler(coord::normalized, min_filter::nearest, mag_filter::nearest); - -struct VertexOut { - float4 position [[position]]; - float2 texCoords; -}; - -vertex VertexOut quad_vertex_main(constant packed_float4 *vertices [[buffer(0)]], - uint vid [[vertex_id]]) -{ - VertexOut out; - float4 in = vertices[vid]; - out.position = float4(in.xy, 0, 1); - out.texCoords = in.zw; - return out; -} - -typedef VertexOut FragmentIn; - -static half3 reinhardToneMapping(half3 color) { - half exposure = 1.5; - color *= exposure / (1 + color / exposure); - return color; -} - -fragment half4 tonemap_fragment_main(FragmentIn in [[stage_in]], - texture2d sourceTexture [[texture(0)]]) -{ - // Original, pre-alpha -// half3 color = sourceTexture.sample(linearSampler, in.texCoords).rgb; -// return half4(reinhardToneMapping(color), 1); - - half4 color = sourceTexture.sample(linearSampler, in.texCoords); - return half4(reinhardToneMapping(color.rgb), color.a); - -} - - -fragment half4 bloom_threshold_fragment_main(FragmentIn in [[stage_in]], - texture2d sourceTexture [[texture(0)]]) -{ - const float bloomThreshold = 0.88; - const float bloomIntensity = 2; - half4 color = sourceTexture.sample(linearSampler, in.texCoords); - half luma = dot(color.rgb, half3(0.2126, 0.7152, 0.0722)); - return (luma > bloomThreshold) ? color * bloomIntensity : half4(0, 0, 0, 1); -} - -fragment half4 blur_horizontal7_fragment_main(FragmentIn in [[stage_in]], - texture2d sourceTexture [[texture(0)]]) -{ - float weights[]{ 0.134032, 0.126854, 0.107545, 0.08167, 0.055555, 0.033851, 0.018476, 0.009033 }; - float offset = 1.0 / sourceTexture.get_width(); - half4 color(0); - color += weights[7] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 7, 0)); - color += weights[6] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 6, 0)); - color += weights[5] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 5, 0)); - color += weights[4] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 4, 0)); - color += weights[3] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 3, 0)); - color += weights[2] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 2, 0)); - color += weights[1] * sourceTexture.sample(nearestSampler, in.texCoords - float2(offset * 1, 0)); - color += weights[0] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 0, 0)); - color += weights[1] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 1, 0)); - color += weights[2] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 2, 0)); - color += weights[3] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 3, 0)); - color += weights[4] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 4, 0)); - color += weights[5] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 5, 0)); - color += weights[6] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 6, 0)); - color += weights[7] * sourceTexture.sample(nearestSampler, in.texCoords + float2(offset * 7, 0)); - return color; -} - -fragment half4 blur_vertical7_fragment_main(FragmentIn in [[stage_in]], - texture2d sourceTexture [[texture(0)]]) -{ - float weights[]{ 0.134032, 0.126854, 0.107545, 0.08167, 0.055555, 0.033851, 0.018476, 0.009033 }; - float offset = 1.0 / sourceTexture.get_height(); - half4 color(0); - color += weights[7] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 7)); - color += weights[6] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 6)); - color += weights[5] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 5)); - color += weights[4] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 4)); - color += weights[3] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 3)); - color += weights[2] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 2)); - color += weights[1] * sourceTexture.sample(nearestSampler, in.texCoords - float2(0, offset * 1)); - color += weights[0] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 0)); - color += weights[1] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 1)); - color += weights[2] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 2)); - color += weights[3] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 3)); - color += weights[4] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 4)); - color += weights[5] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 5)); - color += weights[6] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 6)); - color += weights[7] * sourceTexture.sample(nearestSampler, in.texCoords + float2(0, offset * 7)); - return color; -} - -fragment half4 additive_blend_fragment_main(FragmentIn in [[stage_in]], - texture2d sourceTexture [[texture(0)]]) -{ - half4 color = sourceTexture.sample(linearSampler, in.texCoords); - return color; -} - diff --git a/platform/darwin/src/gltf/gltfkit/shaders/pbr.metal b/platform/darwin/src/gltf/gltfkit/shaders/pbr.metal deleted file mode 100644 index ad5ae9409c17..000000000000 --- a/platform/darwin/src/gltf/gltfkit/shaders/pbr.metal +++ /dev/null @@ -1,463 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#include -using namespace metal; - -constant half minRoughness = 0.04; - -constant int textureIndexBaseColor = 0; -constant int textureIndexNormal = 1; -constant int textureIndexMetallicRoughness = 2; -constant int textureIndexOcclusion = 3; -constant int textureIndexEmissive = 4; -constant int textureIndexDiffuseEnvironment = 5; -constant int textureIndexSpecularEnvironment = 6; -constant int textureIndexBRDFLookup = 7; - -/*%begin_replace_decls%*/ -#define USE_PBR 1 -#define USE_IBL 1 -#define USE_ALPHA_TEST 0 -#define USE_VERTEX_SKINNING 1 -#define USE_EXTENDED_VERTEX_SKINNING 1 -#define USE_DOUBLE_SIDED_MATERIAL 1 -#define HAS_TEXCOORD_0 1 -#define HAS_TEXCOORD_1 1 -#define HAS_VERTEX_COLOR 1 -#define HAS_VERTEX_ROUGHNESS 1 -#define HAS_VERTEX_METALLIC 1 -#define HAS_NORMALS 1 -#define HAS_TANGENTS 1 -#define HAS_BASE_COLOR_MAP 1 -#define HAS_NORMAL_MAP 1 -#define HAS_METALLIC_ROUGHNESS_MAP 1 -#define HAS_OCCLUSION_MAP 1 -#define HAS_EMISSIVE_MAP 1 -#define HAS_TEXTURE_TRANSFORM 1 -#define MATERIAL_IS_UNLIT 0 -#define PREMULTIPLY_BASE_COLOR 1 -#define SPECULAR_ENV_MIP_LEVELS 6 -#define MAX_LIGHTS 3 -#define MAX_MATERIAL_TEXTURES 5 - -#define BaseColorTexCoord texCoord0 -#define NormalTexCoord texCoord0 -#define MetallicRoughnessTexCoord texCoord0 -#define EmissiveTexCoord texCoord0 -#define OcclusionTexCoord texCoord0 - -struct VertexIn { - float3 position [[attribute(0)]]; - float3 normal [[attribute(1)]]; - float4 tangent [[attribute(2)]]; - float2 texCoord0 [[attribute(3)]]; - float2 texCoord1 [[attribute(4)]]; - float4 color [[attribute(5)]]; - float4 weights0 [[attribute(6)]]; - float4 weights1 [[attribute(7)]]; - ushort4 joints0 [[attribute(8)]]; - ushort4 joints1 [[attribute(9)]]; - float roughness [[attribute(10)]]; - float metalness [[attribute(11)]]; -}; -/*%end_replace_decls%*/ - -struct VertexOut { - float4 position [[position]]; - float3 worldPosition; - float2 texCoord0; - float2 texCoord1; - float4 color; - float3 tangent; - float3 bitangent; - float3 normal; - float roughness; - float metalness; -}; - -struct VertexUniforms { - float4x4 modelMatrix; - float4x4 modelViewProjectionMatrix; - float4x4 normalMatrix; -}; - -struct Light { - float4 position; - float4 color; - float intensity; - float innerConeAngle; - float outerConeAngle; - float range; - float4 spotDirection; -}; - -struct FragmentUniforms { - float normalScale; - float3 emissiveFactor; - float occlusionStrength; - float2 metallicRoughnessValues; - float4 baseColorFactor; - float3 camera; - float alphaCutoff; - float envIntensity; - Light ambientLight; - Light lights[MAX_LIGHTS]; - float3x3 textureMatrices[MAX_MATERIAL_TEXTURES]; -}; - -vertex VertexOut vertex_main(VertexIn in [[stage_in]], - constant VertexUniforms &uniforms [[buffer(16)]] -#if USE_VERTEX_SKINNING - , constant float4x4 *jointMatrices [[buffer(17)]] -#endif -) -{ - VertexOut out = { 0 }; - - float4x4 normalMatrix = uniforms.normalMatrix; - - #if USE_VERTEX_SKINNING - ushort4 jointIndices = ushort4(in.joints0); - float4 jointWeights = float4(in.weights0); - - float4x4 skinMatrix = jointWeights[0] * jointMatrices[jointIndices[0]] + - jointWeights[1] * jointMatrices[jointIndices[1]] + - jointWeights[2] * jointMatrices[jointIndices[2]] + - jointWeights[3] * jointMatrices[jointIndices[3]]; - - #if USE_EXTENDED_VERTEX_SKINNING - jointIndices = ushort4(in.joints1); - jointWeights = float4(in.weights1); - - skinMatrix += jointWeights[0] * jointMatrices[jointIndices[0]] + - jointWeights[1] * jointMatrices[jointIndices[1]] + - jointWeights[2] * jointMatrices[jointIndices[2]] + - jointWeights[3] * jointMatrices[jointIndices[3]]; - #endif - - float4 skinnedPosition = skinMatrix * float4(in.position.xyz, 1); - normalMatrix = normalMatrix * skinMatrix; - #else - float4 skinnedPosition = float4(in.position.xyz, 1); - #endif - - float4 position = uniforms.modelMatrix * skinnedPosition; - out.worldPosition = position.xyz / position.w; - - out.position = uniforms.modelViewProjectionMatrix * skinnedPosition; - - #if HAS_NORMALS - #if HAS_TANGENTS - float3 normalW = normalize(float3(normalMatrix * float4(in.normal.xyz, 0.0))); - float3 tangentW = normalize(float3(normalMatrix * float4(in.tangent.xyz, 0.0))); - float3 bitangentW = cross(normalW, tangentW) * in.tangent.w; - out.tangent = tangentW; - out.bitangent = bitangentW; - out.normal = normalW; - #else - out.normal = normalize(float3(normalMatrix * float4(in.normal.xyz, 0.0))); - #endif - #endif - - #if HAS_VERTEX_COLOR - #if VERTEX_COLOR_IS_RGB - out.color = float4(in.color, 1); - #else - out.color = in.color; - #endif - #endif - - #if HAS_VERTEX_ROUGHNESS - out.roughness = in.roughness; - #endif - - #if HAS_VERTEX_METALLIC - out.metalness = in.metalness; - #endif - - #if HAS_TEXCOORD_0 - out.texCoord0 = in.texCoord0; - #endif - - #if HAS_TEXCOORD_1 - out.texCoord1 = in.texCoord1; - #endif - - return out; -} - -static half3 LambertDiffuse(half3 baseColor) -{ - return baseColor / M_PI_F; -} - -static half3 SchlickFresnel(half3 F0, float LdotH) -{ - return F0 + (1 - F0) * pow(1.0 - LdotH, 5.0); -} - -static float SmithGeometric(float NdotL, float NdotV, float roughness) -{ - float k = roughness * 0.5; - float Gl = NdotL / ((NdotL * (1 - k)) + k); - float Gv = NdotV / ((NdotV * (1 - k)) + k); - return Gl * Gv; -} - -static float TrowbridgeReitzNDF(float NdotH, float roughness) -{ - float roughnessSq = roughness * roughness; - float f = NdotH * (NdotH * roughnessSq - NdotH) + 1; - return roughnessSq / (M_PI_F * f * f); -} - -fragment half4 fragment_main(VertexOut in [[stage_in]], -#if HAS_BASE_COLOR_MAP - texture2d baseColorTexture [[texture(textureIndexBaseColor)]], - sampler baseColorSampler [[sampler(textureIndexBaseColor)]], -#endif -#if HAS_NORMAL_MAP - texture2d normalTexture [[texture(textureIndexNormal)]], - sampler normalSampler [[sampler(textureIndexNormal)]], -#endif -#if HAS_EMISSIVE_MAP - texture2d emissiveTexture [[texture(textureIndexEmissive)]], - sampler emissiveSampler [[sampler(textureIndexEmissive)]], -#endif -#if HAS_METALLIC_ROUGHNESS_MAP - texture2d metallicRoughnessTexture [[texture(textureIndexMetallicRoughness)]], - sampler metallicRoughnessSampler [[sampler(textureIndexMetallicRoughness)]], -#endif -#if HAS_OCCLUSION_MAP - texture2d occlusionTexture [[texture(textureIndexOcclusion)]], - sampler occlusionSampler [[sampler(textureIndexOcclusion)]], -#endif -#if USE_IBL - texturecube diffuseEnvTexture [[texture(textureIndexDiffuseEnvironment)]], - texturecube specularEnvTexture [[texture(textureIndexSpecularEnvironment)]], - texture2d brdfLUT [[texture(textureIndexBRDFLookup)]], -#endif - constant FragmentUniforms &uniforms [[buffer(0)]], - bool frontFacing [[front_facing]]) -{ - - #if HAS_TEXTURE_TRANSFORM - float2 baseColorTexCoord = (uniforms.textureMatrices[textureIndexBaseColor] * float3(in.BaseColorTexCoord, 1)).xy; - float2 normalTexCoord = (uniforms.textureMatrices[textureIndexNormal] * float3(in.NormalTexCoord, 1)).xy; - float2 metallicRoughnessTexCoord = (uniforms.textureMatrices[textureIndexMetallicRoughness] * float3(in.MetallicRoughnessTexCoord, 1)).xy; - float2 occlusionTexCoord = (uniforms.textureMatrices[textureIndexOcclusion] * float3(in.OcclusionTexCoord, 1)).xy; - float2 emissiveTexCoord = (uniforms.textureMatrices[textureIndexEmissive] * float3(in.EmissiveTexCoord, 1)).xy; - #else - float2 baseColorTexCoord = in.BaseColorTexCoord; - float2 normalTexCoord = in.NormalTexCoord; - float2 metallicRoughnessTexCoord = in.MetallicRoughnessTexCoord; - float2 occlusionTexCoord = in.OcclusionTexCoord; - float2 emissiveTexCoord = in.EmissiveTexCoord; - #endif - - float3x3 tbn; - #if !HAS_TANGENTS - float3 pos_dx = dfdx(in.worldPosition); - float3 pos_dy = dfdy(in.worldPosition); - float3 tex_dx = dfdx(float3(normalTexCoord, 0)); - float3 tex_dy = dfdy(float3(normalTexCoord, 0)); - float3 t = (tex_dy.y * pos_dx - tex_dx.y * pos_dy) / (tex_dx.x * tex_dy.y - tex_dy.x * tex_dx.y); - - float3 ng(0); - #if HAS_NORMALS - ng = normalize(in.normal); - #else - ng = cross(pos_dx, pos_dy); - #endif - t = normalize(t - ng * dot(ng, t)); - float3 b = normalize(cross(ng, t)); - tbn = float3x3(t, b, ng); - #else - tbn = float3x3(in.tangent, in.bitangent, in.normal); - #endif - - float3 N(0, 0, 1); - #if HAS_NORMAL_MAP - N = normalTexture.sample(normalSampler, normalTexCoord).rgb; - N = normalize(tbn * ((2 * N - 1) * float3(uniforms.normalScale, uniforms.normalScale, 1))); - #else - N = tbn[2].xyz; - #endif - - #if USE_DOUBLE_SIDED_MATERIAL - N *= frontFacing ? 1 : -1; - #endif - - half perceptualRoughness = uniforms.metallicRoughnessValues.y; - half metallic = uniforms.metallicRoughnessValues.x; - - #if HAS_METALLIC_ROUGHNESS_MAP - half4 mrSample = metallicRoughnessTexture.sample(metallicRoughnessSampler, metallicRoughnessTexCoord); - perceptualRoughness = mrSample.g * perceptualRoughness; - metallic = mrSample.b * metallic; - #endif - - #if HAS_VERTEX_ROUGHNESS - perceptualRoughness = in.roughness; - #endif - - #if HAS_VERTEX_METALLIC - metallic = in.metalness; - #endif - - perceptualRoughness = clamp(perceptualRoughness, minRoughness, 1.0h); - metallic = saturate(metallic); - - half4 baseColor; - #if HAS_BASE_COLOR_MAP - baseColor = baseColorTexture.sample(baseColorSampler, baseColorTexCoord); - #if PREMULTIPLY_BASE_COLOR - baseColor.rgb *= baseColor.a; - #endif - baseColor *= half4(uniforms.baseColorFactor); - #else - baseColor = half4(uniforms.baseColorFactor); - #endif - - #if HAS_VERTEX_COLOR - baseColor *= half4(in.color); - #endif - - #if MATERIAL_IS_UNLIT - #if USE_ALPHA_TEST - if (baseColor.a < uniforms.alphaCutoff) { - discard_fragment(); - } - #endif - return baseColor; - #endif - - half3 f0(0.04); - half3 diffuseColor = mix(baseColor.rgb * (1 - f0), half3(0), metallic); - half3 specularColor = mix(f0, baseColor.rgb, metallic); - - half3 F0 = specularColor.rgb; - - float alphaRoughness = perceptualRoughness * perceptualRoughness; - - float3 V = normalize(uniforms.camera - in.worldPosition); - float NdotV = saturate(dot(N, V)); - - float3 reflection = normalize(reflect(V, N)) * float3(-1, -1, 1); - - half3 color(0); - - #if USE_PBR - color += half3(uniforms.ambientLight.color.rgb * uniforms.ambientLight.intensity) * diffuseColor; - - for (int i = 0; i < MAX_LIGHTS; ++i) { - Light light = uniforms.lights[i]; - - float3 L = normalize((light.position.w == 0) ? -light.position.xyz : (light.position.xyz - in.worldPosition)); - float3 H = normalize(L + V); - - float NdotL = saturate(dot(N, L)); - float NdotH = saturate(dot(N, H)); - float VdotH = saturate(dot(V, H)); - - half3 F = SchlickFresnel(F0, VdotH); - float G = SmithGeometric(NdotL, NdotV, alphaRoughness); - float D = TrowbridgeReitzNDF(NdotH, alphaRoughness); - - half3 diffuseContrib(0); - half3 specContrib(0); - if (NdotL > 0) { - diffuseContrib = NdotL * LambertDiffuse(diffuseColor); - specContrib = NdotL * D * F * G / (4.0 * NdotL * NdotV); - } - - half lightDist = length(light.position.xyz - in.worldPosition); - half attenNum = (light.range > 0) ? saturate(1.0 - powr(lightDist / light.range, 4)) : 1; - half atten = (light.position.w == 0) ? 1 : attenNum / powr(lightDist, 2); - - float relativeSpotAngle = acos(dot(-L, normalize(light.spotDirection.xyz))); - float spotAttenParam = 1 - clamp((relativeSpotAngle - light.innerConeAngle) / max(0.001, light.outerConeAngle - light.innerConeAngle), 0.0, 1.0); - float spotAtten = spotAttenParam * spotAttenParam * (3 - 2 * spotAttenParam); - atten *= spotAtten; - - color += half3(light.color.rgb * light.intensity) * atten * (diffuseContrib + specContrib); - } - #endif - -// baseColor = baseColorTexture.sample(baseColorSampler, baseColorTexCoord); - - half3 diffuseLight1 = half3(0.5,0.5,0.5); - diffuseLight1 *= uniforms.envIntensity; - half3 specularLight1(0.5); - specularLight1 *= uniforms.envIntensity; - half3 iblDiffuse1 = diffuseLight1 * diffuseColor; - half3 iblSpecular1 = specularLight1;// * ((specularColor * brdf.x) + brdf.y); - half3 iblColor1 = iblDiffuse1 + iblSpecular1; - color += iblColor1; - color = baseColor.rgb * NdotV; - - - - - return half4(color, baseColor.a); - - - #if USE_IBL - constexpr sampler cubeSampler(coord::normalized, filter::linear, mip_filter::linear); - float mipCount = SPECULAR_ENV_MIP_LEVELS; - float lod = perceptualRoughness * (mipCount - 1); - half2 brdf = brdfLUT.sample(cubeSampler, float2(NdotV, perceptualRoughness)).xy; - half3 diffuseLight = diffuseEnvTexture.sample(cubeSampler, N).rgb; - diffuseLight *= uniforms.envIntensity; - - half3 specularLight(0); - if (mipCount > 1) { - specularLight = specularEnvTexture.sample(cubeSampler, reflection, level(lod)).rgb; - } else { - specularLight = specularEnvTexture.sample(cubeSampler, reflection).rgb; - } - specularLight *= uniforms.envIntensity; - - half3 iblDiffuse = diffuseLight * diffuseColor; - half3 iblSpecular = specularLight * ((specularColor * brdf.x) + brdf.y); - - half3 iblColor = iblDiffuse + iblSpecular; - - color += iblColor; - #endif - - - #if HAS_OCCLUSION_MAP - half ao = occlusionTexture.sample(occlusionSampler, occlusionTexCoord).r; - color = mix(color, color * ao, half(uniforms.occlusionStrength)); - #endif - - #if HAS_EMISSIVE_MAP - half3 emissive = emissiveTexture.sample(emissiveSampler, emissiveTexCoord).rgb; - color += emissive * half3(uniforms.emissiveFactor); - #else - color += half3(uniforms.emissiveFactor); - #endif - - #if USE_ALPHA_TEST - if (baseColor.a < uniforms.alphaCutoff) { - discard_fragment(); - } - #endif - - return half4(color, baseColor.a); -} diff --git a/platform/darwin/src/gltf/gltfkit/shaders/pbr.txt b/platform/darwin/src/gltf/gltfkit/shaders/pbr.txt deleted file mode 100644 index ad5ae9409c17..000000000000 --- a/platform/darwin/src/gltf/gltfkit/shaders/pbr.txt +++ /dev/null @@ -1,463 +0,0 @@ -// -// Copyright (c) 2018 Warren Moore. All rights reserved. -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// - -#include -using namespace metal; - -constant half minRoughness = 0.04; - -constant int textureIndexBaseColor = 0; -constant int textureIndexNormal = 1; -constant int textureIndexMetallicRoughness = 2; -constant int textureIndexOcclusion = 3; -constant int textureIndexEmissive = 4; -constant int textureIndexDiffuseEnvironment = 5; -constant int textureIndexSpecularEnvironment = 6; -constant int textureIndexBRDFLookup = 7; - -/*%begin_replace_decls%*/ -#define USE_PBR 1 -#define USE_IBL 1 -#define USE_ALPHA_TEST 0 -#define USE_VERTEX_SKINNING 1 -#define USE_EXTENDED_VERTEX_SKINNING 1 -#define USE_DOUBLE_SIDED_MATERIAL 1 -#define HAS_TEXCOORD_0 1 -#define HAS_TEXCOORD_1 1 -#define HAS_VERTEX_COLOR 1 -#define HAS_VERTEX_ROUGHNESS 1 -#define HAS_VERTEX_METALLIC 1 -#define HAS_NORMALS 1 -#define HAS_TANGENTS 1 -#define HAS_BASE_COLOR_MAP 1 -#define HAS_NORMAL_MAP 1 -#define HAS_METALLIC_ROUGHNESS_MAP 1 -#define HAS_OCCLUSION_MAP 1 -#define HAS_EMISSIVE_MAP 1 -#define HAS_TEXTURE_TRANSFORM 1 -#define MATERIAL_IS_UNLIT 0 -#define PREMULTIPLY_BASE_COLOR 1 -#define SPECULAR_ENV_MIP_LEVELS 6 -#define MAX_LIGHTS 3 -#define MAX_MATERIAL_TEXTURES 5 - -#define BaseColorTexCoord texCoord0 -#define NormalTexCoord texCoord0 -#define MetallicRoughnessTexCoord texCoord0 -#define EmissiveTexCoord texCoord0 -#define OcclusionTexCoord texCoord0 - -struct VertexIn { - float3 position [[attribute(0)]]; - float3 normal [[attribute(1)]]; - float4 tangent [[attribute(2)]]; - float2 texCoord0 [[attribute(3)]]; - float2 texCoord1 [[attribute(4)]]; - float4 color [[attribute(5)]]; - float4 weights0 [[attribute(6)]]; - float4 weights1 [[attribute(7)]]; - ushort4 joints0 [[attribute(8)]]; - ushort4 joints1 [[attribute(9)]]; - float roughness [[attribute(10)]]; - float metalness [[attribute(11)]]; -}; -/*%end_replace_decls%*/ - -struct VertexOut { - float4 position [[position]]; - float3 worldPosition; - float2 texCoord0; - float2 texCoord1; - float4 color; - float3 tangent; - float3 bitangent; - float3 normal; - float roughness; - float metalness; -}; - -struct VertexUniforms { - float4x4 modelMatrix; - float4x4 modelViewProjectionMatrix; - float4x4 normalMatrix; -}; - -struct Light { - float4 position; - float4 color; - float intensity; - float innerConeAngle; - float outerConeAngle; - float range; - float4 spotDirection; -}; - -struct FragmentUniforms { - float normalScale; - float3 emissiveFactor; - float occlusionStrength; - float2 metallicRoughnessValues; - float4 baseColorFactor; - float3 camera; - float alphaCutoff; - float envIntensity; - Light ambientLight; - Light lights[MAX_LIGHTS]; - float3x3 textureMatrices[MAX_MATERIAL_TEXTURES]; -}; - -vertex VertexOut vertex_main(VertexIn in [[stage_in]], - constant VertexUniforms &uniforms [[buffer(16)]] -#if USE_VERTEX_SKINNING - , constant float4x4 *jointMatrices [[buffer(17)]] -#endif -) -{ - VertexOut out = { 0 }; - - float4x4 normalMatrix = uniforms.normalMatrix; - - #if USE_VERTEX_SKINNING - ushort4 jointIndices = ushort4(in.joints0); - float4 jointWeights = float4(in.weights0); - - float4x4 skinMatrix = jointWeights[0] * jointMatrices[jointIndices[0]] + - jointWeights[1] * jointMatrices[jointIndices[1]] + - jointWeights[2] * jointMatrices[jointIndices[2]] + - jointWeights[3] * jointMatrices[jointIndices[3]]; - - #if USE_EXTENDED_VERTEX_SKINNING - jointIndices = ushort4(in.joints1); - jointWeights = float4(in.weights1); - - skinMatrix += jointWeights[0] * jointMatrices[jointIndices[0]] + - jointWeights[1] * jointMatrices[jointIndices[1]] + - jointWeights[2] * jointMatrices[jointIndices[2]] + - jointWeights[3] * jointMatrices[jointIndices[3]]; - #endif - - float4 skinnedPosition = skinMatrix * float4(in.position.xyz, 1); - normalMatrix = normalMatrix * skinMatrix; - #else - float4 skinnedPosition = float4(in.position.xyz, 1); - #endif - - float4 position = uniforms.modelMatrix * skinnedPosition; - out.worldPosition = position.xyz / position.w; - - out.position = uniforms.modelViewProjectionMatrix * skinnedPosition; - - #if HAS_NORMALS - #if HAS_TANGENTS - float3 normalW = normalize(float3(normalMatrix * float4(in.normal.xyz, 0.0))); - float3 tangentW = normalize(float3(normalMatrix * float4(in.tangent.xyz, 0.0))); - float3 bitangentW = cross(normalW, tangentW) * in.tangent.w; - out.tangent = tangentW; - out.bitangent = bitangentW; - out.normal = normalW; - #else - out.normal = normalize(float3(normalMatrix * float4(in.normal.xyz, 0.0))); - #endif - #endif - - #if HAS_VERTEX_COLOR - #if VERTEX_COLOR_IS_RGB - out.color = float4(in.color, 1); - #else - out.color = in.color; - #endif - #endif - - #if HAS_VERTEX_ROUGHNESS - out.roughness = in.roughness; - #endif - - #if HAS_VERTEX_METALLIC - out.metalness = in.metalness; - #endif - - #if HAS_TEXCOORD_0 - out.texCoord0 = in.texCoord0; - #endif - - #if HAS_TEXCOORD_1 - out.texCoord1 = in.texCoord1; - #endif - - return out; -} - -static half3 LambertDiffuse(half3 baseColor) -{ - return baseColor / M_PI_F; -} - -static half3 SchlickFresnel(half3 F0, float LdotH) -{ - return F0 + (1 - F0) * pow(1.0 - LdotH, 5.0); -} - -static float SmithGeometric(float NdotL, float NdotV, float roughness) -{ - float k = roughness * 0.5; - float Gl = NdotL / ((NdotL * (1 - k)) + k); - float Gv = NdotV / ((NdotV * (1 - k)) + k); - return Gl * Gv; -} - -static float TrowbridgeReitzNDF(float NdotH, float roughness) -{ - float roughnessSq = roughness * roughness; - float f = NdotH * (NdotH * roughnessSq - NdotH) + 1; - return roughnessSq / (M_PI_F * f * f); -} - -fragment half4 fragment_main(VertexOut in [[stage_in]], -#if HAS_BASE_COLOR_MAP - texture2d baseColorTexture [[texture(textureIndexBaseColor)]], - sampler baseColorSampler [[sampler(textureIndexBaseColor)]], -#endif -#if HAS_NORMAL_MAP - texture2d normalTexture [[texture(textureIndexNormal)]], - sampler normalSampler [[sampler(textureIndexNormal)]], -#endif -#if HAS_EMISSIVE_MAP - texture2d emissiveTexture [[texture(textureIndexEmissive)]], - sampler emissiveSampler [[sampler(textureIndexEmissive)]], -#endif -#if HAS_METALLIC_ROUGHNESS_MAP - texture2d metallicRoughnessTexture [[texture(textureIndexMetallicRoughness)]], - sampler metallicRoughnessSampler [[sampler(textureIndexMetallicRoughness)]], -#endif -#if HAS_OCCLUSION_MAP - texture2d occlusionTexture [[texture(textureIndexOcclusion)]], - sampler occlusionSampler [[sampler(textureIndexOcclusion)]], -#endif -#if USE_IBL - texturecube diffuseEnvTexture [[texture(textureIndexDiffuseEnvironment)]], - texturecube specularEnvTexture [[texture(textureIndexSpecularEnvironment)]], - texture2d brdfLUT [[texture(textureIndexBRDFLookup)]], -#endif - constant FragmentUniforms &uniforms [[buffer(0)]], - bool frontFacing [[front_facing]]) -{ - - #if HAS_TEXTURE_TRANSFORM - float2 baseColorTexCoord = (uniforms.textureMatrices[textureIndexBaseColor] * float3(in.BaseColorTexCoord, 1)).xy; - float2 normalTexCoord = (uniforms.textureMatrices[textureIndexNormal] * float3(in.NormalTexCoord, 1)).xy; - float2 metallicRoughnessTexCoord = (uniforms.textureMatrices[textureIndexMetallicRoughness] * float3(in.MetallicRoughnessTexCoord, 1)).xy; - float2 occlusionTexCoord = (uniforms.textureMatrices[textureIndexOcclusion] * float3(in.OcclusionTexCoord, 1)).xy; - float2 emissiveTexCoord = (uniforms.textureMatrices[textureIndexEmissive] * float3(in.EmissiveTexCoord, 1)).xy; - #else - float2 baseColorTexCoord = in.BaseColorTexCoord; - float2 normalTexCoord = in.NormalTexCoord; - float2 metallicRoughnessTexCoord = in.MetallicRoughnessTexCoord; - float2 occlusionTexCoord = in.OcclusionTexCoord; - float2 emissiveTexCoord = in.EmissiveTexCoord; - #endif - - float3x3 tbn; - #if !HAS_TANGENTS - float3 pos_dx = dfdx(in.worldPosition); - float3 pos_dy = dfdy(in.worldPosition); - float3 tex_dx = dfdx(float3(normalTexCoord, 0)); - float3 tex_dy = dfdy(float3(normalTexCoord, 0)); - float3 t = (tex_dy.y * pos_dx - tex_dx.y * pos_dy) / (tex_dx.x * tex_dy.y - tex_dy.x * tex_dx.y); - - float3 ng(0); - #if HAS_NORMALS - ng = normalize(in.normal); - #else - ng = cross(pos_dx, pos_dy); - #endif - t = normalize(t - ng * dot(ng, t)); - float3 b = normalize(cross(ng, t)); - tbn = float3x3(t, b, ng); - #else - tbn = float3x3(in.tangent, in.bitangent, in.normal); - #endif - - float3 N(0, 0, 1); - #if HAS_NORMAL_MAP - N = normalTexture.sample(normalSampler, normalTexCoord).rgb; - N = normalize(tbn * ((2 * N - 1) * float3(uniforms.normalScale, uniforms.normalScale, 1))); - #else - N = tbn[2].xyz; - #endif - - #if USE_DOUBLE_SIDED_MATERIAL - N *= frontFacing ? 1 : -1; - #endif - - half perceptualRoughness = uniforms.metallicRoughnessValues.y; - half metallic = uniforms.metallicRoughnessValues.x; - - #if HAS_METALLIC_ROUGHNESS_MAP - half4 mrSample = metallicRoughnessTexture.sample(metallicRoughnessSampler, metallicRoughnessTexCoord); - perceptualRoughness = mrSample.g * perceptualRoughness; - metallic = mrSample.b * metallic; - #endif - - #if HAS_VERTEX_ROUGHNESS - perceptualRoughness = in.roughness; - #endif - - #if HAS_VERTEX_METALLIC - metallic = in.metalness; - #endif - - perceptualRoughness = clamp(perceptualRoughness, minRoughness, 1.0h); - metallic = saturate(metallic); - - half4 baseColor; - #if HAS_BASE_COLOR_MAP - baseColor = baseColorTexture.sample(baseColorSampler, baseColorTexCoord); - #if PREMULTIPLY_BASE_COLOR - baseColor.rgb *= baseColor.a; - #endif - baseColor *= half4(uniforms.baseColorFactor); - #else - baseColor = half4(uniforms.baseColorFactor); - #endif - - #if HAS_VERTEX_COLOR - baseColor *= half4(in.color); - #endif - - #if MATERIAL_IS_UNLIT - #if USE_ALPHA_TEST - if (baseColor.a < uniforms.alphaCutoff) { - discard_fragment(); - } - #endif - return baseColor; - #endif - - half3 f0(0.04); - half3 diffuseColor = mix(baseColor.rgb * (1 - f0), half3(0), metallic); - half3 specularColor = mix(f0, baseColor.rgb, metallic); - - half3 F0 = specularColor.rgb; - - float alphaRoughness = perceptualRoughness * perceptualRoughness; - - float3 V = normalize(uniforms.camera - in.worldPosition); - float NdotV = saturate(dot(N, V)); - - float3 reflection = normalize(reflect(V, N)) * float3(-1, -1, 1); - - half3 color(0); - - #if USE_PBR - color += half3(uniforms.ambientLight.color.rgb * uniforms.ambientLight.intensity) * diffuseColor; - - for (int i = 0; i < MAX_LIGHTS; ++i) { - Light light = uniforms.lights[i]; - - float3 L = normalize((light.position.w == 0) ? -light.position.xyz : (light.position.xyz - in.worldPosition)); - float3 H = normalize(L + V); - - float NdotL = saturate(dot(N, L)); - float NdotH = saturate(dot(N, H)); - float VdotH = saturate(dot(V, H)); - - half3 F = SchlickFresnel(F0, VdotH); - float G = SmithGeometric(NdotL, NdotV, alphaRoughness); - float D = TrowbridgeReitzNDF(NdotH, alphaRoughness); - - half3 diffuseContrib(0); - half3 specContrib(0); - if (NdotL > 0) { - diffuseContrib = NdotL * LambertDiffuse(diffuseColor); - specContrib = NdotL * D * F * G / (4.0 * NdotL * NdotV); - } - - half lightDist = length(light.position.xyz - in.worldPosition); - half attenNum = (light.range > 0) ? saturate(1.0 - powr(lightDist / light.range, 4)) : 1; - half atten = (light.position.w == 0) ? 1 : attenNum / powr(lightDist, 2); - - float relativeSpotAngle = acos(dot(-L, normalize(light.spotDirection.xyz))); - float spotAttenParam = 1 - clamp((relativeSpotAngle - light.innerConeAngle) / max(0.001, light.outerConeAngle - light.innerConeAngle), 0.0, 1.0); - float spotAtten = spotAttenParam * spotAttenParam * (3 - 2 * spotAttenParam); - atten *= spotAtten; - - color += half3(light.color.rgb * light.intensity) * atten * (diffuseContrib + specContrib); - } - #endif - -// baseColor = baseColorTexture.sample(baseColorSampler, baseColorTexCoord); - - half3 diffuseLight1 = half3(0.5,0.5,0.5); - diffuseLight1 *= uniforms.envIntensity; - half3 specularLight1(0.5); - specularLight1 *= uniforms.envIntensity; - half3 iblDiffuse1 = diffuseLight1 * diffuseColor; - half3 iblSpecular1 = specularLight1;// * ((specularColor * brdf.x) + brdf.y); - half3 iblColor1 = iblDiffuse1 + iblSpecular1; - color += iblColor1; - color = baseColor.rgb * NdotV; - - - - - return half4(color, baseColor.a); - - - #if USE_IBL - constexpr sampler cubeSampler(coord::normalized, filter::linear, mip_filter::linear); - float mipCount = SPECULAR_ENV_MIP_LEVELS; - float lod = perceptualRoughness * (mipCount - 1); - half2 brdf = brdfLUT.sample(cubeSampler, float2(NdotV, perceptualRoughness)).xy; - half3 diffuseLight = diffuseEnvTexture.sample(cubeSampler, N).rgb; - diffuseLight *= uniforms.envIntensity; - - half3 specularLight(0); - if (mipCount > 1) { - specularLight = specularEnvTexture.sample(cubeSampler, reflection, level(lod)).rgb; - } else { - specularLight = specularEnvTexture.sample(cubeSampler, reflection).rgb; - } - specularLight *= uniforms.envIntensity; - - half3 iblDiffuse = diffuseLight * diffuseColor; - half3 iblSpecular = specularLight * ((specularColor * brdf.x) + brdf.y); - - half3 iblColor = iblDiffuse + iblSpecular; - - color += iblColor; - #endif - - - #if HAS_OCCLUSION_MAP - half ao = occlusionTexture.sample(occlusionSampler, occlusionTexCoord).r; - color = mix(color, color * ao, half(uniforms.occlusionStrength)); - #endif - - #if HAS_EMISSIVE_MAP - half3 emissive = emissiveTexture.sample(emissiveSampler, emissiveTexCoord).rgb; - color += emissive * half3(uniforms.emissiveFactor); - #else - color += half3(uniforms.emissiveFactor); - #endif - - #if USE_ALPHA_TEST - if (baseColor.a < uniforms.alphaCutoff) { - discard_fragment(); - } - #endif - - return half4(color, baseColor.a); -} diff --git a/platform/ios/BUILD.bazel b/platform/ios/BUILD.bazel index e2d15d7eb226..5adfca264247 100644 --- a/platform/ios/BUILD.bazel +++ b/platform/ios/BUILD.bazel @@ -95,7 +95,6 @@ public_hdrs = [ ":mln_defines", ":ios_public_hdrs", ":ios_sdk_hdrs", - "//platform/darwin:darwin_gltf_hdrs", "//platform/darwin:darwin_objc_hdrs", "//platform/darwin:generated_style_public_hdrs", ] From 1bdd227784473e31e86f60f2a423cd61f107f037 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 20 Aug 2025 18:51:32 +0300 Subject: [PATCH 177/221] fix frustum offset in android and ios --- include/mbgl/mtl/render_pass.hpp | 3 +++ src/mbgl/mtl/render_pass.cpp | 12 +++++++++++- src/mbgl/renderer/renderer_impl.cpp | 4 ++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/include/mbgl/mtl/render_pass.hpp b/include/mbgl/mtl/render_pass.hpp index 799ae92a7ce9..9983135bf016 100644 --- a/include/mbgl/mtl/render_pass.hpp +++ b/include/mbgl/mtl/render_pass.hpp @@ -94,6 +94,9 @@ class RenderPass final : public gfx::RenderPass { MTL::CullMode currentCullMode = MTL::CullModeNone; MTL::Winding currentWinding = MTL::WindingClockwise; MTL::ScissorRect currentRect; + + size_t width; + size_t height; }; } // namespace mtl diff --git a/src/mbgl/mtl/render_pass.cpp b/src/mbgl/mtl/render_pass.cpp index c38a18bbd6a8..e495102dd258 100644 --- a/src/mbgl/mtl/render_pass.cpp +++ b/src/mbgl/mtl/render_pass.cpp @@ -30,6 +30,10 @@ RenderPass::RenderPass(CommandEncoder& commandEncoder_, const char* name, const } } encoder = NS::RetainPtr(buffer->renderCommandEncoder(rpd.get())); + + const auto& texture = rpd->colorAttachments()->object(0)->texture(); + width = texture->width(); + height = texture->height(); } } @@ -216,9 +220,15 @@ void RenderPass::setFrontFacingWinding(const MTL::Winding winding) { } } -void RenderPass::setScissorRect(const MTL::ScissorRect rect) { +void RenderPass::setScissorRect(MTL::ScissorRect rect) { if (rect.x != currentRect.x || rect.y != currentRect.y || rect.width != currentRect.width || rect.height != currentRect.height) { + if (rect.width + rect.x > width) { + rect.width = width - rect.x; + } + if (rect.height + rect.y > height) { + rect.height = height - rect.y; + } encoder->setScissorRect(rect); currentRect = rect; } diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index adb765f0fac3..88b3014c3235 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -190,7 +190,11 @@ void Renderer::Impl::render(const RenderTree& renderTree, const std::shared_ptr< const EdgeInsets& frustumOffset = state.getFrustumOffset(); const gfx::ScissorRect scissorRect = { static_cast(frustumOffset.left() * pixelRatio), +#if MLN_RENDER_BACKEND_OPENGL + static_cast(frustumOffset.bottom() * pixelRatio), +#else static_cast(frustumOffset.top() * pixelRatio), +#endif static_cast((size.width - (frustumOffset.left() + frustumOffset.right())) * pixelRatio), static_cast((size.height - (frustumOffset.top() + frustumOffset.bottom())) * pixelRatio), }; From 46326ced10011f3384c313a1a3943da5218ef8f3 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 20 Aug 2025 19:05:03 +0300 Subject: [PATCH 178/221] target macos-14 for ci --- .github/workflows/ios-ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ios-ci.yml b/.github/workflows/ios-ci.yml index b97bb3b2dc90..4fc7ecfacd81 100644 --- a/.github/workflows/ios-ci.yml +++ b/.github/workflows/ios-ci.yml @@ -57,7 +57,7 @@ jobs: ios-build: needs: pre_job if: needs.pre_job.outputs.should_skip != 'true' - runs-on: [macos-latest] + runs-on: [macos-14] concurrency: # cancel jobs on PRs only group: ${{ github.workflow }}-${{ github.ref }} @@ -220,7 +220,7 @@ jobs: HOSTING_BASE_PATH="maplibre-native/ios/latest" platform/ios/scripts/docc.sh ios-release: - runs-on: macos-latest + runs-on: macos-14 needs: ios-build if: github.ref == 'refs/heads/main' || github.event.inputs.release == 'pre' defaults: @@ -373,7 +373,7 @@ jobs: ios-build-cmake: needs: pre_job - runs-on: macos-latest + runs-on: macos-14 if: needs.pre_job.outputs.should_skip != 'true' steps: - uses: actions/checkout@v4 From ad83a719189d3a1a2baa2fe782de10d3a8c7c34e Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Wed, 20 Aug 2025 18:52:01 +0300 Subject: [PATCH 179/221] new ios and android release --- platform/android/CHANGELOG.md | 6 ++++++ platform/android/VERSION | 2 +- platform/ios/VERSION | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index ff5752287346..08f091bd12c0 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -2,6 +2,12 @@ ## main +## 11.13.1 + +### Bug fixes + +- Fixed frustum offset in opengl + ## 11.13.0 ### ✨ Features and improvements diff --git a/platform/android/VERSION b/platform/android/VERSION index a03dc570038e..5f7d6d2d20be 100644 --- a/platform/android/VERSION +++ b/platform/android/VERSION @@ -1 +1 @@ -11.13.0 +11.13.1 diff --git a/platform/ios/VERSION b/platform/ios/VERSION index 1b386a547006..2016ec3904eb 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.18.0 +6.18.1 From 89cb7554280beec5007b13eb0c6d1f5cf02fdfc6 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 28 Aug 2025 12:51:39 +0300 Subject: [PATCH 180/221] only update offset if we call `setVertexBuffer` previously --- include/mbgl/mtl/buffer_resource.hpp | 2 ++ src/mbgl/mtl/buffer_resource.cpp | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/mbgl/mtl/buffer_resource.hpp b/include/mbgl/mtl/buffer_resource.hpp index 4efe37a9afdf..d519666f1293 100644 --- a/include/mbgl/mtl/buffer_resource.hpp +++ b/include/mbgl/mtl/buffer_resource.hpp @@ -87,6 +87,8 @@ class BufferResource { std::uint16_t version = 0; bool isIndexBuffer; bool persistent; + + mutable bool usingVertexBuffer = false; }; } // namespace mtl diff --git a/src/mbgl/mtl/buffer_resource.cpp b/src/mbgl/mtl/buffer_resource.cpp index ab2f75174529..6e7b47161479 100644 --- a/src/mbgl/mtl/buffer_resource.cpp +++ b/src/mbgl/mtl/buffer_resource.cpp @@ -165,9 +165,11 @@ void BufferResource::bindVertex(const MTLRenderCommandEncoderPtr& encoder, assert(offset + size_ <= size); if (const auto* mtlBuf = buffer.get()) { encoder->setVertexBuffer(mtlBuf, static_cast(offset), static_cast(index)); + usingVertexBuffer = true; } else if (!raw.empty()) { size_ = size_ ? std::min(size_, size - offset) : size - offset; encoder->setVertexBytes(raw.data() + offset, size_, index); + usingVertexBuffer = false; } } @@ -192,7 +194,7 @@ void BufferResource::updateVertexBindOffset(const MTLRenderCommandEncoderPtr& en // The documentation for `setVertexBufferOffset` indicates that it should work for buffers // assigned using `setVertexBytes` but, in practice, it produces a validation failure: // `Set Vertex Buffer Offset Validation index(1) must have an existing buffer.` - if (buffer.get()) { + if (buffer.get() && usingVertexBuffer) { encoder->setVertexBufferOffset(offset, index); } else { bindVertex(encoder, offset, index, size_); From e73f0d099cf92dd905856a8cfb7dd51e56ca3127 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 28 Aug 2025 12:52:18 +0300 Subject: [PATCH 181/221] make new ios release --- platform/ios/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/VERSION b/platform/ios/VERSION index 2016ec3904eb..ab1d6151183d 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.18.1 +6.18.2 From 0eb5026073d2643598004ae37c4fde8ff85fa6ff Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Sun, 14 Sep 2025 12:38:15 +0300 Subject: [PATCH 182/221] resolve merge issues --- src/mbgl/map/map_impl.hpp | 2 -- src/mbgl/map/transform.cpp | 1 - src/mbgl/map/transform_active.cpp | 3 ++- src/mbgl/renderer/renderer_impl.cpp | 1 - 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/mbgl/map/map_impl.hpp b/src/mbgl/map/map_impl.hpp index 8552db60113b..344bc779a93d 100644 --- a/src/mbgl/map/map_impl.hpp +++ b/src/mbgl/map/map_impl.hpp @@ -17,8 +17,6 @@ #include -#include - namespace mbgl { class FileSource; diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index 4f69ff86d8f8..3de40b69835e 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -40,7 +40,6 @@ double normalizeAngle(double angle, double anchorAngle) { return angle; } -} // namespace Transform::Transform(TransformObserver& observer_, ConstrainMode constrainMode, ViewportMode viewportMode) : observer(observer_), diff --git a/src/mbgl/map/transform_active.cpp b/src/mbgl/map/transform_active.cpp index d0c651807237..2c1e997bfa00 100644 --- a/src/mbgl/map/transform_active.cpp +++ b/src/mbgl/map/transform_active.cpp @@ -13,7 +13,8 @@ void TransformActive::easeTo(const CameraOptions& inputCamera, const AnimationOp Duration duration = animationOptions.duration.value_or(Duration::zero()); if (state.getLatLngBounds() == LatLngBounds() && !isGestureInProgress() && duration != Duration::zero()) { // reuse flyTo, without exaggerated animation, to achieve constant ground speed. - return flyTo(camera, animationOptions, true); + flyTo(camera, animationOptions, true); + return; } double zoom = camera.zoom.value_or(getZoom()); diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 88b3014c3235..a901630018e5 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include From 5233bcc86a2728b16f971c72d9eae6aaa6ed06a4 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Sun, 14 Sep 2025 15:33:07 +0300 Subject: [PATCH 183/221] make new ios and android release --- platform/android/CHANGELOG.md | 6 ++++++ platform/android/VERSION | 2 +- platform/ios/VERSION | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index d701cfdb742d..fc38a2f43f85 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog MapLibre Native for Android +## 11.13.2 + +### ✨ Features and improvements + +- Sync with maplibre primary repo + ## 11.13.1 ### ✨ Features and improvements diff --git a/platform/android/VERSION b/platform/android/VERSION index 5f7d6d2d20be..ea601d579ef2 100644 --- a/platform/android/VERSION +++ b/platform/android/VERSION @@ -1 +1 @@ -11.13.1 +11.13.2 diff --git a/platform/ios/VERSION b/platform/ios/VERSION index ab1d6151183d..2e492703dc0f 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.18.2 +6.18.3 From 939060070fcdac77d2aa12d7ff4b01280ca64cf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sun, 14 Sep 2025 08:58:39 -0400 Subject: [PATCH 184/221] Added network delegate methods --- platform/darwin/core/http_file_source.mm | 13 +++++++++++++ platform/darwin/core/native_apple_interface.m | 16 ++++++++++++++++ .../mbgl/interface/native_apple_interface.h | 17 +++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/platform/darwin/core/http_file_source.mm b/platform/darwin/core/http_file_source.mm index 62ced8e7d1f3..d88f10e4b56e 100644 --- a/platform/darwin/core/http_file_source.mm +++ b/platform/darwin/core/http_file_source.mm @@ -292,11 +292,24 @@ BOOL isValidMapboxEndpoint(NSURL *url) { assert(session); + if ([networkManager.delegate respondsToSelector:@selector(willSendRequest:)]) { + req = [networkManager.delegate willSendRequest:req]; + } + request->task = [session dataTaskWithRequest:req completionHandler:^(NSData* data, NSURLResponse* res, NSError* error) { session = nil; + if ([networkManager.delegate respondsToSelector:@selector(didReceiveResponse:)]) { + NetworkResponse *networkResponse = [NetworkResponse responseWithData:data urlResponse:res error:error]; + networkResponse = [networkManager.delegate didReceiveResponse:networkResponse]; + data = networkResponse.data; + res = networkResponse.response; + error = networkResponse.error; + } + + if (error && [error code] == NSURLErrorCancelled) { [MLNNativeNetworkManager.sharedManager cancelDownloadEventForResponse:res]; return; diff --git a/platform/darwin/core/native_apple_interface.m b/platform/darwin/core/native_apple_interface.m index edd3b981d76b..5d176ea4e255 100644 --- a/platform/darwin/core/native_apple_interface.m +++ b/platform/darwin/core/native_apple_interface.m @@ -1,6 +1,22 @@ #import #import +@implementation NetworkResponse + ++(NetworkResponse *)responseWithData:(NSData *)data + urlResponse:(NSURLResponse *)response + error:(NSError *)error { + + NetworkResponse *tempResult = [[NetworkResponse alloc] init]; + tempResult.data = data; + tempResult.response = response; + tempResult.error = error; + return tempResult; +} + +@end + + @implementation MLNNativeNetworkManager static MLNNativeNetworkManager *instance = nil; diff --git a/platform/darwin/include/mbgl/interface/native_apple_interface.h b/platform/darwin/include/mbgl/interface/native_apple_interface.h index 7633819bb302..34513c5850e0 100644 --- a/platform/darwin/include/mbgl/interface/native_apple_interface.h +++ b/platform/darwin/include/mbgl/interface/native_apple_interface.h @@ -4,12 +4,29 @@ NS_ASSUME_NONNULL_BEGIN @class MLNNativeNetworkManager; +@interface NetworkResponse : NSObject + +@property (nullable) NSError *error; +@property (nullable) NSData *data; +@property NSURLResponse *response; + ++(NetworkResponse *)responseWithData:(NSData *)data + urlResponse:(NSURLResponse *)response + error:(NSError *)error; + +@end + + @protocol MLNNativeNetworkDelegate @optional - (NSURLSession *)sessionForNetworkManager:(MLNNativeNetworkManager *)networkManager; +- (NSMutableURLRequest *)willSendRequest:(NSMutableURLRequest *)request; + +- (NetworkResponse *)didReceiveResponse:(NetworkResponse *)response; + @required - (NSURLSessionConfiguration *)sessionConfiguration; From 04a34ac8ee21daac3bb105e4717882162c0baf37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sun, 14 Sep 2025 09:16:28 -0400 Subject: [PATCH 185/221] Added retain --- .../darwin/include/mbgl/interface/native_apple_interface.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/darwin/include/mbgl/interface/native_apple_interface.h b/platform/darwin/include/mbgl/interface/native_apple_interface.h index 34513c5850e0..c240c435b12c 100644 --- a/platform/darwin/include/mbgl/interface/native_apple_interface.h +++ b/platform/darwin/include/mbgl/interface/native_apple_interface.h @@ -6,8 +6,8 @@ NS_ASSUME_NONNULL_BEGIN @interface NetworkResponse : NSObject -@property (nullable) NSError *error; -@property (nullable) NSData *data; +@property (retain, nullable) NSError *error; +@property (retain, nullable) NSData *data; @property NSURLResponse *response; +(NetworkResponse *)responseWithData:(NSData *)data From c07165580ca7f70c048f92253b22b3e473aeb30e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sun, 14 Sep 2025 09:33:29 -0400 Subject: [PATCH 186/221] Updates --- platform/darwin/include/mbgl/interface/native_apple_interface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/darwin/include/mbgl/interface/native_apple_interface.h b/platform/darwin/include/mbgl/interface/native_apple_interface.h index c240c435b12c..b1d5034e1123 100644 --- a/platform/darwin/include/mbgl/interface/native_apple_interface.h +++ b/platform/darwin/include/mbgl/interface/native_apple_interface.h @@ -8,7 +8,7 @@ NS_ASSUME_NONNULL_BEGIN @property (retain, nullable) NSError *error; @property (retain, nullable) NSData *data; -@property NSURLResponse *response; +@property (retain, nullable) NSURLResponse *response; +(NetworkResponse *)responseWithData:(NSData *)data urlResponse:(NSURLResponse *)response From 3f56a90a20e897a7e082af8c45fa8ba050827db8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sun, 14 Sep 2025 10:24:58 -0400 Subject: [PATCH 187/221] Updated metadata files --- platform/android/CHANGELOG.md | 6 ++++++ platform/android/VERSION | 2 +- platform/ios/VERSION | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index fc38a2f43f85..2a22ebf83274 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog MapLibre Native for Android +## 11.13.3 + +### ✨ Features and improvements + +- Added network delegate methods in iOS + ## 11.13.2 ### ✨ Features and improvements diff --git a/platform/android/VERSION b/platform/android/VERSION index ea601d579ef2..32f0b5a51eba 100644 --- a/platform/android/VERSION +++ b/platform/android/VERSION @@ -1 +1 @@ -11.13.2 +11.13.3 diff --git a/platform/ios/VERSION b/platform/ios/VERSION index 2e492703dc0f..9e3638056b22 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.18.3 +6.18.4 From 4c5be61de5756c9082d13a3fb04551ba7441dac7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sun, 14 Sep 2025 14:47:04 -0400 Subject: [PATCH 188/221] Updates to pass pre-commit --- .../include/mbgl/interface/native_apple_interface.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/platform/darwin/include/mbgl/interface/native_apple_interface.h b/platform/darwin/include/mbgl/interface/native_apple_interface.h index b1d5034e1123..1b7547ddcd64 100644 --- a/platform/darwin/include/mbgl/interface/native_apple_interface.h +++ b/platform/darwin/include/mbgl/interface/native_apple_interface.h @@ -5,18 +5,17 @@ NS_ASSUME_NONNULL_BEGIN @class MLNNativeNetworkManager; @interface NetworkResponse : NSObject - + @property (retain, nullable) NSError *error; @property (retain, nullable) NSData *data; @property (retain, nullable) NSURLResponse *response; -+(NetworkResponse *)responseWithData:(NSData *)data - urlResponse:(NSURLResponse *)response - error:(NSError *)error; ++ (NetworkResponse *)responseWithData:(NSData *)data + urlResponse:(NSURLResponse *)response + error:(NSError *)error; @end - @protocol MLNNativeNetworkDelegate @optional From 1d149f2fa0c4a43e710a90aca8c496acbc5e0177 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Mon, 15 Sep 2025 12:13:17 +0300 Subject: [PATCH 189/221] free up diskspace when building android release --- .github/scripts/free_disk_space.sh | 47 +++++++++++++++++++++++++++ .github/workflows/android-release.yml | 4 +++ 2 files changed, 51 insertions(+) create mode 100755 .github/scripts/free_disk_space.sh diff --git a/.github/scripts/free_disk_space.sh b/.github/scripts/free_disk_space.sh new file mode 100755 index 000000000000..7982cd2560d3 --- /dev/null +++ b/.github/scripts/free_disk_space.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# +# The Azure provided machines typically have the following disk allocation: +# Total space: 85GB +# Allocated: 67 GB +# Free: 17 GB +# This script frees up 28 GB of disk space by deleting unneeded packages and +# large directories. +# The Flink end to end tests download and generate more than 17 GB of files, +# causing unpredictable behavior and build failures. +# +echo "==============================================================================" +echo "Freeing up disk space on CI system" +echo "==============================================================================" + +echo "Listing 100 largest packages" +dpkg-query -Wf '${Installed-Size}\t${Package}\n' | sort -n | tail -n 100 +df -h +echo "Removing large packages" +sudo apt-get remove -y '^ghc-8.*' +sudo apt-get remove -y '^dotnet-.*' +sudo apt-get remove -y '^llvm-.*' +sudo apt-get remove -y 'php.*' +sudo apt-get remove -y azure-cli google-cloud-sdk hhvm google-chrome-stable firefox powershell mono-devel +sudo apt-get autoremove -y +sudo apt-get clean +df -h +echo "Removing large directories" +# deleting 15GB +rm -rf /usr/share/dotnet/ +df -h diff --git a/.github/workflows/android-release.yml b/.github/workflows/android-release.yml index 71f37edc1865..f1c1ab0b87d8 100644 --- a/.github/workflows/android-release.yml +++ b/.github/workflows/android-release.yml @@ -86,6 +86,10 @@ jobs: submodules: recursive fetch-depth: 0 + - name: Free disk space + working-directory: . + run: .github/scripts/free_disk_space.sh + - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v4 with: node-version-file: ".nvmrc" From db4beada38d91e3b4493a0e0541a0b61dfada5ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Mon, 22 Sep 2025 11:49:15 -0400 Subject: [PATCH 190/221] Initial commit --- platform/darwin/bazel/files.bzl | 2 ++ platform/darwin/core/http_file_source.mm | 3 +- platform/darwin/core/native_apple_interface.m | 7 ++-- .../mbgl/interface/native_apple_interface.h | 10 +++--- platform/darwin/src/MLNNetworkConfiguration.h | 7 ++++ .../darwin/src/MLNNetworkConfiguration.mm | 33 +++++++++++++++++++ platform/darwin/src/MLNNetworkResponse.h | 24 ++++++++++++++ platform/darwin/src/MLNNetworkResponse.mm | 25 ++++++++++++++ 8 files changed, 101 insertions(+), 10 deletions(-) create mode 100644 platform/darwin/src/MLNNetworkResponse.h create mode 100644 platform/darwin/src/MLNNetworkResponse.mm diff --git a/platform/darwin/bazel/files.bzl b/platform/darwin/bazel/files.bzl index af0e842864be..16e1c0d4c544 100644 --- a/platform/darwin/bazel/files.bzl +++ b/platform/darwin/bazel/files.bzl @@ -194,6 +194,7 @@ MLN_DARWIN_OBJC_HEADERS = [ "src/NSValue+MLNAdditions.h", "src/MLNPluginLayer.h", "src/MLNPluginStyleLayer.h", + "src/MLNNetworkResponse.h", ] MLN_DARWIN_OBJCPP_HEADERS = [ @@ -308,6 +309,7 @@ MLN_DARWIN_PUBLIC_OBJCPP_SOURCE = [ "src/NSValue+MLNStyleAttributeAdditions.mm", "src/MLNPluginLayer.mm", "src/MLNPluginStyleLayer.mm", + "src/MLNNetworkResponse.mm", ] MLN_DARWIN_PUBLIC_OBJCPP_CUSTOM_DRAWABLE_SOURCE = [ "src/MLNCustomDrawableStyleLayer_Private.h", diff --git a/platform/darwin/core/http_file_source.mm b/platform/darwin/core/http_file_source.mm index d88f10e4b56e..1964968dc3b7 100644 --- a/platform/darwin/core/http_file_source.mm +++ b/platform/darwin/core/http_file_source.mm @@ -12,7 +12,6 @@ #import #include - #include #include @@ -302,7 +301,7 @@ BOOL isValidMapboxEndpoint(NSURL *url) { session = nil; if ([networkManager.delegate respondsToSelector:@selector(didReceiveResponse:)]) { - NetworkResponse *networkResponse = [NetworkResponse responseWithData:data urlResponse:res error:error]; + MLNInternalNetworkResponse *networkResponse = [MLNInternalNetworkResponse responseWithData:data urlResponse:res error:error]; networkResponse = [networkManager.delegate didReceiveResponse:networkResponse]; data = networkResponse.data; res = networkResponse.response; diff --git a/platform/darwin/core/native_apple_interface.m b/platform/darwin/core/native_apple_interface.m index 5d176ea4e255..3730d5cafbcf 100644 --- a/platform/darwin/core/native_apple_interface.m +++ b/platform/darwin/core/native_apple_interface.m @@ -1,13 +1,13 @@ #import #import -@implementation NetworkResponse +@implementation MLNInternalNetworkResponse -+(NetworkResponse *)responseWithData:(NSData *)data ++(MLNInternalNetworkResponse *)responseWithData:(NSData *)data urlResponse:(NSURLResponse *)response error:(NSError *)error { - NetworkResponse *tempResult = [[NetworkResponse alloc] init]; + MLNInternalNetworkResponse *tempResult = [[MLNInternalNetworkResponse alloc] init]; tempResult.data = data; tempResult.response = response; tempResult.error = error; @@ -17,6 +17,7 @@ +(NetworkResponse *)responseWithData:(NSData *)data @end + @implementation MLNNativeNetworkManager static MLNNativeNetworkManager *instance = nil; diff --git a/platform/darwin/include/mbgl/interface/native_apple_interface.h b/platform/darwin/include/mbgl/interface/native_apple_interface.h index 1b7547ddcd64..fc87b5198946 100644 --- a/platform/darwin/include/mbgl/interface/native_apple_interface.h +++ b/platform/darwin/include/mbgl/interface/native_apple_interface.h @@ -4,15 +4,15 @@ NS_ASSUME_NONNULL_BEGIN @class MLNNativeNetworkManager; -@interface NetworkResponse : NSObject +@interface MLNInternalNetworkResponse : NSObject @property (retain, nullable) NSError *error; @property (retain, nullable) NSData *data; @property (retain, nullable) NSURLResponse *response; -+ (NetworkResponse *)responseWithData:(NSData *)data - urlResponse:(NSURLResponse *)response - error:(NSError *)error; ++ (MLNInternalNetworkResponse *)responseWithData:(NSData *)data + urlResponse:(NSURLResponse *)response + error:(NSError *)error; @end @@ -24,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN - (NSMutableURLRequest *)willSendRequest:(NSMutableURLRequest *)request; -- (NetworkResponse *)didReceiveResponse:(NetworkResponse *)response; +- (MLNInternalNetworkResponse *)didReceiveResponse:(MLNInternalNetworkResponse *)response; @required diff --git a/platform/darwin/src/MLNNetworkConfiguration.h b/platform/darwin/src/MLNNetworkConfiguration.h index 01c0fee46f40..7b1ba3ead71e 100644 --- a/platform/darwin/src/MLNNetworkConfiguration.h +++ b/platform/darwin/src/MLNNetworkConfiguration.h @@ -1,6 +1,7 @@ #import #import "MLNFoundation.h" +#import "MLNNetworkResponse.h" NS_ASSUME_NONNULL_BEGIN @@ -24,6 +25,12 @@ NS_ASSUME_NONNULL_BEGIN are not supported at this time. */ - (NSURLSession *)sessionForNetworkConfiguration:(MLNNetworkConfiguration *)configuration; + +- (NSMutableURLRequest *)willSendRequest:(NSMutableURLRequest *)request; + +- (MLNNetworkResponse *)didReceiveResponse:(MLNNetworkResponse *)response; + + @end /** diff --git a/platform/darwin/src/MLNNetworkConfiguration.mm b/platform/darwin/src/MLNNetworkConfiguration.mm index 9cc8db3acbea..711402179cb7 100644 --- a/platform/darwin/src/MLNNetworkConfiguration.mm +++ b/platform/darwin/src/MLNNetworkConfiguration.mm @@ -87,6 +87,39 @@ - (NSURLSession *)sessionForNetworkManager:(MLNNativeNetworkManager *)networkMan return session; } +- (NSMutableURLRequest *)willSendRequest:(NSMutableURLRequest *)request { + + if ([self.delegate respondsToSelector:@selector(willSendRequest:)]) { + return [self.delegate willSendRequest:request]; + } + + return request; + +} + +- (MLNInternalNetworkResponse *)didReceiveResponse:(MLNInternalNetworkResponse *)response { + + if ([self.delegate respondsToSelector:@selector(didReceiveResponse:)]) { + + MLNNetworkResponse *tempResponse = [MLNNetworkResponse responseWithData:response.data + urlResponse:response.response + error:response.error]; + if (tempResponse) { + MLNInternalNetworkResponse *internalResponse = [MLNInternalNetworkResponse responseWithData:tempResponse.data + urlResponse:tempResponse.response + error:tempResponse.error]; + return internalResponse; + } else { + return nil; + } + + } + + return response; + +} + + - (NSURLSessionConfiguration *)sessionConfiguration { NSURLSessionConfiguration *sessionConfig = nil; @synchronized (self) { diff --git a/platform/darwin/src/MLNNetworkResponse.h b/platform/darwin/src/MLNNetworkResponse.h new file mode 100644 index 000000000000..0b862ca40a6b --- /dev/null +++ b/platform/darwin/src/MLNNetworkResponse.h @@ -0,0 +1,24 @@ +// +// MLNNetworkResponse.h +// App +// +// Created by Malcolm Toon on 9/22/25. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MLNNetworkResponse : NSObject + +@property (retain, nullable) NSError *error; +@property (retain, nullable) NSData *data; +@property (retain, nullable) NSURLResponse *response; + ++ (MLNNetworkResponse *)responseWithData:(NSData *)data + urlResponse:(NSURLResponse *)response + error:(NSError *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MLNNetworkResponse.mm b/platform/darwin/src/MLNNetworkResponse.mm new file mode 100644 index 000000000000..4588910b9d21 --- /dev/null +++ b/platform/darwin/src/MLNNetworkResponse.mm @@ -0,0 +1,25 @@ +// +// MLNNetworkResponse.m +// App +// +// Created by Malcolm Toon on 9/22/25. +// + +#import +#import "MLNNetworkResponse.h" + +@implementation MLNNetworkResponse + ++(MLNNetworkResponse *)responseWithData:(NSData *)data + urlResponse:(NSURLResponse *)response + error:(NSError *)error { + + MLNNetworkResponse *tempResult = [[MLNNetworkResponse alloc] init]; + tempResult.data = data; + tempResult.response = response; + tempResult.error = error; + return tempResult; +} + +@end + From 321a959f0a16f0ce3d1e80b0dbb8f833ccf3c914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Tue, 23 Sep 2025 12:42:58 -0400 Subject: [PATCH 191/221] Fix for export issue --- platform/darwin/src/MLNNetworkResponse.h | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/darwin/src/MLNNetworkResponse.h b/platform/darwin/src/MLNNetworkResponse.h index 0b862ca40a6b..d99fa0a78e3e 100644 --- a/platform/darwin/src/MLNNetworkResponse.h +++ b/platform/darwin/src/MLNNetworkResponse.h @@ -9,6 +9,7 @@ NS_ASSUME_NONNULL_BEGIN +MLN_EXPORT @interface MLNNetworkResponse : NSObject @property (retain, nullable) NSError *error; From 35a0b0c726af2be1e1e8df046e6c3305c3be27d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Tue, 23 Sep 2025 12:45:48 -0400 Subject: [PATCH 192/221] Added MLNFoundation --- platform/darwin/src/MLNNetworkResponse.h | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/darwin/src/MLNNetworkResponse.h b/platform/darwin/src/MLNNetworkResponse.h index d99fa0a78e3e..d14c429c8b1d 100644 --- a/platform/darwin/src/MLNNetworkResponse.h +++ b/platform/darwin/src/MLNNetworkResponse.h @@ -6,6 +6,7 @@ // #import +#import "MLNFoundation.h" NS_ASSUME_NONNULL_BEGIN From 00a7eeae0c055c335eb79433ab135a4bfc84ad4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Tue, 23 Sep 2025 13:20:22 -0400 Subject: [PATCH 193/221] Incremented the build version --- platform/ios/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/VERSION b/platform/ios/VERSION index 9e3638056b22..eca90f7138dd 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.18.4 +6.18.5 From fbc21e9ea8151d1be572c89c07bf9d144a2f42d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Tue, 23 Sep 2025 22:51:05 -0400 Subject: [PATCH 194/221] Make the call to the delegate --- platform/darwin/src/MLNNetworkConfiguration.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/darwin/src/MLNNetworkConfiguration.mm b/platform/darwin/src/MLNNetworkConfiguration.mm index 711402179cb7..04f247615386 100644 --- a/platform/darwin/src/MLNNetworkConfiguration.mm +++ b/platform/darwin/src/MLNNetworkConfiguration.mm @@ -104,6 +104,7 @@ - (MLNInternalNetworkResponse *)didReceiveResponse:(MLNInternalNetworkResponse * MLNNetworkResponse *tempResponse = [MLNNetworkResponse responseWithData:response.data urlResponse:response.response error:response.error]; + tempResponse = [self.delegate didReceiveResponse:tempResponse]; if (tempResponse) { MLNInternalNetworkResponse *internalResponse = [MLNInternalNetworkResponse responseWithData:tempResponse.data urlResponse:tempResponse.response From cb1c34dd609f1c5b05112835a10be111300cbb07 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Sun, 5 Oct 2025 12:05:24 +0300 Subject: [PATCH 195/221] check if map is destroyed before calling toggleTransform and setFrustumOffset --- .../main/java/org/maplibre/android/maps/NativeMapView.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java index 45e855a42197..0394b0ac6729 100755 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java @@ -1151,11 +1151,17 @@ public void enableRenderingStatsView(boolean value) { @Override public void toggleTransform() { + if (checkState("toggleTransform")) { + return; + } nativeToggleTransform(); } @Override public void setFrustumOffset(RectF offset) { + if (checkState("setFrustumOffset")) { + return; + } nativeSetFrustumOffset(offset); } From 31b7143ed88def133a794585f2e9e5174afc7f31 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Sun, 5 Oct 2025 12:05:42 +0300 Subject: [PATCH 196/221] make new android release --- platform/android/CHANGELOG.md | 6 ++++++ platform/android/VERSION | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index 2a22ebf83274..9b77192b1a69 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog MapLibre Native for Android +## 11.13.4 + +### 🐞 Bug fixes + +- Avoid crashing when calling `toggleTransform` and `setFrustumOffset` if the map is destroyed. + ## 11.13.3 ### ✨ Features and improvements diff --git a/platform/android/VERSION b/platform/android/VERSION index 32f0b5a51eba..ceba548de1b0 100644 --- a/platform/android/VERSION +++ b/platform/android/VERSION @@ -1 +1 @@ -11.13.3 +11.13.4 From b40973520d7ee7b14bfc1f514c2742b5ebefcbd0 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Sun, 5 Oct 2025 12:23:26 +0300 Subject: [PATCH 197/221] fix format issues --- .../darwin/include/mbgl/interface/native_apple_interface.h | 4 ++-- platform/darwin/src/MLNNetworkConfiguration.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/platform/darwin/include/mbgl/interface/native_apple_interface.h b/platform/darwin/include/mbgl/interface/native_apple_interface.h index fc87b5198946..1118da1e3f67 100644 --- a/platform/darwin/include/mbgl/interface/native_apple_interface.h +++ b/platform/darwin/include/mbgl/interface/native_apple_interface.h @@ -11,8 +11,8 @@ NS_ASSUME_NONNULL_BEGIN @property (retain, nullable) NSURLResponse *response; + (MLNInternalNetworkResponse *)responseWithData:(NSData *)data - urlResponse:(NSURLResponse *)response - error:(NSError *)error; + urlResponse:(NSURLResponse *)response + error:(NSError *)error; @end diff --git a/platform/darwin/src/MLNNetworkConfiguration.h b/platform/darwin/src/MLNNetworkConfiguration.h index 7b1ba3ead71e..19fc298e22b4 100644 --- a/platform/darwin/src/MLNNetworkConfiguration.h +++ b/platform/darwin/src/MLNNetworkConfiguration.h @@ -30,7 +30,6 @@ NS_ASSUME_NONNULL_BEGIN - (MLNNetworkResponse *)didReceiveResponse:(MLNNetworkResponse *)response; - @end /** From 0a32e96318b4fb16bb982c78cdc0799e4f5dcedf Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Mon, 13 Oct 2025 15:17:20 +0300 Subject: [PATCH 198/221] fix CI after latest maplibre changes --- .github/workflows/core-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/core-release.yml b/.github/workflows/core-release.yml index 4d0e9a759f85..2303ef1fbe26 100644 --- a/.github/workflows/core-release.yml +++ b/.github/workflows/core-release.yml @@ -27,7 +27,7 @@ jobs: vendor/maplibre-native-base/deps/geometry.hpp/include \ vendor/maplibre-native-base/deps/geojson.hpp/include \ vendor/metal-cpp \ - vendor/maplibre-native-base/extras/expected-lite/include + vendor/expected-lite/include - name: Create Release if: github.event_name == 'workflow_dispatch' From af8b2ad2b793c768397ea2d2370079f81db2a7b3 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Tue, 14 Oct 2025 13:07:31 +0300 Subject: [PATCH 199/221] fix android CI release workflow --- .github/workflows/android-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android-ci.yml b/.github/workflows/android-ci.yml index a0ca64422262..31e95ad36f6c 100644 --- a/.github/workflows/android-ci.yml +++ b/.github/workflows/android-ci.yml @@ -318,7 +318,7 @@ jobs: runs-on: ubuntu-latest permissions: actions: write - contents: read + contents: write if: needs.pre_job.outputs.should_skip != 'true' && always() needs: - pre_job From 7447ceb4ab30e78eceb8becb3ddea46b4f9ce669 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Tue, 14 Oct 2025 23:58:00 -0400 Subject: [PATCH 200/221] Updated submodels --- vendor/maplibre-native-base/deps/supercluster.hpp | 1 + vendor/maplibre-native-base/extras/args | 1 + vendor/maplibre-native-base/extras/expected-lite | 1 + vendor/maplibre-native-base/extras/filesystem | 1 + vendor/maplibre-native-base/extras/kdbush.hpp | 1 + vendor/maplibre-native-base/extras/rapidjson | 1 + 6 files changed, 6 insertions(+) create mode 160000 vendor/maplibre-native-base/deps/supercluster.hpp create mode 160000 vendor/maplibre-native-base/extras/args create mode 160000 vendor/maplibre-native-base/extras/expected-lite create mode 160000 vendor/maplibre-native-base/extras/filesystem create mode 160000 vendor/maplibre-native-base/extras/kdbush.hpp create mode 160000 vendor/maplibre-native-base/extras/rapidjson diff --git a/vendor/maplibre-native-base/deps/supercluster.hpp b/vendor/maplibre-native-base/deps/supercluster.hpp new file mode 160000 index 000000000000..e5ba492754f8 --- /dev/null +++ b/vendor/maplibre-native-base/deps/supercluster.hpp @@ -0,0 +1 @@ +Subproject commit e5ba492754f865b475577fd85eecc3be70e050ce diff --git a/vendor/maplibre-native-base/extras/args b/vendor/maplibre-native-base/extras/args new file mode 160000 index 000000000000..016aa8a054dd --- /dev/null +++ b/vendor/maplibre-native-base/extras/args @@ -0,0 +1 @@ +Subproject commit 016aa8a054dd88b8e1d2a020466ce38f310444cc diff --git a/vendor/maplibre-native-base/extras/expected-lite b/vendor/maplibre-native-base/extras/expected-lite new file mode 160000 index 000000000000..95b9cb015fa1 --- /dev/null +++ b/vendor/maplibre-native-base/extras/expected-lite @@ -0,0 +1 @@ +Subproject commit 95b9cb015fa17baa749c2b396b335906e1596a9e diff --git a/vendor/maplibre-native-base/extras/filesystem b/vendor/maplibre-native-base/extras/filesystem new file mode 160000 index 000000000000..9fda7b0afbd0 --- /dev/null +++ b/vendor/maplibre-native-base/extras/filesystem @@ -0,0 +1 @@ +Subproject commit 9fda7b0afbd0640f482f4aea8720a8c0afd18740 diff --git a/vendor/maplibre-native-base/extras/kdbush.hpp b/vendor/maplibre-native-base/extras/kdbush.hpp new file mode 160000 index 000000000000..e1e847bfe97c --- /dev/null +++ b/vendor/maplibre-native-base/extras/kdbush.hpp @@ -0,0 +1 @@ +Subproject commit e1e847bfe97c8cdc09edbe87a4e74babc512d18d diff --git a/vendor/maplibre-native-base/extras/rapidjson b/vendor/maplibre-native-base/extras/rapidjson new file mode 160000 index 000000000000..27c3a8dc0e2c --- /dev/null +++ b/vendor/maplibre-native-base/extras/rapidjson @@ -0,0 +1 @@ +Subproject commit 27c3a8dc0e2c9218fe94986d249a12b5ed838f1d From e7c6842c78a05f7b98948496d6b90bd0add2f23d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Thu, 23 Oct 2025 01:56:23 -0400 Subject: [PATCH 201/221] Updates --- platform/darwin/src/MLNPluginStyleLayer.h | 9 ++++ platform/darwin/src/MLNPluginStyleLayer.mm | 54 +++++++++++++++++++++- platform/ios/app/MBXViewController.mm | 20 ++++++++ platform/ios/src/MLNMapView.mm | 3 ++ 4 files changed, 84 insertions(+), 2 deletions(-) diff --git a/platform/darwin/src/MLNPluginStyleLayer.h b/platform/darwin/src/MLNPluginStyleLayer.h index eaf7d86521b3..09accbf0a1f6 100644 --- a/platform/darwin/src/MLNPluginStyleLayer.h +++ b/platform/darwin/src/MLNPluginStyleLayer.h @@ -4,10 +4,19 @@ NS_ASSUME_NONNULL_BEGIN @class MLNPluginLayer; +MLN_EXPORT @interface MLNPluginStyleLayer : MLNStyleLayer - (MLNPluginLayer *)pluginLayer; +- (instancetype)initWithType:(NSString *)layerType + layerIdentifier:(NSString *)identifier + layerPropeties:(NSDictionary *)layerPropeties; + +- (void)setPluginProperty:(NSString *)propertyName + value:(id)propertyValue; + + @end NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MLNPluginStyleLayer.mm b/platform/darwin/src/MLNPluginStyleLayer.mm index c8dc037789c3..3c202e0d2517 100644 --- a/platform/darwin/src/MLNPluginStyleLayer.mm +++ b/platform/darwin/src/MLNPluginStyleLayer.mm @@ -1,11 +1,51 @@ #import "MLNPluginStyleLayer.h" #import "MLNPluginStyleLayer_Private.h" -#import -#import +#import "MLNStyleLayerManager.h" +#include +#include +#include +#include + #import "MLNPluginLayer.h" @implementation MLNPluginStyleLayer +- (instancetype)initWithType:(NSString *)layerType + layerIdentifier:(NSString *)identifier + layerPropeties:(NSDictionary *)layerPropeties { + + // Setup the same property paradigm that would be coming in the style + // This at a minimum creates a dictionary that has id and type + + NSMutableDictionary *layerPropertiesAggregated = [NSMutableDictionary dictionary]; + if (layerPropeties) { + [layerPropertiesAggregated addEntriesFromDictionary:layerPropeties]; + } + [layerPropertiesAggregated setObject:identifier forKey:@"id"]; + [layerPropertiesAggregated setObject:layerType forKey:@"type"]; + + mbgl::style::conversion::Error e; + auto propertiesValue = mbgl::style::makeConvertible(layerPropertiesAggregated); + + // Create the layer using the same convert method that's used by the style loading + std::optional> converted = mbgl::style::conversion::convert>(propertiesValue, e); + if (!converted) { + return nil; + } + auto layer = std::move(*converted); + + if (layer == nullptr) { + return nil; + } + + self = [super initWithPendingLayer:std::move(layer)]; + + return self; + +} + + + -(void)getStats { mbgl::style::PluginLayer *l = (mbgl::style::PluginLayer *)self.rawLayer; @@ -25,6 +65,16 @@ -(MLNPluginLayer *)pluginLayer { } +- (void)setPluginProperty:(NSString *)propertyName + value:(id)propertyValue { + + MLNPluginLayer *layer = [self pluginLayer]; + NSDictionary *updatedProperties = @{propertyName: propertyValue}; + [layer onUpdateLayerProperties:updatedProperties]; + +} + + @end diff --git a/platform/ios/app/MBXViewController.mm b/platform/ios/app/MBXViewController.mm index 835f17bac5fe..f179dda8205f 100644 --- a/platform/ios/app/MBXViewController.mm +++ b/platform/ios/app/MBXViewController.mm @@ -362,6 +362,26 @@ - (void)viewDidLoad } } }]; + /* This is just a test of adding a plugin at runtime via style layer + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self createPluginStyleLayer]; + }); + */ + +} + +-(void)createPluginStyleLayer { + + MLNPluginStyleLayer *layer = [[MLNPluginStyleLayer alloc] initWithType:@"maplibre::filter_features" + layerIdentifier:@"centroid-features" + layerPropeties:@{ + @"source": @"maplibre", + @"source-layer": @"countries", + @"maxzoom": @(24), + @"minzoom": @(1) + }]; + [self.mapView.style addLayer:layer]; + } - (UIInterfaceOrientationMask)supportedInterfaceOrientations diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 01a7206f5682..d6eb5688fecb 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -642,6 +642,9 @@ - (nonnull NSURL *)styleURL - (void)setStyleURL:(nullable NSURL *)styleURL { + // Remove all the plugin layers + [self.pluginLayers removeAllObjects]; + if ( ! styleURL) { styleURL = [MLNStyle defaultStyleURL]; From 42bbb66b8e17fab1f3a0fab62932e0f61e0affcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Thu, 23 Oct 2025 11:31:36 -0400 Subject: [PATCH 202/221] update --- vendor/maplibre-native-base/deps/supercluster.hpp | 1 - vendor/maplibre-native-base/extras/args | 1 - vendor/maplibre-native-base/extras/expected-lite | 1 - vendor/maplibre-native-base/extras/filesystem | 1 - vendor/maplibre-native-base/extras/kdbush.hpp | 1 - vendor/maplibre-native-base/extras/rapidjson | 1 - 6 files changed, 6 deletions(-) delete mode 160000 vendor/maplibre-native-base/deps/supercluster.hpp delete mode 160000 vendor/maplibre-native-base/extras/args delete mode 160000 vendor/maplibre-native-base/extras/expected-lite delete mode 160000 vendor/maplibre-native-base/extras/filesystem delete mode 160000 vendor/maplibre-native-base/extras/kdbush.hpp delete mode 160000 vendor/maplibre-native-base/extras/rapidjson diff --git a/vendor/maplibre-native-base/deps/supercluster.hpp b/vendor/maplibre-native-base/deps/supercluster.hpp deleted file mode 160000 index e5ba492754f8..000000000000 --- a/vendor/maplibre-native-base/deps/supercluster.hpp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e5ba492754f865b475577fd85eecc3be70e050ce diff --git a/vendor/maplibre-native-base/extras/args b/vendor/maplibre-native-base/extras/args deleted file mode 160000 index 016aa8a054dd..000000000000 --- a/vendor/maplibre-native-base/extras/args +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 016aa8a054dd88b8e1d2a020466ce38f310444cc diff --git a/vendor/maplibre-native-base/extras/expected-lite b/vendor/maplibre-native-base/extras/expected-lite deleted file mode 160000 index 95b9cb015fa1..000000000000 --- a/vendor/maplibre-native-base/extras/expected-lite +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 95b9cb015fa17baa749c2b396b335906e1596a9e diff --git a/vendor/maplibre-native-base/extras/filesystem b/vendor/maplibre-native-base/extras/filesystem deleted file mode 160000 index 9fda7b0afbd0..000000000000 --- a/vendor/maplibre-native-base/extras/filesystem +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9fda7b0afbd0640f482f4aea8720a8c0afd18740 diff --git a/vendor/maplibre-native-base/extras/kdbush.hpp b/vendor/maplibre-native-base/extras/kdbush.hpp deleted file mode 160000 index e1e847bfe97c..000000000000 --- a/vendor/maplibre-native-base/extras/kdbush.hpp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e1e847bfe97c8cdc09edbe87a4e74babc512d18d diff --git a/vendor/maplibre-native-base/extras/rapidjson b/vendor/maplibre-native-base/extras/rapidjson deleted file mode 160000 index 27c3a8dc0e2c..000000000000 --- a/vendor/maplibre-native-base/extras/rapidjson +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 27c3a8dc0e2c9218fe94986d249a12b5ed838f1d From aff1b89ea5bd50c31e95177cac00c7aa294ca03c Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Sun, 2 Nov 2025 13:59:40 +0300 Subject: [PATCH 203/221] fix ios ci release flow and avoid immutable releases --- .github/workflows/ios-ci.yml | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ios-ci.yml b/.github/workflows/ios-ci.yml index 739f3d6b8192..7fe7e873c2c5 100644 --- a/.github/workflows/ios-ci.yml +++ b/.github/workflows/ios-ci.yml @@ -316,7 +316,7 @@ jobs: zip MapLibre.dynamic.xcframework.zip LICENSE.md # add license to zip working-directory: . - - name: Release (GitHub) - Create Draft + - name: Release (GitHub) if: env.make_release id: github_release uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3 @@ -329,7 +329,7 @@ jobs: prerelease: ${{ github.event.inputs.release == 'pre' }} body_path: platform/ios/changelog_for_version.md fail_on_unmatched_files: true - draft: true + # draft: true # needed to trigger workflow for Swift Package Index release # - name: Generate token @@ -355,8 +355,8 @@ jobs: "version":"${{ env.version }}", "download_url":"${{ fromJSON(steps.github_release.outputs.assets)[0].browser_download_url }}"}}' - - run: npm install - working-directory: . + # - run: npm install + # working-directory: . # - name: Release (CocoaPods) # shell: bash -leo pipefail {0} # so pod is found @@ -365,20 +365,20 @@ jobs: # env: # GH_TOKEN: ${{ secrets.MAPLIBRE_NATIVE_PRIVATE_TOKEN }} - - name: Publish release (remove draft) - if: env.make_release - uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3 - with: - tag_name: ios-v${{ env.version }} - name: ios-v${{ env.version }} - draft: false + # - name: Publish release (remove draft) + # if: env.make_release + # uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3 + # with: + # tag_name: ios-v${{ env.version }} + # name: ios-v${{ env.version }} + # draft: false - - name: Write release notifications - if: env.make_release && github.repository_owner == 'maplibre' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: node .github/scripts/notify-release-on-prs.ts --tag ios-v${{ env.version }} - working-directory: . + # - name: Write release notifications + # if: env.make_release && github.repository_owner == 'maplibre' + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # run: node .github/scripts/notify-release-on-prs.ts --tag ios-v${{ env.version }} + # working-directory: . ios-build-cmake: needs: pre_job From 113caeb5150ae96947aebe05eb62dc4622123e6b Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Sun, 2 Nov 2025 17:19:02 +0300 Subject: [PATCH 204/221] fix webgpu symbol rendering shader --- include/mbgl/shaders/webgpu/symbol.hpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/include/mbgl/shaders/webgpu/symbol.hpp b/include/mbgl/shaders/webgpu/symbol.hpp index 557f22b6634f..fb0b3a9b0480 100644 --- a/include/mbgl/shaders/webgpu/symbol.hpp +++ b/include/mbgl/shaders/webgpu/symbol.hpp @@ -41,6 +41,7 @@ struct SymbolDrawableUBO { pitch_with_map: u32, is_size_zoom_constant: u32, is_size_feature_constant: u32, + is_offset: u32, size_t: f32, size: f32, @@ -175,7 +176,9 @@ fn main(in: VertexInput) -> VertexOutput { ); let perspective_ratio = clamp(0.5 + 0.5 * distance_ratio, 0.0, 4.0); - size *= perspective_ratio; + if (drawable.is_offset == 0u) { + size *= perspective_ratio; + } let is_text = drawable.is_text_prop != 0u; let fontScale = select(size, size / 24.0, is_text); @@ -348,7 +351,9 @@ fn main(in: VertexInput) -> VertexOutput { ); let perspective_ratio = clamp(0.5 + 0.5 * distance_ratio, 0.0, 4.0); - size *= perspective_ratio; + if (drawable.is_offset == 0u) { + size *= perspective_ratio; + } let is_text = drawable.is_text_prop != 0u; let fontScale = select(size, size / 24.0, is_text); @@ -597,7 +602,9 @@ fn main(in: VertexInput) -> VertexOutput { ); let perspective_ratio = clamp(0.5 + 0.5 * distance_ratio, 0.0, 4.0); - size *= perspective_ratio; + if (drawable.is_offset == 0u) { + size *= perspective_ratio; + } let fontScale = size / 24.0; From afae5655193beed0b086bc8a29637270bd537f20 Mon Sep 17 00:00:00 2001 From: Ahmed El-Helw Date: Fri, 31 Oct 2025 16:58:03 +0400 Subject: [PATCH 205/221] Add a listener that watches the puck position In order to do things like path eating precisely, the exact position of the puck needs to be known. --- .../android/location/LocationComponent.java | 58 +++++++++++++++++-- .../location/LocationLayerController.java | 31 +++++----- .../OnPuckPositionChangeListener.java | 17 ++++++ 3 files changed, 86 insertions(+), 20 deletions(-) create mode 100644 platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/location/OnPuckPositionChangeListener.java diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/location/LocationComponent.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/location/LocationComponent.java index 72d146e95f5c..c5ad38eb0716 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/location/LocationComponent.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/location/LocationComponent.java @@ -23,16 +23,16 @@ import org.maplibre.android.location.engine.LocationEngineDefault; import org.maplibre.android.location.engine.LocationEngineRequest; import org.maplibre.android.location.engine.LocationEngineResult; +import org.maplibre.android.location.engine.MapLibreFusedLocationEngineImpl; import org.maplibre.android.location.modes.CameraMode; import org.maplibre.android.location.modes.RenderMode; -import org.maplibre.android.location.engine.MapLibreFusedLocationEngineImpl; import org.maplibre.android.location.permissions.PermissionsManager; import org.maplibre.android.log.Logger; -import org.maplibre.android.maps.MapView; import org.maplibre.android.maps.MapLibreMap; import org.maplibre.android.maps.MapLibreMap.OnCameraIdleListener; import org.maplibre.android.maps.MapLibreMap.OnCameraMoveListener; import org.maplibre.android.maps.MapLibreMap.OnMapClickListener; +import org.maplibre.android.maps.MapView; import org.maplibre.android.maps.Style; import org.maplibre.android.maps.Transform; import org.maplibre.android.style.layers.SymbolLayer; @@ -53,7 +53,6 @@ import static org.maplibre.android.location.LocationComponentConstants.TRANSITION_ANIMATION_DURATION_MS; import static org.maplibre.android.location.modes.RenderMode.GPS; - /** * The Location Component provides location awareness to your mobile application. Enabling this * component provides a contextual experience to your users by showing an icon representing the users @@ -178,6 +177,8 @@ public final class LocationComponent { = new CopyOnWriteArrayList<>(); private final CopyOnWriteArrayList onLocationLongClickListeners = new CopyOnWriteArrayList<>(); + private final CopyOnWriteArrayList onPuckPositionChangeListeners + = new CopyOnWriteArrayList<>(); private final CopyOnWriteArrayList onCameraTrackingChangedListeners = new CopyOnWriteArrayList<>(); private final CopyOnWriteArrayList onRenderModeChangedListeners @@ -990,6 +991,24 @@ public void removeOnLocationLongClickListener(@NonNull OnLocationLongClickListen onLocationLongClickListeners.remove(listener); } + /** + * Adds a listener that receives updates whenever the rendered puck position changes. + * + * @param listener listener that will be invoked on puck position changes + */ + public void addOnPuckPositionChangeListener(@NonNull OnPuckPositionChangeListener listener) { + onPuckPositionChangeListeners.add(listener); + } + + /** + * Removes a listener that was receiving puck position updates. + * + * @param listener listener to remove + */ + public void removeOnPuckPositionChangeListener(@NonNull OnPuckPositionChangeListener listener) { + onPuckPositionChangeListeners.remove(listener); + } + /** * Adds a listener that gets invoked when camera tracking state changes. * @@ -1298,6 +1317,12 @@ private void updateLocation(@Nullable final Location location, @Nullable List intermediatePoints) { Location[] locations = new Location[intermediatePoints.size() + 1]; locations[locations.length - 1] = location; @@ -1379,7 +1404,13 @@ private void updateAccuracyRadius(Location location, boolean noAnimation) { private void updateAnimatorListenerHolders() { Set animationsValueChangeListeners = new HashSet<>(); - animationsValueChangeListeners.addAll(locationLayerController.getAnimationListeners()); + for (AnimatorListenerHolder holder : locationLayerController.getAnimationListeners()) { + if (holder.getAnimatorType() == MapLibreAnimator.ANIMATOR_LAYER_LATLNG) { + animationsValueChangeListeners.add(wrapPuckPositionListener(holder)); + } else { + animationsValueChangeListeners.add(holder); + } + } animationsValueChangeListeners.addAll(locationCameraController.getAnimationListeners()); locationAnimatorCoordinator.updateAnimatorListenerHolders(animationsValueChangeListeners); locationAnimatorCoordinator.resetAllCameraAnimations(maplibreMap.getCameraPosition(), @@ -1387,6 +1418,25 @@ private void updateAnimatorListenerHolders() { locationAnimatorCoordinator.resetAllLayerAnimations(); } + @SuppressWarnings("unchecked") + private AnimatorListenerHolder wrapPuckPositionListener(AnimatorListenerHolder originalHolder) { + // Forward animator ticks to both the renderer and public puck listeners. + final MapLibreAnimator.AnimationsValueChangeListener originalListener = + (MapLibreAnimator.AnimationsValueChangeListener) originalHolder.getListener(); + if (originalListener == null) { + return originalHolder; + } + MapLibreAnimator.AnimationsValueChangeListener compositeListener = + new MapLibreAnimator.AnimationsValueChangeListener() { + @Override + public void onNewAnimationValue(LatLng value) { + originalListener.onNewAnimationValue(value); + notifyPuckPositionChange(value); + } + }; + return new AnimatorListenerHolder(MapLibreAnimator.ANIMATOR_LAYER_LATLNG, compositeListener); + } + @NonNull private OnCameraMoveListener onCameraMoveListener = new OnCameraMoveListener() { @Override diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/location/LocationLayerController.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/location/LocationLayerController.java index a1039c12e652..9459d3ef2de1 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/location/LocationLayerController.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/location/LocationLayerController.java @@ -1,37 +1,36 @@ package org.maplibre.android.location; +import static org.maplibre.android.location.LocationComponentConstants.BACKGROUND_ICON; +import static org.maplibre.android.location.LocationComponentConstants.BACKGROUND_LAYER; +import static org.maplibre.android.location.LocationComponentConstants.BACKGROUND_STALE_ICON; +import static org.maplibre.android.location.LocationComponentConstants.BEARING_ICON; +import static org.maplibre.android.location.LocationComponentConstants.BEARING_LAYER; +import static org.maplibre.android.location.LocationComponentConstants.FOREGROUND_ICON; +import static org.maplibre.android.location.LocationComponentConstants.FOREGROUND_LAYER; +import static org.maplibre.android.location.LocationComponentConstants.FOREGROUND_STALE_ICON; +import static org.maplibre.android.style.expressions.Expression.interpolate; +import static org.maplibre.android.style.expressions.Expression.linear; +import static org.maplibre.android.style.expressions.Expression.stop; +import static org.maplibre.android.style.expressions.Expression.zoom; + import android.graphics.Bitmap; import android.graphics.PointF; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import org.maplibre.geojson.Feature; +import org.maplibre.android.geometry.LatLng; import org.maplibre.android.location.modes.RenderMode; import org.maplibre.android.log.Logger; import org.maplibre.android.maps.MapLibreMap; import org.maplibre.android.maps.Style; import org.maplibre.android.style.expressions.Expression; +import org.maplibre.geojson.Feature; import java.util.HashSet; import java.util.List; import java.util.Set; -import static org.maplibre.android.location.LocationComponentConstants.BACKGROUND_ICON; -import static org.maplibre.android.location.LocationComponentConstants.BACKGROUND_LAYER; -import static org.maplibre.android.location.LocationComponentConstants.BACKGROUND_STALE_ICON; -import static org.maplibre.android.location.LocationComponentConstants.BEARING_ICON; -import static org.maplibre.android.location.LocationComponentConstants.BEARING_LAYER; -import static org.maplibre.android.location.LocationComponentConstants.FOREGROUND_ICON; -import static org.maplibre.android.location.LocationComponentConstants.FOREGROUND_LAYER; -import static org.maplibre.android.location.LocationComponentConstants.FOREGROUND_STALE_ICON; -import static org.maplibre.android.style.expressions.Expression.interpolate; -import static org.maplibre.android.style.expressions.Expression.linear; -import static org.maplibre.android.style.expressions.Expression.stop; -import static org.maplibre.android.style.expressions.Expression.zoom; - -import org.maplibre.android.geometry.LatLng; - final class LocationLayerController { private static final String TAG = "Mbgl-LocationLayerController"; diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/location/OnPuckPositionChangeListener.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/location/OnPuckPositionChangeListener.java new file mode 100644 index 000000000000..e25cc57aa563 --- /dev/null +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/location/OnPuckPositionChangeListener.java @@ -0,0 +1,17 @@ +package org.maplibre.android.location; + +import androidx.annotation.NonNull; + +import org.maplibre.android.geometry.LatLng; + +/** + * Listener invoked whenever the rendered puck position changes. + */ +public interface OnPuckPositionChangeListener { + /** + * Called when the puck position is updated as part of the location animation. + * + * @param puckPosition current rendered puck position. + */ + void onPuckPositionChanged(@NonNull LatLng puckPosition); +} From 10065e57e60f91f50bcf834e688f75e698991cd7 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 6 Nov 2025 09:36:56 +0300 Subject: [PATCH 206/221] make new android release --- platform/android/CHANGELOG.md | 6 ++++++ platform/android/VERSION | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index 66610313679b..959e42085a73 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog MapLibre Native for Android +## 12.0.2 + +### ✨ Features and improvements + +- Add listener to location update events from maplibre to the user + ## 12.0.1 ### ✨ Features and improvements diff --git a/platform/android/VERSION b/platform/android/VERSION index b700dc1d471e..f36e00abc867 100644 --- a/platform/android/VERSION +++ b/platform/android/VERSION @@ -1 +1 @@ -12.0.1 +12.0.2 From b423c1079054e26dd16a8f7b091e0c20f00b7f8d Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 6 Nov 2025 13:34:44 +0300 Subject: [PATCH 207/221] test building android for release --- .github/workflows/android-ci.yml | 480 +++++++++---------------------- 1 file changed, 142 insertions(+), 338 deletions(-) diff --git a/.github/workflows/android-ci.yml b/.github/workflows/android-ci.yml index 31e95ad36f6c..42bf344a9963 100644 --- a/.github/workflows/android-ci.yml +++ b/.github/workflows/android-ci.yml @@ -1,368 +1,172 @@ -name: android-ci - -permissions: - id-token: write # needed for AWS - contents: write - actions: write +name: android-release on: - push: - branches: - - main - - android-*.*.x - tags: - - "android-*" - + workflow_dispatch: pull_request: branches: - - "*" - + - '*' + push: + branches: + - 'fix_android_release_ci_storage' -concurrency: - # cancel jobs on PRs only - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} +permissions: + contents: write jobs: - pre_job: - runs-on: ubuntu-latest - outputs: - should_skip: ${{ github.event_name != 'workflow_dispatch' && steps.changed-files.outputs.android_any_modified != 'true' }} - steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v4 - with: - submodules: recursive - persist-credentials: false - - - name: Get all Android files that have changed - if: github.event_name != 'workflow_dispatch' - id: changed-files - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 - with: - files_yaml_from_source_file: .github/changed-files.yml - - android-build: + # android-create-release: + # runs-on: ubuntu-24.04 + # outputs: + # version_tag: ${{ steps.prepare_release.outputs.version_tag }} + # defaults: + # run: + # working-directory: platform/android + # steps: + # - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v4 + + # - name: Validate and set version + # working-directory: . + # run: .github/scripts/validate-version.sh platform/android/VERSION + + # - name: npm install + # run: npm install --ignore-scripts + + # # create github release + # - name: Prepare release + # id: prepare_release + # run: | + # RELEASE_NOTES_PATH="${PWD}/release_notes.txt" + # node scripts/release-notes.mjs ${{ env.version }} > "${RELEASE_NOTES_PATH}" + # echo release_notes="${RELEASE_NOTES_PATH}" >> "$GITHUB_OUTPUT" + # echo version_tag=android-v${{ env.version }} >> "$GITHUB_OUTPUT" + # shell: bash + + # - name: Check if version is pre-release + # id: check_version + # run: | + # version="${{ env.version }}" + # if [[ $version =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + # echo "Valid semver: $version" + # echo "prerelease=false" >> "$GITHUB_ENV" + # else + # echo "Invalid semver: $version" + # echo "prerelease=true" >> "$GITHUB_ENV" + # fi + + # - name: Create tag if it does not exist + # working-directory: . + # run: .github/scripts/ensure-tag.sh android-v${{ env.version }} ${{ github.sha }} + + # - name: Create release (draft) + # id: create_release + # uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3 + # with: + # tag_name: ${{ steps.prepare_release.outputs.version_tag }} + # name: ${{ steps.prepare_release.outputs.version_tag }} + # body_path: ${{ steps.prepare_release.outputs.release_notes }} + # draft: true + # prerelease: ${{ env.prerelease }} + + android-build-and-upload-release: + # needs: android-create-release runs-on: ubuntu-24.04 - needs: - - pre_job - if: needs.pre_job.outputs.should_skip != 'true' - strategy: - fail-fast: false - matrix: - renderer: [opengl, vulkan] defaults: run: working-directory: platform/android env: - BUILDTYPE: Debug + JOBS: 8 IS_LOCAL_DEVELOPMENT: false - MLN_ANDROID_STL: c++_static - # SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - # SENTRY_DSN: ${{ secrets.SENTRY_DSN_ANDROID }} + strategy: + matrix: + RENDERER: + - vulkan + - opengl + BUILDTYPE: + - Release + - Debug steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v4 with: submodules: recursive - persist-credentials: false - - uses: ./.github/actions/setup-android-ci + - name: Free disk space + working-directory: . + run: .github/scripts/free_disk_space.sh - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v4 with: node-version-file: ".nvmrc" + - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v4 + with: + distribution: "temurin" + java-version: "17" + - name: npm install run: npm install --ignore-scripts - working-directory: . - shell: bash - - - name: run platform/android/scripts/generate-style-code.mjs - run: node platform/android/scripts/generate-style-code.mjs - working-directory: . - shell: bash - - - run: | - python3 -m venv venv - source venv/bin/activate - pip3 install pre-commit - shell: bash - - run: | - source venv/bin/activate - pre-commit run clang-format --all-files - continue-on-error: true # this can mean files are modified, which is not an error - shell: bash + - name: Android nitpick + run: make run-android-nitpick - - run: | - source venv/bin/activate - pre-commit run clang-format --all-files - rm -rf venv - shell: bash + - name: Build package + run: RENDERER=${{ matrix.RENDERER }} BUILDTYPE=${{ matrix.BUILDTYPE }} make apackage - # - if: env.SENTRY_DSN != '' + # - name: Save buildtype to GITHUB_ENV # run: | - # echo "SENTRY_ORG=maplibre" >> "$GITHUB_ENV" - # echo "SENTRY_PROJECT=maplibre-android" >> "$GITHUB_ENV" - - - uses: infotroph/tree-is-clean@69d598a958e8cb8f3d0e3d52b5ebcd8684f2adc2 # v1.0.6 - with: - check_untracked: true - - - name: Configure AWS Credentials - if: vars.OIDC_AWS_ROLE_TO_ASSUME - uses: aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 # v4 - with: - aws-region: us-west-2 - role-to-assume: ${{ vars.OIDC_AWS_ROLE_TO_ASSUME }} - role-session-name: ${{ github.run_id }} - - - name: Configure sccache - run: | - echo SCCACHE_BUCKET=maplibre-native-sccache >> "$GITHUB_ENV" - echo SCCACHE_REGION=eu-central-1 >> "$GITHUB_ENV" - - if [ -z "${AWS_SECRET_ACCESS_KEY}" ]; then - echo "AWS_SECRET_ACCESS_KEY not set; not uploading sccache cache to S3" - echo SCCACHE_S3_NO_CREDENTIALS=1 >> "$GITHUB_ENV" - fi - - - name: Check code style - if: matrix.renderer == 'opengl' - run: make android-check - - - name: Run Android unit tests - run: RENDERER=${{ matrix.renderer }} make run-android-unit-test - - - name: Build libmaplibre.so for arm-v8 - run: RENDERER=${{ matrix.renderer }} make android-lib-arm-v8 - - - name: Build API documentation - if: matrix.renderer == 'opengl' - run: ./gradlew dokkaGenerate - - - name: Build Examples documentation - if: matrix.renderer == 'opengl' - run: make mkdocs-build - - - name: Copy developer config with API key for UI tests - if: github.ref == 'refs/heads/main' - run: | - MAPLIBRE_DEVELOPER_CONFIG_XML='${{ secrets.MAPLIBRE_DEVELOPER_CONFIG_XML }}' - if [ -n "${MAPLIBRE_DEVELOPER_CONFIG_XML}" ]; then - echo "${MAPLIBRE_DEVELOPER_CONFIG_XML}" > MapLibreAndroidTestApp/src/main/res/values/developer-config.xml - else - echo "No secrets.MAPLIBRE_DEVELOPER_CONFIG_XML variable set, not copying..." - fi - - - name: Build Benchmark, copy to platform/android - run: | - ./gradlew assemble${{ matrix.renderer }}Release assemble${{ matrix.renderer }}ReleaseAndroidTest -PtestBuildType=release -Pmaplibre.abis=arm64-v8a - cp MapLibreAndroidTestApp/build/outputs/apk/${{ matrix.renderer }}/release/MapLibreAndroidTestApp-${{ matrix.renderer }}-release.apk . - cp MapLibreAndroidTestApp/build/outputs/apk/androidTest/${{ matrix.renderer }}/release/MapLibreAndroidTestApp-${{ matrix.renderer }}-release-androidTest.apk . - - # https://developer.android.com/guide/practices/page-sizes - - name: Check alignment of .apk - run: | - unzip -o MapLibreAndroidTestApp/build/outputs/apk/${{ matrix.renderer }}/release/MapLibreAndroidTestApp-${{ matrix.renderer }}-release.apk -d /tmp/my_apk_out - scripts/check-alignment.sh /tmp/my_apk_out - - - name: Create artifact for benchmark APKs - if: matrix.renderer == 'opengl' - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - if-no-files-found: error - name: benchmarkAPKs - path: | - platform/android/MapLibreAndroidTestApp-${{ matrix.renderer }}-release.apk - platform/android/MapLibreAndroidTestApp-${{ matrix.renderer }}-release-androidTest.apk - - - if: github.event_name == 'pull_request' && matrix.renderer == 'opengl' - uses: ./.github/actions/save-pr-number - - - name: Set renderer env var (OpenGL or Vulkan) - shell: bash - run: | - case "${{ matrix.renderer }}" in - opengl) echo "renderer=OpenGL" >> "$GITHUB_ENV" ;; - vulkan) echo "renderer=Vulkan" >> "$GITHUB_ENV" ;; - *) echo "::error ::Unknown renderer '${{ matrix.renderer }}'"; exit 1 ;; - esac - - - name: Build Instrumentation Tests (${{ matrix.renderer }}), copy to platform/android - run: | - ./gradlew assemble${{ matrix.renderer }}Debug assemble${{ matrix.renderer }}DebugAndroidTest -PtestBuildType=debug -Pmaplibre.abis=arm64-v8a - cp MapLibreAndroidTestApp/build/outputs/apk/${{ matrix.renderer }}/debug/MapLibreAndroidTestApp-${{ matrix.renderer }}-debug.apk InstrumentationTestApp${{ env.renderer }}.apk - cp MapLibreAndroidTestApp/build/outputs/apk/androidTest/${{ matrix.renderer }}/debug/MapLibreAndroidTestApp-${{ matrix.renderer }}-debug-androidTest.apk InstrumentationTests${{ env.renderer }}.apk - - # - name: Install sentry-cli - # if: env.SENTRY_DSN != '' - # run: curl -sL https://sentry.io/get-cli/ | sh - - # - name: Upload debug symbols to sentry - # if: env.SENTRY_DSN != '' - # run: sentry-cli debug-files upload MapLibreAndroidTestApp - - - name: Upload android-ui-test-${{ matrix.renderer }} - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - if-no-files-found: error - name: android-ui-test-${{ matrix.renderer }} - path: | - platform/android/InstrumentationTestApp${{ env.renderer }}.apk - platform/android/InstrumentationTests${{ env.renderer }}.apk + # buildtype=${{ matrix.BUILDTYPE }} + # # lowercase + # echo buildtype=${buildtype,,} > "$GITHUB_ENV" - - name: Show sccache stats - run: sccache --show-stats - - android-build-cpp-test: - runs-on: ubuntu-24.04 - - needs: - - pre_job - if: needs.pre_job.outputs.should_skip != 'true' - - defaults: - run: - working-directory: test/android - - steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v4 - with: - submodules: recursive - persist-credentials: false - - - uses: ./.github/actions/setup-android-ci - - - name: Create data.zip in assets directory - run: zip -r test/android/app/src/main/assets/data.zip -@ < test/android/app/src/main/assets/to_zip.txt - working-directory: . - - - name: Configure AWS Credentials - if: vars.OIDC_AWS_ROLE_TO_ASSUME - uses: aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 # v4 - with: - aws-region: us-west-2 - role-to-assume: ${{ vars.OIDC_AWS_ROLE_TO_ASSUME }} - role-session-name: ${{ github.run_id }} - - - name: Configure sccache - run: | - echo SCCACHE_BUCKET=maplibre-native-sccache >> "$GITHUB_ENV" - echo SCCACHE_REGION=eu-central-1 >> "$GITHUB_ENV" - - if [ -z "${AWS_SECRET_ACCESS_KEY}" ]; then - echo "AWS_SECRET_ACCESS_KEY not set; not uploading sccache cache to S3" - echo SCCACHE_S3_NO_CREDENTIALS=1 >> "$GITHUB_ENV" - fi - - - name: Build C++ Unit Tests App - run: | - ./gradlew assembleDebug assembleAndroidTest -Pmaplibre.abis=arm64-v8a - cp app/build/outputs/apk/debug/app-debug.apk . - cp app/build/outputs/apk/androidTest/release/app-release-androidTest.apk . - - - name: Store C++ Unit Tests .apk files - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: android-cpp-tests - if-no-files-found: error - path: | - ./test/android/app-debug.apk - ./test/android/app-release-androidTest.apk - - android-build-render-test: - strategy: - fail-fast: false - matrix: - flavor: [opengl, vulkan] - - runs-on: ubuntu-24.04 - - needs: - - pre_job - - if: needs.pre_job.outputs.should_skip != 'true' - - steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v4 - with: - submodules: recursive - persist-credentials: false - - - uses: ./.github/actions/setup-android-ci - - - name: Configure AWS Credentials - if: vars.OIDC_AWS_ROLE_TO_ASSUME - uses: aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 # v4 - with: - aws-region: us-west-2 - role-to-assume: ${{ vars.OIDC_AWS_ROLE_TO_ASSUME }} - role-session-name: ${{ github.run_id }} - - - name: Configure sccache - run: | - echo SCCACHE_BUCKET=maplibre-native-sccache >> "$GITHUB_ENV" - echo SCCACHE_REGION=eu-central-1 >> "$GITHUB_ENV" - - if [ -z "${AWS_SECRET_ACCESS_KEY}" ]; then - echo "AWS_SECRET_ACCESS_KEY not set; not uploading sccache cache to S3" - echo SCCACHE_S3_NO_CREDENTIALS=1 >> "$GITHUB_ENV" - fi - - - name: Build and Upload Render Test APKs (${{ matrix.flavor }}) - uses: ./.github/actions/android-build-and-upload-render-test - with: - flavor: ${{ matrix.flavor }} - - android-ci-result: - runs-on: ubuntu-latest - permissions: - actions: write - contents: write - if: needs.pre_job.outputs.should_skip != 'true' && always() - needs: - - pre_job - - android-build - - android-build-cpp-test - - android-build-render-test - steps: - - name: Set success=true - if: needs.android-build.result == 'success' && needs.android-build-cpp-test.result == 'success' && needs.android-build-render-test.result == 'success' - run: echo success=true > "$GITHUB_ENV" - - - name: Mark result as failed - if: env.success != 'true' - run: exit 1 - - # automatically trigger android-release when code is pushed to main - # and the platform/android/VERSION file has changed - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v4 - if: github.ref == 'refs/heads/main' && github.event_name == 'push' - - - name: VERSION file changed - if: github.ref == 'refs/heads/main' && github.event_name == 'push' - id: version-file-android-changed - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 - with: - files: platform/android/VERSION - - - name: Should make release? - if: env.success && github.ref == 'refs/heads/main' && github.event_name == 'push' && steps.version-file-android-changed.outputs.any_changed == 'true' - run: echo make_release=true >> "$GITHUB_ENV" - - - name: Validate and set version - if: env.make_release == 'true' - working-directory: . - run: .github/scripts/validate-version.sh platform/android/VERSION - - - name: Create tag if it does not exist - if: env.make_release == 'true' - run: .github/scripts/ensure-tag.sh android-v${{ env.version }} ${{ github.sha }} - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Trigger release - if: env.make_release == 'true' - run: gh workflow run android-release.yml --ref android-v${{ env.version }} - env: - GH_TOKEN: ${{ github.token }} + # - name: Prepare release asset filenames (include tag) + # run: | + # version_tag='${{ needs.android-create-release.outputs.version_tag }}' + # # AAR + # aar_dir='MapLibreAndroid/build/outputs/aar' + # mv "$aar_dir/MapLibreAndroid-${{ matrix.RENDERER }}-${{ env.buildtype }}.aar" \ + # "$aar_dir/MapLibreAndroid-${{ matrix.RENDERER }}-${{ env.buildtype }}-$version_tag.aar" + # # Debug symbols + # mv "build/debug-symbols-${{ matrix.RENDERER }}-${{ env.buildtype }}.tar.gz" \ + # "build/debug-symbols-maplibre-android-${{ matrix.RENDERER }}-${{ env.buildtype }}-$version_tag.tar.gz" + + # - name: Upload release assets (${{ matrix.RENDERER }}, ${{ matrix.BUILDTYPE }}) + # uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3 + # with: + # tag_name: ${{ needs.android-create-release.outputs.version_tag }} + # fail_on_unmatched_files: true + # draft: true + # files: | + # platform/android/MapLibreAndroid/build/outputs/aar/MapLibreAndroid-${{ matrix.RENDERER }}-${{ env.buildtype }}-${{ needs.android-create-release.outputs.version_tag }}.aar + # platform/android/build/debug-symbols-maplibre-android-${{ matrix.RENDERER }}-${{ env.buildtype }}-${{ needs.android-create-release.outputs.version_tag }}.tar.gz + + # - name: Publish to Github + # env: + # GITHUB_TOKEN: ${{ secrets.MAPLIBRE_NATIVE_PRIVATE_TOKEN }} + # run: | + # renderer=${{ matrix.RENDERER }} + # if [ "$renderer" = "opengl" ]; then + # ./gradlew :MapLibreAndroid:publishDefault${{ env.buildtype }}PublicationToGithubPackagesRepository + # else + # ./gradlew :MapLibreAndroid:publishVulkan${{ env.buildtype }}PublicationToGithubPackagesRepository + # fi + + # finilize-release: + # runs-on: ubuntu-latest + # needs: + # - android-create-release + # - android-build-and-upload-release + # steps: + # - name: Publish release (remove draft) + # uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3 + # with: + # tag_name: ${{ needs.android-create-release.outputs.version_tag }} + # name: ${{ needs.android-create-release.outputs.version_tag }} + # draft: false + + # - run: npm install + # working-directory: . + + # - name: Write release notifications + # if: github.repository_owner == 'maplibre' + # env: + # GITHUB_TOKEN: ${{ secrets.MAPLIBRE_NATIVE_PRIVATE_TOKEN }} + # run: node .github/scripts/notify-release-on-prs.ts --tag ${{ needs.android-create-release.outputs.version_tag }} + # working-directory: . From 35f2d275644be98c6330172cff06106f1c365894 Mon Sep 17 00:00:00 2001 From: Yousif Aldolaijan Date: Thu, 6 Nov 2025 15:19:22 +0300 Subject: [PATCH 208/221] use /mnt with symlinks --- .github/workflows/android-ci.yml | 480 ++++++++++++++++++-------- .github/workflows/android-release.yml | 18 + 2 files changed, 356 insertions(+), 142 deletions(-) diff --git a/.github/workflows/android-ci.yml b/.github/workflows/android-ci.yml index 42bf344a9963..31e95ad36f6c 100644 --- a/.github/workflows/android-ci.yml +++ b/.github/workflows/android-ci.yml @@ -1,172 +1,368 @@ -name: android-release +name: android-ci + +permissions: + id-token: write # needed for AWS + contents: write + actions: write on: - workflow_dispatch: - pull_request: - branches: - - '*' push: branches: - - 'fix_android_release_ci_storage' + - main + - android-*.*.x + tags: + - "android-*" -permissions: - contents: write + pull_request: + branches: + - "*" + + +concurrency: + # cancel jobs on PRs only + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} jobs: - # android-create-release: - # runs-on: ubuntu-24.04 - # outputs: - # version_tag: ${{ steps.prepare_release.outputs.version_tag }} - # defaults: - # run: - # working-directory: platform/android - # steps: - # - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v4 - - # - name: Validate and set version - # working-directory: . - # run: .github/scripts/validate-version.sh platform/android/VERSION - - # - name: npm install - # run: npm install --ignore-scripts - - # # create github release - # - name: Prepare release - # id: prepare_release - # run: | - # RELEASE_NOTES_PATH="${PWD}/release_notes.txt" - # node scripts/release-notes.mjs ${{ env.version }} > "${RELEASE_NOTES_PATH}" - # echo release_notes="${RELEASE_NOTES_PATH}" >> "$GITHUB_OUTPUT" - # echo version_tag=android-v${{ env.version }} >> "$GITHUB_OUTPUT" - # shell: bash - - # - name: Check if version is pre-release - # id: check_version - # run: | - # version="${{ env.version }}" - # if [[ $version =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - # echo "Valid semver: $version" - # echo "prerelease=false" >> "$GITHUB_ENV" - # else - # echo "Invalid semver: $version" - # echo "prerelease=true" >> "$GITHUB_ENV" - # fi - - # - name: Create tag if it does not exist - # working-directory: . - # run: .github/scripts/ensure-tag.sh android-v${{ env.version }} ${{ github.sha }} - - # - name: Create release (draft) - # id: create_release - # uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3 - # with: - # tag_name: ${{ steps.prepare_release.outputs.version_tag }} - # name: ${{ steps.prepare_release.outputs.version_tag }} - # body_path: ${{ steps.prepare_release.outputs.release_notes }} - # draft: true - # prerelease: ${{ env.prerelease }} - - android-build-and-upload-release: - # needs: android-create-release + pre_job: + runs-on: ubuntu-latest + outputs: + should_skip: ${{ github.event_name != 'workflow_dispatch' && steps.changed-files.outputs.android_any_modified != 'true' }} + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v4 + with: + submodules: recursive + persist-credentials: false + + - name: Get all Android files that have changed + if: github.event_name != 'workflow_dispatch' + id: changed-files + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files_yaml_from_source_file: .github/changed-files.yml + + android-build: runs-on: ubuntu-24.04 + needs: + - pre_job + if: needs.pre_job.outputs.should_skip != 'true' + strategy: + fail-fast: false + matrix: + renderer: [opengl, vulkan] defaults: run: working-directory: platform/android env: - JOBS: 8 + BUILDTYPE: Debug IS_LOCAL_DEVELOPMENT: false - strategy: - matrix: - RENDERER: - - vulkan - - opengl - BUILDTYPE: - - Release - - Debug + MLN_ANDROID_STL: c++_static + # SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + # SENTRY_DSN: ${{ secrets.SENTRY_DSN_ANDROID }} steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v4 with: submodules: recursive + persist-credentials: false - - name: Free disk space - working-directory: . - run: .github/scripts/free_disk_space.sh + - uses: ./.github/actions/setup-android-ci - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v4 with: node-version-file: ".nvmrc" - - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v4 - with: - distribution: "temurin" - java-version: "17" - - name: npm install run: npm install --ignore-scripts + working-directory: . + shell: bash - - name: Android nitpick - run: make run-android-nitpick + - name: run platform/android/scripts/generate-style-code.mjs + run: node platform/android/scripts/generate-style-code.mjs + working-directory: . + shell: bash - - name: Build package - run: RENDERER=${{ matrix.RENDERER }} BUILDTYPE=${{ matrix.BUILDTYPE }} make apackage + - run: | + python3 -m venv venv + source venv/bin/activate + pip3 install pre-commit + shell: bash - # - name: Save buildtype to GITHUB_ENV - # run: | - # buildtype=${{ matrix.BUILDTYPE }} - # # lowercase - # echo buildtype=${buildtype,,} > "$GITHUB_ENV" + - run: | + source venv/bin/activate + pre-commit run clang-format --all-files + continue-on-error: true # this can mean files are modified, which is not an error + shell: bash - # - name: Prepare release asset filenames (include tag) - # run: | - # version_tag='${{ needs.android-create-release.outputs.version_tag }}' - # # AAR - # aar_dir='MapLibreAndroid/build/outputs/aar' - # mv "$aar_dir/MapLibreAndroid-${{ matrix.RENDERER }}-${{ env.buildtype }}.aar" \ - # "$aar_dir/MapLibreAndroid-${{ matrix.RENDERER }}-${{ env.buildtype }}-$version_tag.aar" - # # Debug symbols - # mv "build/debug-symbols-${{ matrix.RENDERER }}-${{ env.buildtype }}.tar.gz" \ - # "build/debug-symbols-maplibre-android-${{ matrix.RENDERER }}-${{ env.buildtype }}-$version_tag.tar.gz" - - # - name: Upload release assets (${{ matrix.RENDERER }}, ${{ matrix.BUILDTYPE }}) - # uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3 - # with: - # tag_name: ${{ needs.android-create-release.outputs.version_tag }} - # fail_on_unmatched_files: true - # draft: true - # files: | - # platform/android/MapLibreAndroid/build/outputs/aar/MapLibreAndroid-${{ matrix.RENDERER }}-${{ env.buildtype }}-${{ needs.android-create-release.outputs.version_tag }}.aar - # platform/android/build/debug-symbols-maplibre-android-${{ matrix.RENDERER }}-${{ env.buildtype }}-${{ needs.android-create-release.outputs.version_tag }}.tar.gz - - # - name: Publish to Github - # env: - # GITHUB_TOKEN: ${{ secrets.MAPLIBRE_NATIVE_PRIVATE_TOKEN }} + - run: | + source venv/bin/activate + pre-commit run clang-format --all-files + rm -rf venv + shell: bash + + # - if: env.SENTRY_DSN != '' # run: | - # renderer=${{ matrix.RENDERER }} - # if [ "$renderer" = "opengl" ]; then - # ./gradlew :MapLibreAndroid:publishDefault${{ env.buildtype }}PublicationToGithubPackagesRepository - # else - # ./gradlew :MapLibreAndroid:publishVulkan${{ env.buildtype }}PublicationToGithubPackagesRepository - # fi - - # finilize-release: - # runs-on: ubuntu-latest - # needs: - # - android-create-release - # - android-build-and-upload-release - # steps: - # - name: Publish release (remove draft) - # uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3 - # with: - # tag_name: ${{ needs.android-create-release.outputs.version_tag }} - # name: ${{ needs.android-create-release.outputs.version_tag }} - # draft: false - - # - run: npm install - # working-directory: . - - # - name: Write release notifications - # if: github.repository_owner == 'maplibre' - # env: - # GITHUB_TOKEN: ${{ secrets.MAPLIBRE_NATIVE_PRIVATE_TOKEN }} - # run: node .github/scripts/notify-release-on-prs.ts --tag ${{ needs.android-create-release.outputs.version_tag }} - # working-directory: . + # echo "SENTRY_ORG=maplibre" >> "$GITHUB_ENV" + # echo "SENTRY_PROJECT=maplibre-android" >> "$GITHUB_ENV" + + - uses: infotroph/tree-is-clean@69d598a958e8cb8f3d0e3d52b5ebcd8684f2adc2 # v1.0.6 + with: + check_untracked: true + + - name: Configure AWS Credentials + if: vars.OIDC_AWS_ROLE_TO_ASSUME + uses: aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 # v4 + with: + aws-region: us-west-2 + role-to-assume: ${{ vars.OIDC_AWS_ROLE_TO_ASSUME }} + role-session-name: ${{ github.run_id }} + + - name: Configure sccache + run: | + echo SCCACHE_BUCKET=maplibre-native-sccache >> "$GITHUB_ENV" + echo SCCACHE_REGION=eu-central-1 >> "$GITHUB_ENV" + + if [ -z "${AWS_SECRET_ACCESS_KEY}" ]; then + echo "AWS_SECRET_ACCESS_KEY not set; not uploading sccache cache to S3" + echo SCCACHE_S3_NO_CREDENTIALS=1 >> "$GITHUB_ENV" + fi + + - name: Check code style + if: matrix.renderer == 'opengl' + run: make android-check + + - name: Run Android unit tests + run: RENDERER=${{ matrix.renderer }} make run-android-unit-test + + - name: Build libmaplibre.so for arm-v8 + run: RENDERER=${{ matrix.renderer }} make android-lib-arm-v8 + + - name: Build API documentation + if: matrix.renderer == 'opengl' + run: ./gradlew dokkaGenerate + + - name: Build Examples documentation + if: matrix.renderer == 'opengl' + run: make mkdocs-build + + - name: Copy developer config with API key for UI tests + if: github.ref == 'refs/heads/main' + run: | + MAPLIBRE_DEVELOPER_CONFIG_XML='${{ secrets.MAPLIBRE_DEVELOPER_CONFIG_XML }}' + if [ -n "${MAPLIBRE_DEVELOPER_CONFIG_XML}" ]; then + echo "${MAPLIBRE_DEVELOPER_CONFIG_XML}" > MapLibreAndroidTestApp/src/main/res/values/developer-config.xml + else + echo "No secrets.MAPLIBRE_DEVELOPER_CONFIG_XML variable set, not copying..." + fi + + - name: Build Benchmark, copy to platform/android + run: | + ./gradlew assemble${{ matrix.renderer }}Release assemble${{ matrix.renderer }}ReleaseAndroidTest -PtestBuildType=release -Pmaplibre.abis=arm64-v8a + cp MapLibreAndroidTestApp/build/outputs/apk/${{ matrix.renderer }}/release/MapLibreAndroidTestApp-${{ matrix.renderer }}-release.apk . + cp MapLibreAndroidTestApp/build/outputs/apk/androidTest/${{ matrix.renderer }}/release/MapLibreAndroidTestApp-${{ matrix.renderer }}-release-androidTest.apk . + + # https://developer.android.com/guide/practices/page-sizes + - name: Check alignment of .apk + run: | + unzip -o MapLibreAndroidTestApp/build/outputs/apk/${{ matrix.renderer }}/release/MapLibreAndroidTestApp-${{ matrix.renderer }}-release.apk -d /tmp/my_apk_out + scripts/check-alignment.sh /tmp/my_apk_out + + - name: Create artifact for benchmark APKs + if: matrix.renderer == 'opengl' + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + if-no-files-found: error + name: benchmarkAPKs + path: | + platform/android/MapLibreAndroidTestApp-${{ matrix.renderer }}-release.apk + platform/android/MapLibreAndroidTestApp-${{ matrix.renderer }}-release-androidTest.apk + + - if: github.event_name == 'pull_request' && matrix.renderer == 'opengl' + uses: ./.github/actions/save-pr-number + + - name: Set renderer env var (OpenGL or Vulkan) + shell: bash + run: | + case "${{ matrix.renderer }}" in + opengl) echo "renderer=OpenGL" >> "$GITHUB_ENV" ;; + vulkan) echo "renderer=Vulkan" >> "$GITHUB_ENV" ;; + *) echo "::error ::Unknown renderer '${{ matrix.renderer }}'"; exit 1 ;; + esac + + - name: Build Instrumentation Tests (${{ matrix.renderer }}), copy to platform/android + run: | + ./gradlew assemble${{ matrix.renderer }}Debug assemble${{ matrix.renderer }}DebugAndroidTest -PtestBuildType=debug -Pmaplibre.abis=arm64-v8a + cp MapLibreAndroidTestApp/build/outputs/apk/${{ matrix.renderer }}/debug/MapLibreAndroidTestApp-${{ matrix.renderer }}-debug.apk InstrumentationTestApp${{ env.renderer }}.apk + cp MapLibreAndroidTestApp/build/outputs/apk/androidTest/${{ matrix.renderer }}/debug/MapLibreAndroidTestApp-${{ matrix.renderer }}-debug-androidTest.apk InstrumentationTests${{ env.renderer }}.apk + + # - name: Install sentry-cli + # if: env.SENTRY_DSN != '' + # run: curl -sL https://sentry.io/get-cli/ | sh + + # - name: Upload debug symbols to sentry + # if: env.SENTRY_DSN != '' + # run: sentry-cli debug-files upload MapLibreAndroidTestApp + + - name: Upload android-ui-test-${{ matrix.renderer }} + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + if-no-files-found: error + name: android-ui-test-${{ matrix.renderer }} + path: | + platform/android/InstrumentationTestApp${{ env.renderer }}.apk + platform/android/InstrumentationTests${{ env.renderer }}.apk + + - name: Show sccache stats + run: sccache --show-stats + + android-build-cpp-test: + runs-on: ubuntu-24.04 + + needs: + - pre_job + if: needs.pre_job.outputs.should_skip != 'true' + + defaults: + run: + working-directory: test/android + + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v4 + with: + submodules: recursive + persist-credentials: false + + - uses: ./.github/actions/setup-android-ci + + - name: Create data.zip in assets directory + run: zip -r test/android/app/src/main/assets/data.zip -@ < test/android/app/src/main/assets/to_zip.txt + working-directory: . + + - name: Configure AWS Credentials + if: vars.OIDC_AWS_ROLE_TO_ASSUME + uses: aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 # v4 + with: + aws-region: us-west-2 + role-to-assume: ${{ vars.OIDC_AWS_ROLE_TO_ASSUME }} + role-session-name: ${{ github.run_id }} + + - name: Configure sccache + run: | + echo SCCACHE_BUCKET=maplibre-native-sccache >> "$GITHUB_ENV" + echo SCCACHE_REGION=eu-central-1 >> "$GITHUB_ENV" + + if [ -z "${AWS_SECRET_ACCESS_KEY}" ]; then + echo "AWS_SECRET_ACCESS_KEY not set; not uploading sccache cache to S3" + echo SCCACHE_S3_NO_CREDENTIALS=1 >> "$GITHUB_ENV" + fi + + - name: Build C++ Unit Tests App + run: | + ./gradlew assembleDebug assembleAndroidTest -Pmaplibre.abis=arm64-v8a + cp app/build/outputs/apk/debug/app-debug.apk . + cp app/build/outputs/apk/androidTest/release/app-release-androidTest.apk . + + - name: Store C++ Unit Tests .apk files + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: android-cpp-tests + if-no-files-found: error + path: | + ./test/android/app-debug.apk + ./test/android/app-release-androidTest.apk + + android-build-render-test: + strategy: + fail-fast: false + matrix: + flavor: [opengl, vulkan] + + runs-on: ubuntu-24.04 + + needs: + - pre_job + + if: needs.pre_job.outputs.should_skip != 'true' + + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v4 + with: + submodules: recursive + persist-credentials: false + + - uses: ./.github/actions/setup-android-ci + + - name: Configure AWS Credentials + if: vars.OIDC_AWS_ROLE_TO_ASSUME + uses: aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 # v4 + with: + aws-region: us-west-2 + role-to-assume: ${{ vars.OIDC_AWS_ROLE_TO_ASSUME }} + role-session-name: ${{ github.run_id }} + + - name: Configure sccache + run: | + echo SCCACHE_BUCKET=maplibre-native-sccache >> "$GITHUB_ENV" + echo SCCACHE_REGION=eu-central-1 >> "$GITHUB_ENV" + + if [ -z "${AWS_SECRET_ACCESS_KEY}" ]; then + echo "AWS_SECRET_ACCESS_KEY not set; not uploading sccache cache to S3" + echo SCCACHE_S3_NO_CREDENTIALS=1 >> "$GITHUB_ENV" + fi + + - name: Build and Upload Render Test APKs (${{ matrix.flavor }}) + uses: ./.github/actions/android-build-and-upload-render-test + with: + flavor: ${{ matrix.flavor }} + + android-ci-result: + runs-on: ubuntu-latest + permissions: + actions: write + contents: write + if: needs.pre_job.outputs.should_skip != 'true' && always() + needs: + - pre_job + - android-build + - android-build-cpp-test + - android-build-render-test + steps: + - name: Set success=true + if: needs.android-build.result == 'success' && needs.android-build-cpp-test.result == 'success' && needs.android-build-render-test.result == 'success' + run: echo success=true > "$GITHUB_ENV" + + - name: Mark result as failed + if: env.success != 'true' + run: exit 1 + + # automatically trigger android-release when code is pushed to main + # and the platform/android/VERSION file has changed + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v4 + if: github.ref == 'refs/heads/main' && github.event_name == 'push' + + - name: VERSION file changed + if: github.ref == 'refs/heads/main' && github.event_name == 'push' + id: version-file-android-changed + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files: platform/android/VERSION + + - name: Should make release? + if: env.success && github.ref == 'refs/heads/main' && github.event_name == 'push' && steps.version-file-android-changed.outputs.any_changed == 'true' + run: echo make_release=true >> "$GITHUB_ENV" + + - name: Validate and set version + if: env.make_release == 'true' + working-directory: . + run: .github/scripts/validate-version.sh platform/android/VERSION + + - name: Create tag if it does not exist + if: env.make_release == 'true' + run: .github/scripts/ensure-tag.sh android-v${{ env.version }} ${{ github.sha }} + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Trigger release + if: env.make_release == 'true' + run: gh workflow run android-release.yml --ref android-v${{ env.version }} + env: + GH_TOKEN: ${{ github.token }} diff --git a/.github/workflows/android-release.yml b/.github/workflows/android-release.yml index 8467b026d428..0333f9cd1ab9 100644 --- a/.github/workflows/android-release.yml +++ b/.github/workflows/android-release.yml @@ -86,6 +86,24 @@ jobs: working-directory: . run: .github/scripts/free_disk_space.sh + - name: Setup build directories on /mnt + working-directory: . + run: | + echo "Disk space before setup:" + df -h + + # Create build directories on /mnt + sudo mkdir -p /mnt/gradle /mnt/build /mnt/android-sdk + sudo chown -R $USER:$USER /mnt/gradle /mnt/build /mnt/android-sdk + + # Create symlinks for build directories + mkdir -p platform/android + ln -sfn /mnt/build platform/android/build || true + + # Configure gradle to use /mnt + echo "gradle.user.home=/mnt/gradle" >> gradle.properties || true + echo "buildDir=/mnt/build" >> gradle.properties || true + - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v4 with: node-version-file: ".nvmrc" From 63c707cfd1d20c13210f54c79cea797227bf1206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Tue, 11 Nov 2025 11:24:05 -0500 Subject: [PATCH 209/221] Updated with precommit --- platform/darwin/src/MLNPluginStyleLayer.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platform/darwin/src/MLNPluginStyleLayer.h b/platform/darwin/src/MLNPluginStyleLayer.h index 09accbf0a1f6..92bb2ef5cd0e 100644 --- a/platform/darwin/src/MLNPluginStyleLayer.h +++ b/platform/darwin/src/MLNPluginStyleLayer.h @@ -13,9 +13,7 @@ MLN_EXPORT layerIdentifier:(NSString *)identifier layerPropeties:(NSDictionary *)layerPropeties; -- (void)setPluginProperty:(NSString *)propertyName - value:(id)propertyValue; - +- (void)setPluginProperty:(NSString *)propertyName value:(id)propertyValue; @end From 83bb6f8aef55d4958e17b256d3a1bf86f9564cf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Tue, 11 Nov 2025 12:05:21 -0500 Subject: [PATCH 210/221] Android cleanup --- .../org/maplibre/android/maps/MapLibreMap.java | 3 +-- .../maplibre/android/maps/NativeMapView.java | 2 -- .../android/plugin/PluginFileSource.java | 18 ++++++++++-------- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java index b264a1892e79..3abcfd90d050 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java @@ -2729,11 +2729,10 @@ private void notifyDeveloperAnimationListeners() { * Adds a custom protocol handler to the map view */ ArrayList pluginProtocolHandlers = new ArrayList(); + public void addPluginProtocolHandler(PluginProtocolHandler protocolHandler) { pluginProtocolHandlers.add(protocolHandler); nativeMapView.addPluginProtocolHandler(protocolHandler); - - // nativeMapView.addPolygon() } diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java index 018fcf39f3ed..78f624f8dab7 100755 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java @@ -15,7 +15,6 @@ import org.maplibre.android.plugin.PluginFileSource; import org.maplibre.android.plugin.PluginProtocolHandler; -import org.maplibre.android.plugin.PluginProtocolHandlerResource; import org.maplibre.geojson.Feature; import org.maplibre.geojson.Geometry; import org.maplibre.android.LibraryLoader; @@ -41,7 +40,6 @@ import org.maplibre.android.style.sources.Source; import org.maplibre.android.utils.BitmapUtils; import org.maplibre.android.tile.TileOperation; -import org.maplibre.android.plugin.PluginFileSource; import java.util.ArrayList; import java.util.Arrays; diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginFileSource.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginFileSource.java index e99ca05a08fb..5fbafbfb8d47 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginFileSource.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginFileSource.java @@ -2,17 +2,19 @@ public class PluginFileSource { - public PluginProtocolHandler protocolHandler; + public PluginProtocolHandler protocolHandler; - public boolean canRequestResource(PluginProtocolHandlerResource resource) { + public boolean canRequestResource(PluginProtocolHandlerResource resource) { - return protocolHandler.canRequestResource(resource); + return protocolHandler.canRequestResource(resource); - } + } - public PluginProtocolHandlerResponse requestResource(PluginProtocolHandlerResource resource) { - PluginProtocolHandlerResponse response = protocolHandler.requestResource(resource); - return response; - } + public PluginProtocolHandlerResponse requestResource(PluginProtocolHandlerResource resource) { + + PluginProtocolHandlerResponse response = protocolHandler.requestResource(resource); + return response; + + } } From f4f22d9d61a16f2b0c99fbdd57f3f9df9a17d205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Wed, 12 Nov 2025 08:12:02 -0500 Subject: [PATCH 211/221] Cleaning up java files --- .../java/org/maplibre/android/plugin/PluginFileSource.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginFileSource.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginFileSource.java index 5fbafbfb8d47..9321740f0a7c 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginFileSource.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/plugin/PluginFileSource.java @@ -11,10 +11,10 @@ public boolean canRequestResource(PluginProtocolHandlerResource resource) { } public PluginProtocolHandlerResponse requestResource(PluginProtocolHandlerResource resource) { - + PluginProtocolHandlerResponse response = protocolHandler.requestResource(resource); return response; - + } } From 64c0391c957b9967985c57dc7dd46ee7194f895d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Wed, 12 Nov 2025 08:24:13 -0500 Subject: [PATCH 212/221] Change how render function is called --- src/mbgl/plugin/plugin_layer_render.cpp | 4 ++-- src/mbgl/plugin/plugin_layer_render.hpp | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/mbgl/plugin/plugin_layer_render.cpp b/src/mbgl/plugin/plugin_layer_render.cpp index 09d8beb27987..84ca4091384f 100644 --- a/src/mbgl/plugin/plugin_layer_render.cpp +++ b/src/mbgl/plugin/plugin_layer_render.cpp @@ -57,7 +57,7 @@ void RenderPluginLayerTweaker::execute([[maybe_unused]] mbgl::gfx::Drawable& dra style::CustomLayerRenderParameters parameters(paintParameters); #endif - _plugInRenderer->render(paintParameters); + _plugInRenderer->callRenderFunction(paintParameters); // Reset the view back to our original one, just in case the CustomLayer // changed the viewport or Framebuffer. @@ -181,7 +181,7 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis void RenderPluginLayer::upload([[maybe_unused]] gfx::UploadPass& uploadPass) {} -void RenderPluginLayer::render(PaintParameters& paintParameters) { +void RenderPluginLayer::callRenderFunction(PaintParameters& paintParameters) { if (_renderFunction) { _renderFunction(paintParameters); } diff --git a/src/mbgl/plugin/plugin_layer_render.hpp b/src/mbgl/plugin/plugin_layer_render.hpp index f7ccdc70d8c8..41f2655c878f 100644 --- a/src/mbgl/plugin/plugin_layer_render.hpp +++ b/src/mbgl/plugin/plugin_layer_render.hpp @@ -28,7 +28,6 @@ class RenderPluginLayer final : public RenderLayer { void prepare(const LayerPrepareParameters&) override; void upload(gfx::UploadPass&) override; - void render(PaintParameters&) override; void setRenderFunction(style::PluginLayer::OnRenderLayer renderFunction) { _renderFunction = renderFunction; } void setUpdateFunction(style::PluginLayer::OnUpdateLayer updateFunction) { _updateFunction = updateFunction; } @@ -36,6 +35,8 @@ class RenderPluginLayer final : public RenderLayer { _updateLayerPropertiesFunction = updateLayerPropertiesFunction; } + void callRenderFunction(PaintParameters& paintParameters); + private: void transition(const TransitionParameters&) override; void evaluate(const PropertyEvaluationParameters&) override; From 748b97283a5a563acb7952c0b01fe9da4cdb3c26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Wed, 12 Nov 2025 08:54:52 -0500 Subject: [PATCH 213/221] Fix for compiler issue --- platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp index 2546a188efc7..152b135d4089 100644 --- a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp +++ b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp @@ -1547,10 +1547,10 @@ void NativeMapView::registerNative(jni::JNIEnv& env) { METHOD(&NativeMapView::getTileLodZoomShift, "nativeGetTileLodZoomShift"), METHOD(&NativeMapView::triggerRepaint, "nativeTriggerRepaint"), METHOD(&NativeMapView::toggleTransform, "nativeToggleTransform"), - METHOD(&NativeMapView::setFrustumOffset, "nativeSetFrustumOffset")); + METHOD(&NativeMapView::setFrustumOffset, "nativeSetFrustumOffset"), METHOD(&NativeMapView::isRenderingStatsViewEnabled, "nativeIsRenderingStatsViewEnabled"), METHOD(&NativeMapView::enableRenderingStatsView, "nativeEnableRenderingStatsView"), - METHOD(&NativeMapView::addPluginFileSource, "nativeAddPluginFileSource")); + METHOD(&NativeMapView::addPluginFileSource, "nativeAddPluginFileSource") } void NativeMapView::onRegisterShaders(gfx::ShaderRegistry&) {}; From 951ac20175335905876b45f88ebee37d7d184ee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Wed, 12 Nov 2025 09:12:50 -0500 Subject: [PATCH 214/221] Fix for android build issue --- platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp index 152b135d4089..a9df1fc86165 100644 --- a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp +++ b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp @@ -1550,7 +1550,7 @@ void NativeMapView::registerNative(jni::JNIEnv& env) { METHOD(&NativeMapView::setFrustumOffset, "nativeSetFrustumOffset"), METHOD(&NativeMapView::isRenderingStatsViewEnabled, "nativeIsRenderingStatsViewEnabled"), METHOD(&NativeMapView::enableRenderingStatsView, "nativeEnableRenderingStatsView"), - METHOD(&NativeMapView::addPluginFileSource, "nativeAddPluginFileSource") + METHOD(&NativeMapView::addPluginFileSource, "nativeAddPluginFileSource")); } void NativeMapView::onRegisterShaders(gfx::ShaderRegistry&) {}; From fbe70c9f75b23d60fe65cfa00abebc1c626560c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Sun, 16 Nov 2025 23:56:21 -0500 Subject: [PATCH 215/221] Updated version --- platform/ios/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/VERSION b/platform/ios/VERSION index 7a33340e0e39..3a8e58e6b3a9 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.19.3 +6.19.4 From bd237ff830814742b9bad26dd9fe9aacbb55012a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Mon, 17 Nov 2025 01:05:31 -0500 Subject: [PATCH 216/221] Compiler fixes for linux build --- src/mbgl/style/style.cpp | 2 +- src/mbgl/style/style_impl.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index 0caa94860549..0df55a81d168 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -180,7 +180,7 @@ std::unique_ptr Style::removeLayer(const std::string& id) { // Add style parsing filter void Style::addStyleFilter(std::shared_ptr filter) { impl->mutated = true; - return impl->addStyleFilter(filter); + impl->addStyleFilter(filter); } } // namespace style diff --git a/src/mbgl/style/style_impl.cpp b/src/mbgl/style/style_impl.cpp index 11669068c641..a2be6d9860d3 100644 --- a/src/mbgl/style/style_impl.cpp +++ b/src/mbgl/style/style_impl.cpp @@ -88,7 +88,7 @@ void Style::Impl::filterThenParse(const std::string& styleData) { // Otherwise, go through the chain of filters std::string filteredStyle = styleData; - for (auto filter : _styleFilters) { + for (const auto & filter : _styleFilters) { filteredStyle = filter->filterResponse(filteredStyle); } parse(filteredStyle); From 6382974bc03eef6aa53172708e28a2ec83d8b4e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Mon, 17 Nov 2025 01:17:16 -0500 Subject: [PATCH 217/221] precommit fix --- src/mbgl/style/style_impl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mbgl/style/style_impl.cpp b/src/mbgl/style/style_impl.cpp index a2be6d9860d3..3dab0eecd209 100644 --- a/src/mbgl/style/style_impl.cpp +++ b/src/mbgl/style/style_impl.cpp @@ -88,7 +88,7 @@ void Style::Impl::filterThenParse(const std::string& styleData) { // Otherwise, go through the chain of filters std::string filteredStyle = styleData; - for (const auto & filter : _styleFilters) { + for (const auto& filter : _styleFilters) { filteredStyle = filter->filterResponse(filteredStyle); } parse(filteredStyle); From e8be6e6b06c15873448e4bf26bf3e37cb1ab84bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Mon, 17 Nov 2025 02:18:41 -0500 Subject: [PATCH 218/221] Another linux build issue --- src/mbgl/plugin/plugin_layer_render.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mbgl/plugin/plugin_layer_render.cpp b/src/mbgl/plugin/plugin_layer_render.cpp index 84ca4091384f..978f5fdb7d56 100644 --- a/src/mbgl/plugin/plugin_layer_render.cpp +++ b/src/mbgl/plugin/plugin_layer_render.cpp @@ -90,7 +90,7 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis bool removeAllTiles = ((renderTiles == nullptr) || (renderTiles->empty())); // Get list of tiles to remove and then remove them - for (auto currentCollection : _featureCollectionByTile) { + for (const auto & currentCollection : _featureCollectionByTile) { if (removeAllTiles || !hasRenderTile(currentCollection.first)) { removedTiles.push_back(currentCollection.first); } From 9026b34f5cd30c72f4f78eb37110c50abdc70789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Mon, 17 Nov 2025 02:28:22 -0500 Subject: [PATCH 219/221] fix for android build --- src/mbgl/plugin/plugin_layer_render.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mbgl/plugin/plugin_layer_render.cpp b/src/mbgl/plugin/plugin_layer_render.cpp index 978f5fdb7d56..f3a209f82547 100644 --- a/src/mbgl/plugin/plugin_layer_render.cpp +++ b/src/mbgl/plugin/plugin_layer_render.cpp @@ -90,7 +90,7 @@ void RenderPluginLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaderRegis bool removeAllTiles = ((renderTiles == nullptr) || (renderTiles->empty())); // Get list of tiles to remove and then remove them - for (const auto & currentCollection : _featureCollectionByTile) { + for (const auto& currentCollection : _featureCollectionByTile) { if (removeAllTiles || !hasRenderTile(currentCollection.first)) { removedTiles.push_back(currentCollection.first); } From 7847a00c65900f7573aa07a2594e58464d2270f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Mon, 17 Nov 2025 03:34:24 -0500 Subject: [PATCH 220/221] Another fix for linux --- src/mbgl/plugin/feature_collection_bucket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mbgl/plugin/feature_collection_bucket.cpp b/src/mbgl/plugin/feature_collection_bucket.cpp index 09d24dbbd09b..f8a358517822 100644 --- a/src/mbgl/plugin/feature_collection_bucket.cpp +++ b/src/mbgl/plugin/feature_collection_bucket.cpp @@ -76,7 +76,7 @@ void FeatureCollectionBucket::addFeature(const GeometryTileFeature& tileFeature, } auto pm = tileFeature.getProperties(); - for (auto p : pm) { + for (const auto& p : pm) { auto name = p.first; mapbox::feature::value value = p.second; From 9d6d5a5087b8268ace020619114668e569c0a7c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CMalcolm?= <“mtoon@atlasprogramming.com”> Date: Mon, 17 Nov 2025 04:38:29 -0500 Subject: [PATCH 221/221] Another linux build fix --- platform/default/src/mbgl/storage/main_resource_loader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/default/src/mbgl/storage/main_resource_loader.cpp b/platform/default/src/mbgl/storage/main_resource_loader.cpp index 208c109e5fe8..90150031adbe 100644 --- a/platform/default/src/mbgl/storage/main_resource_loader.cpp +++ b/platform/default/src/mbgl/storage/main_resource_loader.cpp @@ -68,7 +68,7 @@ class MainResourceLoaderThread { // Go through custom handlers bool requestHandledByCustomHandler = false; auto fm = FileSourceManager::get(); - for (auto customFileSource : fm->getCustomFileSources()) { + for (const auto& customFileSource : fm->getCustomFileSources()) { if (customFileSource->canRequest(resource)) { tasks[req] = customFileSource->request(resource, callback); requestHandledByCustomHandler = true; @@ -195,7 +195,7 @@ class MainResourceLoader::Impl { bool canRequest(const Resource& resource) const { // Check the custom file sources auto fm = FileSourceManager::get(); - for (auto customFileSource : fm->getCustomFileSources()) { + for (const auto& customFileSource : fm->getCustomFileSources()) { if (customFileSource->canRequest(resource)) { return true; }