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