From 4ea73657d1b790354aaf240c0ab5c72b77cf4132 Mon Sep 17 00:00:00 2001 From: David Lively Date: Fri, 3 Oct 2025 12:34:53 -0500 Subject: [PATCH 01/13] Modified texture and model import process to flip texture images and UV coordinates to comply with Unity U-right, V-up convention. --- CHANGES.md | 6 +++ native~/Runtime/src/TextureLoader.cpp | 37 ++++++++++++++++--- .../src/UnityPrepareRendererResources.cpp | 6 ++- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 9b9a5249..c8690092 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,11 @@ # Change Log +## ? - ? + +##### Fixes :wrench: + +- Corrected texture import process to flip textures and UV coordinates from glTF's U-right, V-down convention to comply with Unity's U-right, V-up coordinate system. + ## v1.18.1 - 2025-10-01 This release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.51.0 to v0.52.1. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. diff --git a/native~/Runtime/src/TextureLoader.cpp b/native~/Runtime/src/TextureLoader.cpp index 9ae20be8..b7e0d627 100644 --- a/native~/Runtime/src/TextureLoader.cpp +++ b/native~/Runtime/src/TextureLoader.cpp @@ -69,6 +69,25 @@ getUncompressedPixelFormat(const CesiumGltf::ImageAsset& image) { } } +/** + * Copy image data while flipping the data vertically. According to the glTF 2.0 + * spec, glTF stores textures in x-right, y-down (right-handed) coordinates. + * However, Unity uses x-right, y-up coordinates, so we need to flip the textures + * and UV coordinates. See loadPrimitive() in UnityPrepareRenderResources.cpp for + * the corresponding UV flip. + **/ +template +void copyAndFlipY(TSrcByte* dst, const TDstByte* src, const size_t dataLength, const size_t height) { + assert((dataLength % height) == 0 && "Image data size is not an even multiple of image width."); + + const size_t stride = dataLength / height; + + for (size_t j=0; j < height; ++j) { + memcpy(dst, src + (height - j) * stride, stride); + dst += stride; + } +} + } // namespace UnityEngine::Texture @@ -100,21 +119,29 @@ TextureLoader::loadTexture(const CesiumGltf::ImageAsset& image, bool sRGB) { if (image.mipPositions.empty()) { // No mipmaps, copy the whole thing and then let Unity generate mipmaps on a // worker thread. - std::memcpy(pixels, image.pixelData.data(), image.pixelData.size()); + copyAndFlipY(pixels, image.pixelData.data(), image.pixelData.size(), image.height); result.Apply(false, true); } else { // Copy the mipmaps explicitly. std::uint8_t* pWritePosition = pixels; const std::byte* pReadBuffer = image.pixelData.data(); + // track square image dimension for each mip level + int32_t mipHeight = image.height; + for (const ImageAssetMipPosition& mip : image.mipPositions) { - size_t start = mip.byteOffset; - size_t end = mip.byteOffset + mip.byteSize; - if (start >= textureLength || end > textureLength) + assert(mipHeight > 0 && "Invalid image size."); + const size_t start = mip.byteOffset; + const size_t end = mip.byteOffset + mip.byteSize; + if (start >= textureLength || end > textureLength) { + mipHeight /= 2; continue; // invalid mip spec, ignore it + } - std::memcpy(pWritePosition, pReadBuffer + start, mip.byteSize); + copyAndFlipY(pWritePosition, pReadBuffer + start, mip.byteSize, mipHeight); pWritePosition += mip.byteSize; + // adjust height for next mip level. + mipHeight /= 2; } result.Apply(false, true); diff --git a/native~/Runtime/src/UnityPrepareRendererResources.cpp b/native~/Runtime/src/UnityPrepareRendererResources.cpp index dbeff78c..1d5807f4 100644 --- a/native~/Runtime/src/UnityPrepareRendererResources.cpp +++ b/native~/Runtime/src/UnityPrepareRendererResources.cpp @@ -628,8 +628,10 @@ void loadPrimitive( for (uint32_t texCoordIndex = 0; texCoordIndex < numTexCoords; ++texCoordIndex) { - *reinterpret_cast(pWritePos) = - texCoordViews[texCoordIndex][i]; + Vector2 texCoord = texCoordViews[texCoordIndex][i]; + // flip Y to comply with Unity's left-handed UV coordinates + texCoord.y = 1 - texCoord.y; + *reinterpret_cast(pWritePos) = texCoord; pWritePos += sizeof(Vector2); } } From 1284e5801c061fddc1c7897f5c021fcf44cffba3 Mon Sep 17 00:00:00 2001 From: David Lively Date: Fri, 3 Oct 2025 12:46:51 -0500 Subject: [PATCH 02/13] Formatting --- .gitignore | 2 ++ native~/Runtime/src/TextureLoader.cpp | 32 +++++++++++++++++++-------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index af8e1747..73bb4bcc 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,8 @@ CesiumForUnityNativeBindings/native/ *.user .DS_STORE .idea +obj.meta +bin.meta Reinterop.dll Reinterop.deps.json Reinterop.deps.json.meta diff --git a/native~/Runtime/src/TextureLoader.cpp b/native~/Runtime/src/TextureLoader.cpp index b7e0d627..b60a2232 100644 --- a/native~/Runtime/src/TextureLoader.cpp +++ b/native~/Runtime/src/TextureLoader.cpp @@ -72,17 +72,23 @@ getUncompressedPixelFormat(const CesiumGltf::ImageAsset& image) { /** * Copy image data while flipping the data vertically. According to the glTF 2.0 * spec, glTF stores textures in x-right, y-down (right-handed) coordinates. - * However, Unity uses x-right, y-up coordinates, so we need to flip the textures - * and UV coordinates. See loadPrimitive() in UnityPrepareRenderResources.cpp for - * the corresponding UV flip. + * However, Unity uses x-right, y-up coordinates, so we need to flip the + *textures and UV coordinates. See loadPrimitive() in + *UnityPrepareRenderResources.cpp for the corresponding UV flip. **/ -template -void copyAndFlipY(TSrcByte* dst, const TDstByte* src, const size_t dataLength, const size_t height) { - assert((dataLength % height) == 0 && "Image data size is not an even multiple of image width."); +template +void copyAndFlipY( + TSrcByte* dst, + const TDstByte* src, + const size_t dataLength, + const size_t height) { + assert( + (dataLength % height) == 0 && + "Image data size is not an even multiple of image width."); const size_t stride = dataLength / height; - for (size_t j=0; j < height; ++j) { + for (size_t j = 0; j < height; ++j) { memcpy(dst, src + (height - j) * stride, stride); dst += stride; } @@ -119,7 +125,11 @@ TextureLoader::loadTexture(const CesiumGltf::ImageAsset& image, bool sRGB) { if (image.mipPositions.empty()) { // No mipmaps, copy the whole thing and then let Unity generate mipmaps on a // worker thread. - copyAndFlipY(pixels, image.pixelData.data(), image.pixelData.size(), image.height); + copyAndFlipY( + pixels, + image.pixelData.data(), + image.pixelData.size(), + image.height); result.Apply(false, true); } else { // Copy the mipmaps explicitly. @@ -138,7 +148,11 @@ TextureLoader::loadTexture(const CesiumGltf::ImageAsset& image, bool sRGB) { continue; // invalid mip spec, ignore it } - copyAndFlipY(pWritePosition, pReadBuffer + start, mip.byteSize, mipHeight); + copyAndFlipY( + pWritePosition, + pReadBuffer + start, + mip.byteSize, + mipHeight); pWritePosition += mip.byteSize; // adjust height for next mip level. mipHeight /= 2; From 0c3618a59e0c98c0f9629fae33b89aeeae494d2f Mon Sep 17 00:00:00 2001 From: David Lively Date: Fri, 3 Oct 2025 12:48:28 -0500 Subject: [PATCH 03/13] Corrected assert message --- native~/Runtime/src/TextureLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native~/Runtime/src/TextureLoader.cpp b/native~/Runtime/src/TextureLoader.cpp index b60a2232..d0b909c6 100644 --- a/native~/Runtime/src/TextureLoader.cpp +++ b/native~/Runtime/src/TextureLoader.cpp @@ -84,7 +84,7 @@ void copyAndFlipY( const size_t height) { assert( (dataLength % height) == 0 && - "Image data size is not an even multiple of image width."); + "Image data size is not an even multiple of image height."); const size_t stride = dataLength / height; From 01e4a4805c2bc85f40c4627643778813f5122d36 Mon Sep 17 00:00:00 2001 From: David Lively Date: Fri, 3 Oct 2025 12:49:42 -0500 Subject: [PATCH 04/13] Rephrased --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index c8690092..5707df66 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,7 +4,7 @@ ##### Fixes :wrench: -- Corrected texture import process to flip textures and UV coordinates from glTF's U-right, V-down convention to comply with Unity's U-right, V-up coordinate system. +- Corrected glTF import process to flip textures and UV coordinates from glTF's U-right, V-down convention to comply with Unity's U-right, V-up coordinate system. ## v1.18.1 - 2025-10-01 From f9e8723b3be8dae91690494169e26c0bbeca7fca Mon Sep 17 00:00:00 2001 From: David Lively Date: Fri, 3 Oct 2025 13:23:58 -0500 Subject: [PATCH 05/13] Corrected overlooked case when vertices are duplicated for flat normals --- native~/Runtime/src/UnityPrepareRendererResources.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/native~/Runtime/src/UnityPrepareRendererResources.cpp b/native~/Runtime/src/UnityPrepareRendererResources.cpp index 1d5807f4..b10935fb 100644 --- a/native~/Runtime/src/UnityPrepareRendererResources.cpp +++ b/native~/Runtime/src/UnityPrepareRendererResources.cpp @@ -605,8 +605,9 @@ void loadPrimitive( } for (uint32_t texCoordIndex = 0; texCoordIndex < numTexCoords; ++texCoordIndex) { - *reinterpret_cast(pWritePos) = - texCoordViews[texCoordIndex][vertexIndex]; + Vector2 texCoord = texCoordViews[texCoordIndex][vertexIndex]; + texCoord.y = 1 - texCoord.y; + *reinterpret_cast(pWritePos) =texCoord; pWritePos += sizeof(Vector2); } } From e861ad24669c8f4ec73a49dde3c6f942c61b3b36 Mon Sep 17 00:00:00 2001 From: David Lively Date: Fri, 3 Oct 2025 13:34:27 -0500 Subject: [PATCH 06/13] Added a comment. --- native~/Runtime/src/UnityPrepareRendererResources.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/native~/Runtime/src/UnityPrepareRendererResources.cpp b/native~/Runtime/src/UnityPrepareRendererResources.cpp index b10935fb..95939605 100644 --- a/native~/Runtime/src/UnityPrepareRendererResources.cpp +++ b/native~/Runtime/src/UnityPrepareRendererResources.cpp @@ -606,6 +606,7 @@ void loadPrimitive( for (uint32_t texCoordIndex = 0; texCoordIndex < numTexCoords; ++texCoordIndex) { Vector2 texCoord = texCoordViews[texCoordIndex][vertexIndex]; + // flip Y to comply with Unity's left-handed UV coordinates texCoord.y = 1 - texCoord.y; *reinterpret_cast(pWritePos) =texCoord; pWritePos += sizeof(Vector2); @@ -615,18 +616,15 @@ void loadPrimitive( for (int64_t i = 0; i < vertexCount; ++i) { *reinterpret_cast(pWritePos) = positionView[i]; pWritePos += sizeof(Vector3); - if (hasNormals) { *reinterpret_cast(pWritePos) = normalView[i]; pWritePos += sizeof(Vector3); } - // Skip the slot allocated for vertex colors, we will fill them in // bulk later. if (hasVertexColors) { pWritePos += sizeof(uint32_t); } - for (uint32_t texCoordIndex = 0; texCoordIndex < numTexCoords; ++texCoordIndex) { Vector2 texCoord = texCoordViews[texCoordIndex][i]; From 6d1bae70421a95ca09325356da9cef770bcb1c2a Mon Sep 17 00:00:00 2001 From: David Lively Date: Fri, 3 Oct 2025 13:58:17 -0500 Subject: [PATCH 07/13] Formatting --- native~/Runtime/src/UnityPrepareRendererResources.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native~/Runtime/src/UnityPrepareRendererResources.cpp b/native~/Runtime/src/UnityPrepareRendererResources.cpp index 95939605..617aeda8 100644 --- a/native~/Runtime/src/UnityPrepareRendererResources.cpp +++ b/native~/Runtime/src/UnityPrepareRendererResources.cpp @@ -608,7 +608,7 @@ void loadPrimitive( Vector2 texCoord = texCoordViews[texCoordIndex][vertexIndex]; // flip Y to comply with Unity's left-handed UV coordinates texCoord.y = 1 - texCoord.y; - *reinterpret_cast(pWritePos) =texCoord; + *reinterpret_cast(pWritePos) = texCoord; pWritePos += sizeof(Vector2); } } From 93aeee2817063b7327ea897b24c78b6a85045a37 Mon Sep 17 00:00:00 2001 From: David Lively Date: Mon, 6 Oct 2025 12:21:13 -0500 Subject: [PATCH 08/13] Addressing PR feedback. Renamed a few things for clarity. --- CHANGES.md | 3 +- native~/Runtime/src/TextureLoader.cpp | 30 +++++++++---------- .../src/UnityPrepareRendererResources.cpp | 4 +-- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5707df66..6cda75f4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,8 +3,7 @@ ## ? - ? ##### Fixes :wrench: - -- Corrected glTF import process to flip textures and UV coordinates from glTF's U-right, V-down convention to comply with Unity's U-right, V-up coordinate system. +- Textures and UV coordinates from glTFs are now flipped to properly comply with Unity's U-right, V-up convention. ## v1.18.1 - 2025-10-01 diff --git a/native~/Runtime/src/TextureLoader.cpp b/native~/Runtime/src/TextureLoader.cpp index d0b909c6..a938a9c9 100644 --- a/native~/Runtime/src/TextureLoader.cpp +++ b/native~/Runtime/src/TextureLoader.cpp @@ -71,15 +71,14 @@ getUncompressedPixelFormat(const CesiumGltf::ImageAsset& image) { /** * Copy image data while flipping the data vertically. According to the glTF 2.0 - * spec, glTF stores textures in x-right, y-down (right-handed) coordinates. + * spec, glTF stores textures in x-right, y-down coordinates. * However, Unity uses x-right, y-up coordinates, so we need to flip the - *textures and UV coordinates. See loadPrimitive() in - *UnityPrepareRenderResources.cpp for the corresponding UV flip. + * textures and UV coordinates. See loadPrimitive() in + * UnityPrepareRenderResources.cpp for the corresponding UV flip. **/ -template -void copyAndFlipY( - TSrcByte* dst, - const TDstByte* src, +void copyAndFlipTexture( + std::uint8_t* dst, + const std::byte* src, const size_t dataLength, const size_t height) { assert( @@ -88,8 +87,8 @@ void copyAndFlipY( const size_t stride = dataLength / height; - for (size_t j = 0; j < height; ++j) { - memcpy(dst, src + (height - j) * stride, stride); + for (int32_t i = int32_t(height) - 1; i >= 0; --i) { + memcpy(dst, src + i * stride, stride); dst += stride; } } @@ -125,7 +124,7 @@ TextureLoader::loadTexture(const CesiumGltf::ImageAsset& image, bool sRGB) { if (image.mipPositions.empty()) { // No mipmaps, copy the whole thing and then let Unity generate mipmaps on a // worker thread. - copyAndFlipY( + copyAndFlipTexture( pixels, image.pixelData.data(), image.pixelData.size(), @@ -136,26 +135,27 @@ TextureLoader::loadTexture(const CesiumGltf::ImageAsset& image, bool sRGB) { std::uint8_t* pWritePosition = pixels; const std::byte* pReadBuffer = image.pixelData.data(); - // track square image dimension for each mip level - int32_t mipHeight = image.height; + // Track image height for each mip level + size_t mipHeight = image.height; for (const ImageAssetMipPosition& mip : image.mipPositions) { assert(mipHeight > 0 && "Invalid image size."); const size_t start = mip.byteOffset; const size_t end = mip.byteOffset + mip.byteSize; if (start >= textureLength || end > textureLength) { + // Invalid mip, skip this level. mipHeight /= 2; - continue; // invalid mip spec, ignore it + continue; } - copyAndFlipY( + copyAndFlipTexture( pWritePosition, pReadBuffer + start, mip.byteSize, mipHeight); pWritePosition += mip.byteSize; // adjust height for next mip level. - mipHeight /= 2; + mipHeight >>= 1; } result.Apply(false, true); diff --git a/native~/Runtime/src/UnityPrepareRendererResources.cpp b/native~/Runtime/src/UnityPrepareRendererResources.cpp index 617aeda8..78842918 100644 --- a/native~/Runtime/src/UnityPrepareRendererResources.cpp +++ b/native~/Runtime/src/UnityPrepareRendererResources.cpp @@ -606,7 +606,7 @@ void loadPrimitive( for (uint32_t texCoordIndex = 0; texCoordIndex < numTexCoords; ++texCoordIndex) { Vector2 texCoord = texCoordViews[texCoordIndex][vertexIndex]; - // flip Y to comply with Unity's left-handed UV coordinates + // Flip Y to comply with Unity's Y-up coordinate convention texCoord.y = 1 - texCoord.y; *reinterpret_cast(pWritePos) = texCoord; pWritePos += sizeof(Vector2); @@ -628,7 +628,7 @@ void loadPrimitive( for (uint32_t texCoordIndex = 0; texCoordIndex < numTexCoords; ++texCoordIndex) { Vector2 texCoord = texCoordViews[texCoordIndex][i]; - // flip Y to comply with Unity's left-handed UV coordinates + // Flip Y to comply with Unity's Y-up coordinate convention texCoord.y = 1 - texCoord.y; *reinterpret_cast(pWritePos) = texCoord; pWritePos += sizeof(Vector2); From 2dd2514f3ae963c91ca5ee38534c2f67a824c397 Mon Sep 17 00:00:00 2001 From: David Lively Date: Mon, 6 Oct 2025 12:26:56 -0500 Subject: [PATCH 09/13] Corrected a comment. --- native~/Runtime/src/UnityPrepareRendererResources.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/native~/Runtime/src/UnityPrepareRendererResources.cpp b/native~/Runtime/src/UnityPrepareRendererResources.cpp index 78842918..19f8d26e 100644 --- a/native~/Runtime/src/UnityPrepareRendererResources.cpp +++ b/native~/Runtime/src/UnityPrepareRendererResources.cpp @@ -606,7 +606,7 @@ void loadPrimitive( for (uint32_t texCoordIndex = 0; texCoordIndex < numTexCoords; ++texCoordIndex) { Vector2 texCoord = texCoordViews[texCoordIndex][vertexIndex]; - // Flip Y to comply with Unity's Y-up coordinate convention + // Flip Y to comply with Unity's V-up coordinate convention texCoord.y = 1 - texCoord.y; *reinterpret_cast(pWritePos) = texCoord; pWritePos += sizeof(Vector2); @@ -628,7 +628,7 @@ void loadPrimitive( for (uint32_t texCoordIndex = 0; texCoordIndex < numTexCoords; ++texCoordIndex) { Vector2 texCoord = texCoordViews[texCoordIndex][i]; - // Flip Y to comply with Unity's Y-up coordinate convention + // Flip Y to comply with Unity's V-up coordinate convention texCoord.y = 1 - texCoord.y; *reinterpret_cast(pWritePos) = texCoord; pWritePos += sizeof(Vector2); From b10469619d29c1f5a0e5a9d19efb7404b370a79b Mon Sep 17 00:00:00 2001 From: Janine Liu <32226860+j9liu@users.noreply.github.com> Date: Tue, 7 Oct 2025 15:24:38 -0400 Subject: [PATCH 10/13] Apply suggestions from code review --- CHANGES.md | 1 + native~/Runtime/src/TextureLoader.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 6cda75f4..0853ab2f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,7 @@ ## ? - ? ##### Fixes :wrench: + - Textures and UV coordinates from glTFs are now flipped to properly comply with Unity's U-right, V-up convention. ## v1.18.1 - 2025-10-01 diff --git a/native~/Runtime/src/TextureLoader.cpp b/native~/Runtime/src/TextureLoader.cpp index a938a9c9..c47e1f5f 100644 --- a/native~/Runtime/src/TextureLoader.cpp +++ b/native~/Runtime/src/TextureLoader.cpp @@ -77,8 +77,8 @@ getUncompressedPixelFormat(const CesiumGltf::ImageAsset& image) { * UnityPrepareRenderResources.cpp for the corresponding UV flip. **/ void copyAndFlipTexture( - std::uint8_t* dst, - const std::byte* src, + std::uint8_t* pDst, + const std::byte* pSrc, const size_t dataLength, const size_t height) { assert( @@ -88,8 +88,8 @@ void copyAndFlipTexture( const size_t stride = dataLength / height; for (int32_t i = int32_t(height) - 1; i >= 0; --i) { - memcpy(dst, src + i * stride, stride); - dst += stride; + memcpy(pDst, pSrc + i * stride, stride); + pDst += stride; } } @@ -144,7 +144,7 @@ TextureLoader::loadTexture(const CesiumGltf::ImageAsset& image, bool sRGB) { const size_t end = mip.byteOffset + mip.byteSize; if (start >= textureLength || end > textureLength) { // Invalid mip, skip this level. - mipHeight /= 2; + mipHeight >>= 1; continue; } From b08837cf567097ed0d120ae1906f11c9187dec63 Mon Sep 17 00:00:00 2001 From: David Lively Date: Wed, 8 Oct 2025 14:10:14 -0500 Subject: [PATCH 11/13] Modified mipmap loading to use generation to use ImageAssetMipPosition.rowPitch for the row stride when flipping textures. --- native~/Runtime/src/TextureLoader.cpp | 24 ++++++++---------------- native~/extern/cesium-native | 2 +- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/native~/Runtime/src/TextureLoader.cpp b/native~/Runtime/src/TextureLoader.cpp index c47e1f5f..fe02b8fd 100644 --- a/native~/Runtime/src/TextureLoader.cpp +++ b/native~/Runtime/src/TextureLoader.cpp @@ -80,14 +80,13 @@ void copyAndFlipTexture( std::uint8_t* pDst, const std::byte* pSrc, const size_t dataLength, - const size_t height) { + const size_t stride) { assert( - (dataLength % height) == 0 && - "Image data size is not an even multiple of image height."); + (dataLength % stride == 0) && + "Image data size is not an even multiple of the given row pitch."); - const size_t stride = dataLength / height; - - for (int32_t i = int32_t(height) - 1; i >= 0; --i) { + const int32_t height = static_cast(dataLength / stride); + for (int32_t i = height-1; i >= 0; --i) { memcpy(pDst, pSrc + i * stride, stride); pDst += stride; } @@ -124,38 +123,31 @@ TextureLoader::loadTexture(const CesiumGltf::ImageAsset& image, bool sRGB) { if (image.mipPositions.empty()) { // No mipmaps, copy the whole thing and then let Unity generate mipmaps on a // worker thread. + const size_t stride = image.pixelData.size() / image.height; copyAndFlipTexture( pixels, image.pixelData.data(), image.pixelData.size(), - image.height); + stride); result.Apply(false, true); } else { // Copy the mipmaps explicitly. std::uint8_t* pWritePosition = pixels; const std::byte* pReadBuffer = image.pixelData.data(); - // Track image height for each mip level - size_t mipHeight = image.height; - for (const ImageAssetMipPosition& mip : image.mipPositions) { - assert(mipHeight > 0 && "Invalid image size."); const size_t start = mip.byteOffset; const size_t end = mip.byteOffset + mip.byteSize; if (start >= textureLength || end > textureLength) { // Invalid mip, skip this level. - mipHeight >>= 1; continue; } - copyAndFlipTexture( pWritePosition, pReadBuffer + start, mip.byteSize, - mipHeight); + mip.rowPitch); pWritePosition += mip.byteSize; - // adjust height for next mip level. - mipHeight >>= 1; } result.Apply(false, true); diff --git a/native~/extern/cesium-native b/native~/extern/cesium-native index 9f6ae299..f4f7772f 160000 --- a/native~/extern/cesium-native +++ b/native~/extern/cesium-native @@ -1 +1 @@ -Subproject commit 9f6ae299e2709f866db52c4be29b6c31e10718c8 +Subproject commit f4f7772f487962ba494d9073b96c333bd2a6afb8 From 25f04b98caa7686a8231054b9bb23c2e3f017aef Mon Sep 17 00:00:00 2001 From: David Lively Date: Wed, 8 Oct 2025 14:12:37 -0500 Subject: [PATCH 12/13] Formatting. --- native~/Runtime/src/TextureLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native~/Runtime/src/TextureLoader.cpp b/native~/Runtime/src/TextureLoader.cpp index fe02b8fd..33281ce3 100644 --- a/native~/Runtime/src/TextureLoader.cpp +++ b/native~/Runtime/src/TextureLoader.cpp @@ -86,7 +86,7 @@ void copyAndFlipTexture( "Image data size is not an even multiple of the given row pitch."); const int32_t height = static_cast(dataLength / stride); - for (int32_t i = height-1; i >= 0; --i) { + for (int32_t i = height - 1; i >= 0; --i) { memcpy(pDst, pSrc + i * stride, stride); pDst += stride; } From 7bda9ee13c050ef31d55ad97728c249510a11bfe Mon Sep 17 00:00:00 2001 From: David Lively Date: Thu, 9 Oct 2025 10:40:46 -0500 Subject: [PATCH 13/13] Rebasing cesium-native dependency --- native~/extern/cesium-native | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native~/extern/cesium-native b/native~/extern/cesium-native index f4f7772f..00e16452 160000 --- a/native~/extern/cesium-native +++ b/native~/extern/cesium-native @@ -1 +1 @@ -Subproject commit f4f7772f487962ba494d9073b96c333bd2a6afb8 +Subproject commit 00e164521e9783284930bb4a067fa7b0b0ce4349