Compare commits
140 Commits
6a67c589f9
...
6ff8de351e
| Author | SHA1 | Date |
|---|---|---|
|
|
6ff8de351e | |
|
|
111429032d | |
|
|
3e68c7a1c2 | |
|
|
577ec52e8c | |
|
|
2bdeadac3d | |
|
|
e876c133c8 | |
|
|
e9a9415539 | |
|
|
d92188a276 | |
|
|
c5ea386972 | |
|
|
8b86d7f3d7 | |
|
|
3f372f75a4 | |
|
|
77715ec5e5 | |
|
|
198c22c795 | |
|
|
110382a8db | |
|
|
d9d31300d7 | |
|
|
65b6c866a0 | |
|
|
c96485f98c | |
|
|
22e9dbcd7c | |
|
|
f42203eb71 | |
|
|
ccba7b2510 | |
|
|
00c35a1ffc | |
|
|
221611fd21 | |
|
|
58e8bafe71 | |
|
|
eecc1e9411 | |
|
|
5f06bc153e | |
|
|
b23852cddd | |
|
|
d1bffc5d37 | |
|
|
1e9f39df84 | |
|
|
de6f08b7bc | |
|
|
b33640a9ff | |
|
|
0aaaee207e | |
|
|
25cc1e89ca | |
|
|
16be63a245 | |
|
|
097ca8c26a | |
|
|
54c22fddb5 | |
|
|
7734cff91c | |
|
|
90a24654f7 | |
|
|
8d9ee6fee6 | |
|
|
52e5736b4a | |
|
|
d3b0ccbeaa | |
|
|
30cc96901b | |
|
|
8c6f35b008 | |
|
|
12ee3f00b5 | |
|
|
3080d41edb | |
|
|
b800becaae | |
|
|
f66d9dacf6 | |
|
|
077e9f3765 | |
|
|
60faebd4d2 | |
|
|
b948b9cbfd | |
|
|
8df7a1f98d | |
|
|
c913278446 | |
|
|
0e53ac995d | |
|
|
a93b082380 | |
|
|
eaf77c07f1 | |
|
|
84a9574e7b | |
|
|
5e554d3638 | |
|
|
e390112e21 | |
|
|
97883d1451 | |
|
|
a72529e9cb | |
|
|
000d27cbb1 | |
|
|
d0427df530 | |
|
|
f6d83fb859 | |
|
|
34cc5236a4 | |
|
|
33d5640416 | |
|
|
9c41f33c83 | |
|
|
8d3d70a930 | |
|
|
62ef5734da | |
|
|
e4c0150a4d | |
|
|
614458ed9b | |
|
|
b40e3ecbc0 | |
|
|
f54db5f321 | |
|
|
fb0123673e | |
|
|
f245947101 | |
|
|
39c1ac8c62 | |
|
|
167a728aa0 | |
|
|
5d44fd4670 | |
|
|
d66de9af3b | |
|
|
9787c25d84 | |
|
|
c754a5fdec | |
|
|
cf18fd06b4 | |
|
|
fc68020535 | |
|
|
1cdb48a8da | |
|
|
5a28968283 | |
|
|
557f2b2898 | |
|
|
d5ca2caf9f | |
|
|
eef757a96f | |
|
|
956a3820a7 | |
|
|
fd85c8ed6a | |
|
|
fd19709464 | |
|
|
3b1b0f9e73 | |
|
|
de5ed6e7ba | |
|
|
733bc2c05d | |
|
|
99f1404fe7 | |
|
|
abf28c5ecc | |
|
|
1c13589457 | |
|
|
1ca38cd6e7 | |
|
|
99355d423e | |
|
|
50b1530722 | |
|
|
56f2dc8e8b | |
|
|
1aa2788d33 | |
|
|
6b45940fd5 | |
|
|
3f416be76d | |
|
|
9da2c9c8d9 | |
|
|
90d1c96818 | |
|
|
dc8ce97b1d | |
|
|
641e9f0b9e | |
|
|
8a72d9357a | |
|
|
cb2c5a1458 | |
|
|
2105e5b235 | |
|
|
0193409bc0 | |
|
|
b7330ea1b5 | |
|
|
a37c73e776 | |
|
|
6e43196dd0 | |
|
|
0d8ef62517 | |
|
|
01ef36e6ed | |
|
|
99ddaec2e0 | |
|
|
88c3716272 | |
|
|
1ff50143bc | |
|
|
1e1663bba7 | |
|
|
8329b52169 | |
|
|
a5e925c597 | |
|
|
f465fd9435 | |
|
|
d2f5d780ce | |
|
|
6efafe6bc9 | |
|
|
9258a5b79a | |
|
|
32dff5e051 | |
|
|
b6896cf807 | |
|
|
d687c267db | |
|
|
ca2f95b1ce | |
|
|
cf5cfe000a | |
|
|
fe8d2f0cea | |
|
|
852ba2ddaf | |
|
|
0ab8381d61 | |
|
|
c71c3263ca | |
|
|
22f50cefb5 | |
|
|
70185b6304 | |
|
|
7703c0c7fc | |
|
|
89263366e9 | |
|
|
2c830aa233 | |
|
|
d6e4d5d847 |
|
|
@ -217,3 +217,70 @@ jobs:
|
|||
run: |
|
||||
cd build
|
||||
ctest -V
|
||||
EmscriptenBuild:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version: [ "3.1.39", "4.0.13" ]
|
||||
memory: [ "32", "64" ]
|
||||
exclude:
|
||||
- version: "3.1.39"
|
||||
memory: "64"
|
||||
name: Emscripten v${{matrix.version}} ${{matrix.memory}}bit memory
|
||||
env:
|
||||
CACHE_KEY: "emscripten-${{matrix.version}}-${{matrix.memory}}"
|
||||
runs-on: windows-2022
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Use NodeJS 24 for WebAssembly 64-bit memory support
|
||||
if: ${{ matrix.memory == '64' }}
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '>=24'
|
||||
- name: Checkout vcpkg 2025.02.14 packages for use with Emscripten 3.1.39
|
||||
if: ${{ matrix.version == '3.1.39' }}
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: microsoft/vcpkg
|
||||
clean: false
|
||||
ref: 2025.02.14
|
||||
path: extern/vcpkg/temp
|
||||
sparse-checkout-cone-mode: false
|
||||
sparse-checkout: |
|
||||
ports/ada-url
|
||||
- name: Move overlay ports to the correct location
|
||||
if: ${{ matrix.version == '3.1.39' }}
|
||||
run: |
|
||||
mv extern/vcpkg/temp/ports/* extern/vcpkg/ports/
|
||||
- name: Add OpenSSL "no-dso" option on older Emscripten versions
|
||||
if: ${{ matrix.version == '3.1.39' }}
|
||||
run: |
|
||||
echo "
|
||||
if(PORT MATCHES "openssl")
|
||||
set(VCPKG_CONFIGURE_MAKE_OPTIONS "no-dso")
|
||||
endif()
|
||||
" >> extern/vcpkg/triplets/wasm32-emscripten-cesium.cmake
|
||||
- name: Install latest CMake 3 and Ninja
|
||||
uses: lukka/get-cmake@latest
|
||||
with:
|
||||
cmakeVersion: "3.31.6"
|
||||
- name: Install nasm
|
||||
uses: ilammy/setup-nasm@v1
|
||||
- name: Setup emsdk
|
||||
uses: mymindstorm/setup-emsdk@v14
|
||||
with:
|
||||
version: ${{matrix.version}}
|
||||
- name: Verify
|
||||
run: emcc -v
|
||||
- name: Compile Debug Configuration
|
||||
run: |
|
||||
$env:VCPKG_ROOT="$env:VCPKG_INSTALLATION_ROOT"
|
||||
$MEMORYPROPERTY="${{matrix.memory}}" -eq "64" ? "-DCESIUM_WASM64=ON" : ""
|
||||
emcmake cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug $MEMORYPROPERTY
|
||||
cmake --build build --config Debug --parallel
|
||||
- name: Test Debug Configuration
|
||||
run: |
|
||||
node build/CesiumNativeTests/cesium-native-tests.js
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
build
|
||||
build-*
|
||||
doxygen
|
||||
Testing
|
||||
node_modules
|
||||
|
|
@ -8,7 +9,5 @@ CMakeSettings.json
|
|||
.cache
|
||||
*.DS_Store
|
||||
test.db
|
||||
build-wsl
|
||||
.idea
|
||||
build-debug
|
||||
clang-tidy.log
|
||||
|
|
|
|||
11
CHANGES.md
11
CHANGES.md
|
|
@ -1,5 +1,11 @@
|
|||
# Change Log
|
||||
|
||||
### v0.54.0 - 2025-11-17
|
||||
|
||||
##### Additions :tada:
|
||||
|
||||
- Cesium Native can now be built with Emscripten.
|
||||
|
||||
### v0.53.0 - 2025-11-03
|
||||
|
||||
##### Breaking Changes :mega:
|
||||
|
|
@ -13,6 +19,11 @@
|
|||
- Added `Uri::ensureTrailingSlash`, which is helpful when the `Uri` represents a base URL.
|
||||
- Added `GltfModifier`, which can be used to modify tile glTFs as they load, as well as apply new modifications to them later.
|
||||
|
||||
##### Additions :tada:
|
||||
|
||||
- Added support for the `KHR_gaussian_splatting` extension.
|
||||
- SPZ payloads for `KHR_guassian_splatting` using the `KHR_gaussian_splatting_compression_spz_2` extension will now be decoded.
|
||||
|
||||
##### Fixes :wrench:
|
||||
|
||||
- Fixed a bug in `GoogleMapTilesRasterOverlay` that tried to parse credits from an erroneous viewport service response.
|
||||
|
|
|
|||
|
|
@ -4,6 +4,14 @@ if (NOT VCPKG_LIBRARY_LINKAGE)
|
|||
set(VCPKG_LIBRARY_LINKAGE static)
|
||||
endif()
|
||||
|
||||
get_filename_component(toolchainFile "${CMAKE_TOOLCHAIN_FILE}" NAME)
|
||||
if(toolchainFile STREQUAL "Emscripten.cmake")
|
||||
set(CESIUM_TARGET_WASM ON)
|
||||
# Include the toolchain directly as ezvcpkg will overwrite the
|
||||
# toolchain before it's loaded
|
||||
include(${CMAKE_TOOLCHAIN_FILE})
|
||||
endif()
|
||||
|
||||
# By default, Use ezvcpkg to install dependencies. But don't use
|
||||
# ezvcpkg if it appears that this configuration is using vcpkg
|
||||
# manifest mode already, either by building cesium-native directly,
|
||||
|
|
@ -24,6 +32,13 @@ endif()
|
|||
|
||||
option(CESIUM_USE_EZVCPKG "use ezvcpkg helper" ${CESIUM_USE_EZVCPKG_DEFAULT})
|
||||
option(CESIUM_DISABLE_CURL "Disable cesium-native's use of libcurl" OFF)
|
||||
option(CESIUM_DISABLE_LIBJPEG_TURBO "Disable cesium-native's use of libjpeg-turbo. JPEG images will be decoded with STB instead." OFF)
|
||||
option(CESIUM_WASM64 "Enable 64-bit WebAssembly target" OFF)
|
||||
|
||||
if (CESIUM_TARGET_WASM)
|
||||
# Make sure curl is disabled on wasm builds, as it is not supported.
|
||||
set(CESIUM_DISABLE_CURL ON)
|
||||
endif()
|
||||
|
||||
if(CESIUM_USE_EZVCPKG)
|
||||
# Keep vcpkg from running in manifset mode. It will try to because
|
||||
|
|
@ -50,6 +65,15 @@ if (NOT VCPKG_TRIPLET)
|
|||
elseif(DETECTED_VCPKG_TRIPLET STREQUAL "x64-windows")
|
||||
# cesium-native requires static linking on Windows
|
||||
set(VCPKG_TRIPLET "x64-windows-static-md")
|
||||
elseif(DETECTED_VCPKG_TRIPLET STREQUAL "wasm32-emscripten")
|
||||
# Use our custom triplet for wasm builds. Most importantly, this
|
||||
# enables multithreading support. Also switch to 64-bit wasm if
|
||||
# requested.
|
||||
if (CESIUM_WASM64)
|
||||
set(VCPKG_TRIPLET "wasm64-emscripten-cesium")
|
||||
else()
|
||||
set(VCPKG_TRIPLET "wasm32-emscripten-cesium")
|
||||
endif()
|
||||
else()
|
||||
set(VCPKG_TRIPLET "${DETECTED_VCPKG_TRIPLET}")
|
||||
endif()
|
||||
|
|
@ -87,6 +111,10 @@ if (NOT VCPKG_OVERLAY_TRIPLETS)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/extern/vcpkg/triplets")
|
||||
list(APPEND VCPKG_OVERLAY_TRIPLETS "${CMAKE_CURRENT_SOURCE_DIR}/extern/vcpkg/triplets")
|
||||
endif()
|
||||
|
||||
message(STATUS "VCPKG_OVERLAY_TRIPLETS ${VCPKG_OVERLAY_TRIPLETS}")
|
||||
|
||||
# These packages are used in the public headers of Cesium libraries, so we need to distribute the headers and binaries
|
||||
|
|
@ -98,13 +126,13 @@ set(PACKAGES_PUBLIC asyncplusplus expected-lite fmt glm rapidjson spdlog stb ada
|
|||
# to distribute the binaries for linking, but not the headers, as downstream consumers don't need them
|
||||
# OpenSSL and abseil are both dependencies of s2geometry
|
||||
set(PACKAGES_PRIVATE
|
||||
abseil draco ktx modp-base64 meshoptimizer openssl s2geometry
|
||||
libjpeg-turbo sqlite3 tinyxml2 libwebp zlib-ng picosha2
|
||||
earcut-hpp cpp-httplib[core] libmorton zstd
|
||||
abseil draco ktx[core] modp-base64 meshoptimizer openssl s2geometry
|
||||
sqlite3 tinyxml2 libwebp zlib-ng picosha2
|
||||
earcut-hpp libmorton zstd spz zlib
|
||||
)
|
||||
|
||||
# asmjit needed by blend2d on non-iOS platforms (iOS doesn't support JIT)
|
||||
if(NOT IOS AND NOT VCPKG_CMAKE_SYSTEM_NAME MATCHES "iOS")
|
||||
# asmjit needed by blend2d on non-iOS platforms (iOS and Wasm don't support JIT)
|
||||
if(NOT CESIUM_TARGET_WASM AND NOT IOS AND NOT VCPKG_CMAKE_SYSTEM_NAME MATCHES "iOS")
|
||||
list(APPEND PACKAGES_PRIVATE blend2d asmjit)
|
||||
else()
|
||||
# Use [core] feature to disable default jit feature.
|
||||
|
|
@ -115,16 +143,37 @@ if(NOT CESIUM_DISABLE_CURL)
|
|||
list(APPEND PACKAGES_PRIVATE curl)
|
||||
endif()
|
||||
|
||||
if(NOT CESIUM_DISABLE_LIBJPEG_TURBO)
|
||||
list(APPEND PACKAGES_PRIVATE libjpeg-turbo)
|
||||
endif()
|
||||
|
||||
# We use cpp-httplib to host a local web server for OAuth2 authorization. That's not
|
||||
# going to work at all on the web, and the latest versions of cpp-httplib only support
|
||||
# 64-bit platforms anyway, so skip it entirely for WebAssembly builds.
|
||||
if(NOT CESIUM_TARGET_WASM)
|
||||
list(APPEND PACKAGES_PRIVATE "cpp-httplib[core]")
|
||||
endif()
|
||||
|
||||
# Packages only used for testing
|
||||
set(PACKAGES_TEST doctest)
|
||||
|
||||
if(CESIUM_TARGET_WASM)
|
||||
# vcpkg will attempt to second-guess our CMAKE_C_COMPILER setting, choosing to go with the value of CC instead.
|
||||
# While normally this is the correct value to go with, for wasm we need to be using emcc and em++.
|
||||
# So we set CC and CXX to emcc and em++ here so vcpkg will pick them up properly.
|
||||
# Does this make sense? No. Does it work? Somehow. ¯\_(ツ)_/¯
|
||||
set(ENV{CC} ${CMAKE_C_COMPILER})
|
||||
set(ENV{CXX} ${CMAKE_CXX_COMPILER})
|
||||
endif()
|
||||
|
||||
if(CESIUM_USE_EZVCPKG)
|
||||
set(PACKAGES_ALL ${PACKAGES_PUBLIC})
|
||||
list(APPEND PACKAGES_ALL ${PACKAGES_PRIVATE})
|
||||
list(APPEND PACKAGES_ALL ${PACKAGES_TEST})
|
||||
|
||||
ezvcpkg_fetch(
|
||||
COMMIT 2025.09.17
|
||||
COMMIT afc0a2e01ae104a2474216a2df0e8d78516fd5af
|
||||
REPO microsoft/vcpkg
|
||||
PACKAGES ${PACKAGES_ALL}
|
||||
# Clean the build trees after building, so that we don't use a ton a disk space on the CI cache
|
||||
CLEAN_BUILDTREES
|
||||
|
|
@ -145,10 +194,20 @@ endif()
|
|||
include("cmake/defaults.cmake")
|
||||
|
||||
project(cesium-native
|
||||
VERSION 0.53.0
|
||||
VERSION 0.54.0
|
||||
LANGUAGES CXX C
|
||||
)
|
||||
|
||||
if(CESIUM_TARGET_WASM)
|
||||
if(CESIUM_WASM64)
|
||||
set(CMAKE_SIZEOF_VOID_P 8)
|
||||
else()
|
||||
set(CMAKE_SIZEOF_VOID_P 4)
|
||||
endif()
|
||||
# Tells emscripten to output an HTML harness for the generated WASM
|
||||
set(CMAKE_EXECUTABLE_SUFFIX ".html")
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(CMakeDependentOption)
|
||||
|
||||
|
|
@ -318,21 +377,20 @@ find_package(doctest CONFIG REQUIRED)
|
|||
find_package(draco CONFIG REQUIRED)
|
||||
find_package(expected-lite CONFIG REQUIRED)
|
||||
find_package(glm CONFIG REQUIRED)
|
||||
find_package(httplib CONFIG REQUIRED)
|
||||
find_package(Ktx CONFIG REQUIRED)
|
||||
find_package(libjpeg-turbo CONFIG REQUIRED)
|
||||
find_package(libmorton CONFIG REQUIRED)
|
||||
find_package(meshoptimizer CONFIG REQUIRED)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
find_package(s2 CONFIG REQUIRED)
|
||||
find_package(spdlog CONFIG REQUIRED)
|
||||
find_package(spz CONFIG REQUIRED)
|
||||
find_package(tinyxml2 CONFIG REQUIRED)
|
||||
find_package(unofficial-sqlite3 CONFIG REQUIRED)
|
||||
find_package(WebP CONFIG REQUIRED)
|
||||
find_package(zlib-ng CONFIG REQUIRED)
|
||||
|
||||
# asmjit should not be included with iOS builds as iOS doesn't support JIT compilation.
|
||||
if(NOT IOS AND NOT VCPKG_CMAKE_SYSTEM_NAME MATCHES "iOS")
|
||||
# asmjit should not be included with iOS or Wasm builds as they don't support JIT compilation.
|
||||
if(NOT CESIUM_TARGET_WASM AND NOT IOS AND NOT VCPKG_CMAKE_SYSTEM_NAME MATCHES "iOS")
|
||||
find_package(asmjit CONFIG REQUIRED)
|
||||
endif()
|
||||
|
||||
|
|
@ -340,6 +398,14 @@ if(NOT CESIUM_DISABLE_CURL)
|
|||
find_package(CURL REQUIRED)
|
||||
endif()
|
||||
|
||||
if(NOT CESIUM_DISABLE_LIBJPEG_TURBO)
|
||||
find_package(libjpeg-turbo CONFIG REQUIRED)
|
||||
endif()
|
||||
|
||||
if(NOT CESIUM_TARGET_WASM)
|
||||
find_package(httplib CONFIG REQUIRED)
|
||||
endif()
|
||||
|
||||
# Private Library (s2geometry)
|
||||
add_subdirectory(extern EXCLUDE_FROM_ALL)
|
||||
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ public:
|
|||
bool isContentAvailable(
|
||||
const CesiumGeometry::QuadtreeTileID& subtreeId,
|
||||
const CesiumGeometry::QuadtreeTileID& tileId,
|
||||
uint64_t contentId) const noexcept;
|
||||
size_t contentId) const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Determines if content for a given tile in the octree is available.
|
||||
|
|
@ -247,7 +247,7 @@ public:
|
|||
bool isContentAvailable(
|
||||
const CesiumGeometry::OctreeTileID& subtreeId,
|
||||
const CesiumGeometry::OctreeTileID& tileId,
|
||||
uint64_t contentId) const noexcept;
|
||||
size_t contentId) const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Determines if content for a given tile in the subtree is available.
|
||||
|
|
@ -262,7 +262,7 @@ public:
|
|||
bool isContentAvailable(
|
||||
uint32_t relativeTileLevel,
|
||||
uint64_t relativeTileMortonId,
|
||||
uint64_t contentId) const noexcept;
|
||||
size_t contentId) const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Sets the availability state of the content for a given tile in the
|
||||
|
|
@ -276,7 +276,7 @@ public:
|
|||
void setContentAvailable(
|
||||
const CesiumGeometry::QuadtreeTileID& subtreeId,
|
||||
const CesiumGeometry::QuadtreeTileID& tileId,
|
||||
uint64_t contentId,
|
||||
size_t contentId,
|
||||
bool isAvailable) noexcept;
|
||||
|
||||
/**
|
||||
|
|
@ -291,7 +291,7 @@ public:
|
|||
void setContentAvailable(
|
||||
const CesiumGeometry::OctreeTileID& subtreeId,
|
||||
const CesiumGeometry::OctreeTileID& tileId,
|
||||
uint64_t contentId,
|
||||
size_t contentId,
|
||||
bool isAvailable) noexcept;
|
||||
|
||||
/**
|
||||
|
|
@ -309,7 +309,7 @@ public:
|
|||
void setContentAvailable(
|
||||
uint32_t relativeTileLevel,
|
||||
uint64_t relativeTileMortonId,
|
||||
uint64_t contentId,
|
||||
size_t contentId,
|
||||
bool isAvailable) noexcept;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1014,7 +1014,10 @@ void copyStringsToBuffers(
|
|||
for (const auto& str : arrayMember.GetArray()) {
|
||||
OffsetType byteLength = static_cast<OffsetType>(
|
||||
str.GetStringLength() * sizeof(rapidjson::Value::Ch));
|
||||
std::memcpy(valueBuffer.data() + offset, str.GetString(), byteLength);
|
||||
std::memcpy(
|
||||
valueBuffer.data() + offset,
|
||||
str.GetString(),
|
||||
size_t(byteLength));
|
||||
std::memcpy(
|
||||
offsetBuffer.data() + offsetIndex * sizeof(OffsetType),
|
||||
&offset,
|
||||
|
|
@ -1075,8 +1078,7 @@ void updateStringArrayProperty(
|
|||
++it;
|
||||
}
|
||||
|
||||
const uint64_t totalByteLength =
|
||||
totalCharCount * sizeof(rapidjson::Value::Ch);
|
||||
const size_t totalByteLength = totalCharCount * sizeof(rapidjson::Value::Ch);
|
||||
std::vector<std::byte> valueBuffer;
|
||||
std::vector<std::byte> stringOffsetBuffer;
|
||||
PropertyComponentType stringOffsetType = PropertyComponentType::None;
|
||||
|
|
|
|||
|
|
@ -823,7 +823,7 @@ void decodeDracoMetadata(
|
|||
const std::unique_ptr<draco::PointCloud>& pPointCloud,
|
||||
rapidjson::Document& batchTableJson,
|
||||
PntsContent& parsedContent) {
|
||||
const uint64_t pointsLength = parsedContent.pointsLength;
|
||||
const size_t pointsLength = parsedContent.pointsLength;
|
||||
std::vector<std::byte>& data = parsedContent.dracoBatchTableBinary;
|
||||
|
||||
const auto& dracoMetadataSemantics = parsedContent.dracoMetadataSemantics;
|
||||
|
|
|
|||
|
|
@ -281,7 +281,7 @@ void SubtreeAvailability::setTileAvailable(
|
|||
bool SubtreeAvailability::isContentAvailable(
|
||||
const CesiumGeometry::QuadtreeTileID& subtreeId,
|
||||
const CesiumGeometry::QuadtreeTileID& tileId,
|
||||
uint64_t contentId) const noexcept {
|
||||
size_t contentId) const noexcept {
|
||||
uint64_t relativeTileMortonIdx =
|
||||
ImplicitTilingUtilities::computeRelativeMortonIndex(subtreeId, tileId);
|
||||
return this->isContentAvailable(
|
||||
|
|
@ -293,7 +293,7 @@ bool SubtreeAvailability::isContentAvailable(
|
|||
bool SubtreeAvailability::isContentAvailable(
|
||||
const CesiumGeometry::OctreeTileID& subtreeId,
|
||||
const CesiumGeometry::OctreeTileID& tileId,
|
||||
uint64_t contentId) const noexcept {
|
||||
size_t contentId) const noexcept {
|
||||
uint64_t relativeTileMortonIdx =
|
||||
ImplicitTilingUtilities::computeRelativeMortonIndex(subtreeId, tileId);
|
||||
return this->isContentAvailable(
|
||||
|
|
@ -305,7 +305,7 @@ bool SubtreeAvailability::isContentAvailable(
|
|||
bool SubtreeAvailability::isContentAvailable(
|
||||
uint32_t relativeTileLevel,
|
||||
uint64_t relativeTileMortonId,
|
||||
uint64_t contentId) const noexcept {
|
||||
size_t contentId) const noexcept {
|
||||
if (contentId >= this->_contentAvailability.size())
|
||||
return false;
|
||||
return isAvailable(
|
||||
|
|
@ -317,7 +317,7 @@ bool SubtreeAvailability::isContentAvailable(
|
|||
void SubtreeAvailability::setContentAvailable(
|
||||
const CesiumGeometry::QuadtreeTileID& subtreeId,
|
||||
const CesiumGeometry::QuadtreeTileID& tileId,
|
||||
uint64_t contentId,
|
||||
size_t contentId,
|
||||
bool isAvailable) noexcept {
|
||||
uint64_t relativeTileMortonIdx =
|
||||
ImplicitTilingUtilities::computeRelativeMortonIndex(subtreeId, tileId);
|
||||
|
|
@ -331,7 +331,7 @@ void SubtreeAvailability::setContentAvailable(
|
|||
void SubtreeAvailability::setContentAvailable(
|
||||
const CesiumGeometry::OctreeTileID& subtreeId,
|
||||
const CesiumGeometry::OctreeTileID& tileId,
|
||||
uint64_t contentId,
|
||||
size_t contentId,
|
||||
bool isAvailable) noexcept {
|
||||
uint64_t relativeTileMortonIdx =
|
||||
ImplicitTilingUtilities::computeRelativeMortonIndex(subtreeId, tileId);
|
||||
|
|
@ -345,7 +345,7 @@ void SubtreeAvailability::setContentAvailable(
|
|||
void SubtreeAvailability::setContentAvailable(
|
||||
uint32_t relativeTileLevel,
|
||||
uint64_t relativeTileMortonId,
|
||||
uint64_t contentId,
|
||||
size_t contentId,
|
||||
bool isAvailable) noexcept {
|
||||
if (contentId < this->_contentAvailability.size()) {
|
||||
this->setAvailable(
|
||||
|
|
@ -518,7 +518,7 @@ bool SubtreeAvailability::isAvailableUsingBufferView(
|
|||
const SubtreeBufferViewAvailability* bufferViewAvailability =
|
||||
std::get_if<SubtreeBufferViewAvailability>(&availabilityView);
|
||||
|
||||
const uint64_t byteIndex = availabilityBitIndex / 8;
|
||||
const size_t byteIndex = size_t(availabilityBitIndex / 8);
|
||||
if (byteIndex >= bufferViewAvailability->view.size()) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -541,7 +541,7 @@ void SubtreeAvailability::setAvailableUsingBufferView(
|
|||
const SubtreeBufferViewAvailability* pBufferViewAvailability =
|
||||
std::get_if<SubtreeBufferViewAvailability>(&availabilityView);
|
||||
|
||||
const uint64_t byteIndex = availabilityBitIndex / 8;
|
||||
const size_t byteIndex = size_t(availabilityBitIndex / 8);
|
||||
if (byteIndex >= pBufferViewAvailability->view.size()) {
|
||||
// Attempting to set an invalid tile. Assert, but otherwise ignore it.
|
||||
CESIUM_ASSERT(false);
|
||||
|
|
|
|||
|
|
@ -67,8 +67,8 @@ void markTileAvailableForQuadtree(
|
|||
uint64_t availabilityBitIndex =
|
||||
numOfTilesFromRootToParentLevel +
|
||||
libmorton::morton2D_64_encode(tileID.x, tileID.y);
|
||||
const uint64_t byteIndex = availabilityBitIndex / 8;
|
||||
const uint64_t bitIndex = availabilityBitIndex % 8;
|
||||
const size_t byteIndex = size_t(availabilityBitIndex / 8);
|
||||
const size_t bitIndex = size_t(availabilityBitIndex % 8);
|
||||
available[byteIndex] |= std::byte(1 << bitIndex);
|
||||
}
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ void markSubtreeAvailableForQuadtree(
|
|||
libmorton::morton2D_64_encode(tileID.x, tileID.y);
|
||||
const uint64_t byteIndex = availabilityBitIndex / 8;
|
||||
const uint64_t bitIndex = availabilityBitIndex % 8;
|
||||
available[byteIndex] |= std::byte(1 << bitIndex);
|
||||
available[(size_t)byteIndex] |= std::byte(1 << bitIndex);
|
||||
}
|
||||
|
||||
using SubtreeContentInput =
|
||||
|
|
@ -140,17 +140,17 @@ SubtreeContent createSubtreeContent(
|
|||
: 0;
|
||||
|
||||
std::vector<std::byte> availabilityBuffer(
|
||||
bufferSize + bufferSize + subtreeBufferSize);
|
||||
size_t(bufferSize + bufferSize + subtreeBufferSize));
|
||||
|
||||
std::span<std::byte> contentAvailabilityBuffer(
|
||||
availabilityBuffer.data(),
|
||||
bufferSize);
|
||||
size_t(bufferSize));
|
||||
std::span<std::byte> tileAvailabilityBuffer(
|
||||
availabilityBuffer.data() + bufferSize,
|
||||
bufferSize);
|
||||
size_t(bufferSize));
|
||||
std::span<std::byte> subtreeAvailabilityBuffer(
|
||||
availabilityBuffer.data() + bufferSize + bufferSize,
|
||||
subtreeBufferSize);
|
||||
size_t(subtreeBufferSize));
|
||||
|
||||
SubtreeAvailability::AvailabilityView tileAvailability = std::visit(
|
||||
GetAvailabilityView{tileAvailabilityBuffer, false},
|
||||
|
|
@ -486,9 +486,9 @@ TEST_CASE("Test SubtreeAvailability methods") {
|
|||
subtree.bufferViews[1].buffer = 1;
|
||||
subtree.bufferViews[2].buffer = 2;
|
||||
|
||||
contentAvailabilityBuffer.resize(bufferSize);
|
||||
tileAvailabilityBuffer.resize(bufferSize);
|
||||
subtreeAvailabilityBuffer.resize(subtreeBufferSize);
|
||||
contentAvailabilityBuffer.resize(size_t(bufferSize));
|
||||
tileAvailabilityBuffer.resize(size_t(bufferSize));
|
||||
subtreeAvailabilityBuffer.resize(size_t(subtreeBufferSize));
|
||||
|
||||
subtree.buffers[0].byteLength = subtree.bufferViews[0].byteLength =
|
||||
int64_t(bufferSize);
|
||||
|
|
@ -622,18 +622,18 @@ TEST_CASE("Test parsing subtree format") {
|
|||
subtreeHeader.jsonByteLength = subtreeJsonBuffer.GetSize();
|
||||
subtreeHeader.binaryByteLength = subtreeBuffers.buffers.size();
|
||||
|
||||
std::vector<std::byte> buffer(
|
||||
std::vector<std::byte> buffer(size_t(
|
||||
sizeof(subtreeHeader) + subtreeHeader.jsonByteLength +
|
||||
subtreeHeader.binaryByteLength);
|
||||
subtreeHeader.binaryByteLength));
|
||||
std::memcpy(buffer.data(), &subtreeHeader, sizeof(subtreeHeader));
|
||||
std::memcpy(
|
||||
buffer.data() + sizeof(subtreeHeader),
|
||||
subtreeJsonBuffer.GetString(),
|
||||
subtreeHeader.jsonByteLength);
|
||||
size_t(subtreeHeader.jsonByteLength));
|
||||
std::memcpy(
|
||||
buffer.data() + sizeof(subtreeHeader) + subtreeHeader.jsonByteLength,
|
||||
subtreeBuffers.buffers.data(),
|
||||
subtreeHeader.binaryByteLength);
|
||||
size_t(subtreeHeader.binaryByteLength));
|
||||
|
||||
// mock the request
|
||||
auto pMockResponse = std::make_unique<SimpleAssetResponse>(
|
||||
|
|
@ -711,18 +711,18 @@ TEST_CASE("Test parsing subtree format") {
|
|||
subtreeHeader.jsonByteLength = subtreeJsonBuffer.GetSize();
|
||||
subtreeHeader.binaryByteLength = subtreeContent.buffers.size();
|
||||
|
||||
std::vector<std::byte> buffer(
|
||||
std::vector<std::byte> buffer(size_t(
|
||||
sizeof(subtreeHeader) + subtreeHeader.jsonByteLength +
|
||||
subtreeHeader.binaryByteLength);
|
||||
subtreeHeader.binaryByteLength));
|
||||
std::memcpy(buffer.data(), &subtreeHeader, sizeof(subtreeHeader));
|
||||
std::memcpy(
|
||||
buffer.data() + sizeof(subtreeHeader),
|
||||
subtreeJsonBuffer.GetString(),
|
||||
subtreeHeader.jsonByteLength);
|
||||
size_t(subtreeHeader.jsonByteLength));
|
||||
std::memcpy(
|
||||
buffer.data() + sizeof(subtreeHeader) + subtreeHeader.jsonByteLength,
|
||||
subtreeContent.buffers.data(),
|
||||
subtreeHeader.binaryByteLength);
|
||||
size_t(subtreeHeader.binaryByteLength));
|
||||
|
||||
// mock the request
|
||||
auto pMockResponse = std::make_unique<SimpleAssetResponse>(
|
||||
|
|
@ -799,14 +799,14 @@ TEST_CASE("Test parsing subtree format") {
|
|||
subtreeHeader.jsonByteLength = subtreeJsonBuffer.GetSize();
|
||||
subtreeHeader.binaryByteLength = 0;
|
||||
|
||||
std::vector<std::byte> buffer(
|
||||
std::vector<std::byte> buffer(size_t(
|
||||
sizeof(subtreeHeader) + subtreeHeader.jsonByteLength +
|
||||
subtreeHeader.binaryByteLength);
|
||||
subtreeHeader.binaryByteLength));
|
||||
std::memcpy(buffer.data(), &subtreeHeader, sizeof(subtreeHeader));
|
||||
std::memcpy(
|
||||
buffer.data() + sizeof(subtreeHeader),
|
||||
subtreeJsonBuffer.GetString(),
|
||||
subtreeHeader.jsonByteLength);
|
||||
size_t(subtreeHeader.jsonByteLength));
|
||||
|
||||
// mock the request
|
||||
auto pMockResponse = std::make_unique<SimpleAssetResponse>(
|
||||
|
|
|
|||
|
|
@ -165,12 +165,12 @@ Future<ReadJsonResult<Subtree>> SubtreeFileReader::loadBinary(
|
|||
}
|
||||
|
||||
ReadJsonResult<Subtree> result = this->_reader.readFromJson(
|
||||
data.subspan(sizeof(SubtreeHeader), header->jsonByteLength));
|
||||
data.subspan(sizeof(SubtreeHeader), size_t(header->jsonByteLength)));
|
||||
|
||||
if (result.value) {
|
||||
std::span<const std::byte> binaryChunk = data.subspan(
|
||||
sizeof(SubtreeHeader) + header->jsonByteLength,
|
||||
header->binaryByteLength);
|
||||
sizeof(SubtreeHeader) + size_t(header->jsonByteLength),
|
||||
size_t(header->binaryByteLength));
|
||||
|
||||
if (binaryChunk.size() > 0) {
|
||||
if (result.value->buffers.empty()) {
|
||||
|
|
@ -207,7 +207,7 @@ Future<ReadJsonResult<Subtree>> SubtreeFileReader::loadBinary(
|
|||
|
||||
buffer.cesium.data = std::vector<std::byte>(
|
||||
binaryChunk.begin(),
|
||||
binaryChunk.begin() + buffer.byteLength);
|
||||
binaryChunk.begin() + ptrdiff_t(buffer.byteLength));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ target_link_libraries(Cesium3DTilesSelection
|
|||
CesiumQuantizedMeshTerrain
|
||||
CesiumRasterOverlays
|
||||
CesiumUtility
|
||||
spdlog::spdlog spdlog::spdlog_header_only
|
||||
spdlog::spdlog
|
||||
# PRIVATE
|
||||
libmorton::libmorton
|
||||
draco::draco
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ cesium_target_include_directories(
|
|||
target_link_libraries(CesiumAsync
|
||||
PUBLIC
|
||||
CesiumUtility
|
||||
spdlog::spdlog spdlog::spdlog_header_only
|
||||
spdlog::spdlog
|
||||
Async++
|
||||
PRIVATE
|
||||
unofficial::sqlite3::sqlite3
|
||||
|
|
|
|||
|
|
@ -44,6 +44,12 @@ target_link_libraries(CesiumClientCommon
|
|||
PRIVATE
|
||||
picosha2::picosha2
|
||||
modp_b64::modp_b64
|
||||
httplib::httplib
|
||||
OpenSSL::Crypto
|
||||
)
|
||||
|
||||
if (NOT CESIUM_TARGET_WASM)
|
||||
target_link_libraries(CesiumClientCommon
|
||||
PRIVATE
|
||||
httplib::httplib
|
||||
)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
#include <CesiumUtility/joinToString.h>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <httplib.h>
|
||||
#include <modp_b64.h>
|
||||
#include <rapidjson/document.h>
|
||||
#include <rapidjson/error/en.h>
|
||||
|
|
@ -34,6 +33,13 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
// Using httplib for the internal HTTP server to receive the OAuth2 redirect URI
|
||||
// is certainly not going to work on the web. And cpp-httplib only supports
|
||||
// 64-bit platforms, so we can't even build it for 32-bit emscripten targets.
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#include <httplib.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4244)
|
||||
|
|
@ -59,6 +65,7 @@ using namespace CesiumUtility;
|
|||
namespace CesiumClientCommon {
|
||||
|
||||
namespace {
|
||||
#ifndef __EMSCRIPTEN__
|
||||
std::string encodeBase64(const std::vector<uint8_t>& bytes) {
|
||||
const size_t count = modp_b64_encode_len(bytes.size());
|
||||
std::string result(count, 0);
|
||||
|
|
@ -72,7 +79,7 @@ std::string encodeBase64(const std::vector<uint8_t>& bytes) {
|
|||
// in [RFC7636 Appendix A](https://tools.ietf.org/html/rfc7636#appendix-A)
|
||||
const size_t firstPaddingIndex = result.find('=');
|
||||
if (firstPaddingIndex != std::string::npos) {
|
||||
result.erase(result.begin() + int64_t(firstPaddingIndex), result.end());
|
||||
result.erase(result.begin() + ptrdiff_t(firstPaddingIndex), result.end());
|
||||
}
|
||||
std::replace(result.begin(), result.end(), '+', '-');
|
||||
std::replace(result.begin(), result.end(), '/', '_');
|
||||
|
|
@ -170,17 +177,28 @@ std::string createAuthorizationErrorHtml(
|
|||
exception.what(),
|
||||
applicationName);
|
||||
}
|
||||
#endif // #ifndef __EMSCRIPTEN__
|
||||
} // namespace
|
||||
|
||||
CesiumAsync::Future<Result<OAuth2TokenResponse>> OAuth2PKCE::authorize(
|
||||
const CesiumAsync::AsyncSystem& asyncSystem,
|
||||
const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor,
|
||||
const std::string& friendlyApplicationName,
|
||||
const OAuth2ClientOptions& clientOptions,
|
||||
const std::vector<std::string>& scopes,
|
||||
std::function<void(const std::string&)>&& openUrlCallback,
|
||||
const std::string& tokenEndpointUrl,
|
||||
const std::string& authorizeBaseUrl) {
|
||||
[[maybe_unused]] const std::shared_ptr<CesiumAsync::IAssetAccessor>&
|
||||
pAssetAccessor,
|
||||
[[maybe_unused]] const std::string& friendlyApplicationName,
|
||||
[[maybe_unused]] const OAuth2ClientOptions& clientOptions,
|
||||
[[maybe_unused]] const std::vector<std::string>& scopes,
|
||||
[[maybe_unused]] std::function<void(const std::string&)>&& openUrlCallback,
|
||||
[[maybe_unused]] const std::string& tokenEndpointUrl,
|
||||
[[maybe_unused]] const std::string& authorizeBaseUrl) {
|
||||
#ifdef __EMSCRIPTEN__
|
||||
// Currently we just fail the authorization attempt in Emscripten / web
|
||||
// builds. In theory, we can do a more web-oriented authorization flow here
|
||||
// instead.
|
||||
return asyncSystem.createResolvedFuture<Result<OAuth2TokenResponse>>(
|
||||
Result<OAuth2TokenResponse>(
|
||||
ErrorList::error("OAuth2 PKCE authorization is not supported in "
|
||||
"Emscripten / WebAssembly builds.")));
|
||||
#else // #ifdef __EMSCRIPTEN__
|
||||
auto promise = asyncSystem.createPromise<Result<OAuth2TokenResponse>>();
|
||||
|
||||
std::shared_ptr<httplib::Server> pServer =
|
||||
|
|
@ -332,6 +350,7 @@ CesiumAsync::Future<Result<OAuth2TokenResponse>> OAuth2PKCE::authorize(
|
|||
openUrlCallback(authorizeUrl);
|
||||
|
||||
return promise.getFuture();
|
||||
#endif // #ifdef __EMSCRIPTEN__ #else
|
||||
}
|
||||
|
||||
CesiumAsync::Future<Result<OAuth2TokenResponse>>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,121 @@
|
|||
// This file was generated by generate-classes.
|
||||
// DO NOT EDIT THIS FILE!
|
||||
#pragma once
|
||||
|
||||
#include <CesiumGltf/Library.h>
|
||||
#include <CesiumUtility/ExtensibleObject.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace CesiumGltf {
|
||||
/**
|
||||
* @brief Data defining a 3D Gaussian Splat primitive.
|
||||
*/
|
||||
struct CESIUMGLTF_API ExtensionKhrGaussianSplatting final
|
||||
: public CesiumUtility::ExtensibleObject {
|
||||
/**
|
||||
* @brief The original name of this type.
|
||||
*/
|
||||
static constexpr const char* TypeName = "ExtensionKhrGaussianSplatting";
|
||||
/** @brief The official name of the extension. This should be the same as its
|
||||
* key in the `extensions` object. */
|
||||
static constexpr const char* ExtensionName = "KHR_gaussian_splatting";
|
||||
|
||||
/**
|
||||
* @brief Known values for Optional property specifying how to project the
|
||||
* Gaussians to achieve a perspective correct value. This property defaults to
|
||||
* perspective.
|
||||
*/
|
||||
struct Projection {
|
||||
/** @brief `perspective` */
|
||||
inline static const std::string perspective = "perspective";
|
||||
|
||||
/** @brief `orthographic` */
|
||||
inline static const std::string orthographic = "orthographic";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Known values for Optional property specifying how to sort the
|
||||
* Gaussians during rendering. This property defaults to cameraDistance.
|
||||
*/
|
||||
struct SortingMethod {
|
||||
/** @brief `cameraDistance` */
|
||||
inline static const std::string cameraDistance = "cameraDistance";
|
||||
|
||||
/** @brief `zDepth` */
|
||||
inline static const std::string zDepth = "zDepth";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Known values for Optional property specifying the color space of the
|
||||
* spherical harmonics. This property defaults to BT.709.
|
||||
*/
|
||||
struct ColorSpace {
|
||||
/** @brief `BT.709` */
|
||||
inline static const std::string BT_709 = "BT.709";
|
||||
|
||||
/** @brief `BT.2020-ITU` */
|
||||
inline static const std::string BT_2020_ITU = "BT.2020-ITU";
|
||||
|
||||
/** @brief `BT.2020-HLG` */
|
||||
inline static const std::string BT_2020_HLG = "BT.2020-HLG";
|
||||
|
||||
/** @brief `BT.2020-PQ` */
|
||||
inline static const std::string BT_2020_PQ = "BT.2020-PQ";
|
||||
|
||||
/** @brief `Display-P3` */
|
||||
inline static const std::string Display_P3 = "Display-P3";
|
||||
|
||||
/** @brief `linear` */
|
||||
inline static const std::string linear = "linear";
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Optional property specifying parameters regarding the kernel used to
|
||||
* generate the Gaussians. This property defaults to ellipse.
|
||||
*/
|
||||
std::string kernel = "ellipse";
|
||||
|
||||
/**
|
||||
* @brief Optional property specifying how to project the Gaussians to achieve
|
||||
* a perspective correct value. This property defaults to perspective.
|
||||
*
|
||||
* Known values are defined in {@link Projection}.
|
||||
*
|
||||
*/
|
||||
std::string projection = Projection::perspective;
|
||||
|
||||
/**
|
||||
* @brief Optional property specifying how to sort the Gaussians during
|
||||
* rendering. This property defaults to cameraDistance.
|
||||
*
|
||||
* Known values are defined in {@link SortingMethod}.
|
||||
*
|
||||
*/
|
||||
std::string sortingMethod = SortingMethod::cameraDistance;
|
||||
|
||||
/**
|
||||
* @brief Optional property specifying the color space of the spherical
|
||||
* harmonics. This property defaults to BT.709.
|
||||
*
|
||||
* Known values are defined in {@link ColorSpace}.
|
||||
*
|
||||
*/
|
||||
std::string colorSpace = ColorSpace::BT_709;
|
||||
|
||||
/**
|
||||
* @brief Calculates the size in bytes of this object, including the contents
|
||||
* of all collections, pointers, and strings. This will NOT include the size
|
||||
* of any extensions attached to the object. Calling this method may be slow
|
||||
* as it requires traversing the object's entire structure.
|
||||
*/
|
||||
int64_t getSizeBytes() const {
|
||||
int64_t accum = 0;
|
||||
accum += int64_t(sizeof(ExtensionKhrGaussianSplatting));
|
||||
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
|
||||
int64_t(sizeof(CesiumUtility::ExtensibleObject));
|
||||
accum += int64_t(this->kernel.capacity() * sizeof(char));
|
||||
return accum;
|
||||
}
|
||||
};
|
||||
} // namespace CesiumGltf
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
// This file was generated by generate-classes.
|
||||
// DO NOT EDIT THIS FILE!
|
||||
#pragma once
|
||||
|
||||
#include <CesiumGltf/Library.h>
|
||||
#include <CesiumUtility/ExtensibleObject.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace CesiumGltf {
|
||||
/**
|
||||
* @brief Compressed data for SPZ v2 primitive.
|
||||
*/
|
||||
struct CESIUMGLTF_API ExtensionKhrGaussianSplattingCompressionSpz2 final
|
||||
: public CesiumUtility::ExtensibleObject {
|
||||
/**
|
||||
* @brief The original name of this type.
|
||||
*/
|
||||
static constexpr const char* TypeName =
|
||||
"ExtensionKhrGaussianSplattingCompressionSpz2";
|
||||
/** @brief The official name of the extension. This should be the same as its
|
||||
* key in the `extensions` object. */
|
||||
static constexpr const char* ExtensionName =
|
||||
"KHR_gaussian_splatting_compression_spz_2";
|
||||
|
||||
/**
|
||||
* @brief The index of the bufferView.
|
||||
*/
|
||||
int32_t bufferView = -1;
|
||||
|
||||
/**
|
||||
* @brief Calculates the size in bytes of this object, including the contents
|
||||
* of all collections, pointers, and strings. This will NOT include the size
|
||||
* of any extensions attached to the object. Calling this method may be slow
|
||||
* as it requires traversing the object's entire structure.
|
||||
*/
|
||||
int64_t getSizeBytes() const {
|
||||
int64_t accum = 0;
|
||||
accum += int64_t(sizeof(ExtensionKhrGaussianSplattingCompressionSpz2));
|
||||
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
|
||||
int64_t(sizeof(CesiumUtility::ExtensibleObject));
|
||||
|
||||
return accum;
|
||||
}
|
||||
};
|
||||
} // namespace CesiumGltf
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
// This file was generated by generate-classes.
|
||||
// DO NOT EDIT THIS FILE!
|
||||
#pragma once
|
||||
|
||||
#include <CesiumGltf/Library.h>
|
||||
#include <CesiumUtility/ExtensibleObject.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace CesiumGltf {
|
||||
/**
|
||||
* @brief Optional rendering hints for rendering the 3D Gaussian splats.
|
||||
* Renderers are free to ignore any of these.
|
||||
*/
|
||||
struct CESIUMGLTF_API ExtensionKhrGaussianSplattingHintsValue final
|
||||
: public CesiumUtility::ExtensibleObject {
|
||||
/**
|
||||
* @brief The original name of this type.
|
||||
*/
|
||||
static constexpr const char* TypeName =
|
||||
"ExtensionKhrGaussianSplattingHintsValue";
|
||||
|
||||
/**
|
||||
* @brief Provides a hint specifying how to project the Gaussians to achieve a
|
||||
* perspective correct value. This is a freeform field that defaults to
|
||||
* perspective. See the extension specification for further known types.
|
||||
*/
|
||||
std::string projection = "perspective";
|
||||
|
||||
/**
|
||||
* @brief Provides a hint specifying how to sort the Gaussians during
|
||||
* rendering. This is a freeform field defaulting to cameraDistance. See the
|
||||
* extension specification for further known types.
|
||||
*/
|
||||
std::string sortingMethod = "cameraDistance";
|
||||
|
||||
/**
|
||||
* @brief Calculates the size in bytes of this object, including the contents
|
||||
* of all collections, pointers, and strings. This will NOT include the size
|
||||
* of any extensions attached to the object. Calling this method may be slow
|
||||
* as it requires traversing the object's entire structure.
|
||||
*/
|
||||
int64_t getSizeBytes() const {
|
||||
int64_t accum = 0;
|
||||
accum += int64_t(sizeof(ExtensionKhrGaussianSplattingHintsValue));
|
||||
accum += CesiumUtility::ExtensibleObject::getSizeBytes() -
|
||||
int64_t(sizeof(CesiumUtility::ExtensibleObject));
|
||||
accum += int64_t(this->projection.capacity() * sizeof(char));
|
||||
accum += int64_t(this->sortingMethod.capacity() * sizeof(char));
|
||||
return accum;
|
||||
}
|
||||
};
|
||||
} // namespace CesiumGltf
|
||||
|
|
@ -22,7 +22,7 @@ struct CESIUMGLTF_API ExtensionTextureWebp final
|
|||
static constexpr const char* ExtensionName = "EXT_texture_webp";
|
||||
|
||||
/**
|
||||
* @brief The index of the images node which points to a WebP image.
|
||||
* @brief The index of the WebP image.
|
||||
*/
|
||||
int32_t source = -1;
|
||||
|
||||
|
|
|
|||
|
|
@ -2823,7 +2823,7 @@ private:
|
|||
}
|
||||
|
||||
uint64_t totalLength = stringOffsets.back();
|
||||
result.data.resize(totalLength);
|
||||
result.data.resize(size_t(totalLength));
|
||||
for (size_t i = 0; i < strings.size(); ++i) {
|
||||
std::memcpy(
|
||||
result.data.data() + stringOffsets[i],
|
||||
|
|
|
|||
|
|
@ -44,7 +44,12 @@
|
|||
#include <glm/ext/quaternion_double.hpp>
|
||||
#include <glm/ext/vector_float3.hpp>
|
||||
#include <glm/geometric.hpp>
|
||||
#include <glm/gtc/quaternion.hpp> // NOLINT(misc-include-cleaner)
|
||||
#include <glm/gtx/norm.hpp>
|
||||
// Despite what clang-tidy will say, we *do* actually need this include or we'll
|
||||
// get a "missing mat4_cast" error.
|
||||
// NOLINTNEXTLINE
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
|
@ -408,7 +413,7 @@ ErrorList Model::merge(Model&& rhs) {
|
|||
std::copy(
|
||||
pRhsDefaultScene->nodes.begin(),
|
||||
pRhsDefaultScene->nodes.end(),
|
||||
newScene.nodes.begin() + int64_t(originalNodeCount));
|
||||
newScene.nodes.begin() + ptrdiff_t(originalNodeCount));
|
||||
|
||||
// No need to update indices because they've already been updated when
|
||||
// we copied them from rhs to this.
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ template <typename T>
|
|||
PropertyViewStatusType checkOffsetsBuffer(
|
||||
const std::span<const std::byte>& offsetBuffer,
|
||||
size_t valueBufferSize,
|
||||
size_t instanceCount,
|
||||
uint64_t instanceCount,
|
||||
bool checkBitSize,
|
||||
PropertyViewStatusType offsetsNotSortedError,
|
||||
PropertyViewStatusType offsetOutOfBoundsError) noexcept {
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
|
|
@ -1158,8 +1159,8 @@ void deleteBufferRange(
|
|||
// Actually remove the bytes from the buffer.
|
||||
pBuffer->byteLength -= bytesToRemove;
|
||||
pBuffer->cesium.data.erase(
|
||||
pBuffer->cesium.data.begin() + start,
|
||||
pBuffer->cesium.data.begin() + end);
|
||||
pBuffer->cesium.data.begin() + ptrdiff_t(start),
|
||||
pBuffer->cesium.data.begin() + ptrdiff_t(end));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -62,6 +62,21 @@ target_link_libraries(CesiumGltfReader
|
|||
meshoptimizer::meshoptimizer
|
||||
modp_b64::modp_b64
|
||||
KTX::ktx
|
||||
WebP::webp WebP::webpdecoder
|
||||
$<IF:$<TARGET_EXISTS:libjpeg-turbo::turbojpeg>,libjpeg-turbo::turbojpeg,libjpeg-turbo::turbojpeg-static>
|
||||
spz::spz
|
||||
WebP::webp
|
||||
WebP::webpdecoder
|
||||
)
|
||||
|
||||
if(CESIUM_DISABLE_LIBJPEG_TURBO)
|
||||
target_compile_definitions(
|
||||
CesiumGltfReader
|
||||
PRIVATE
|
||||
CESIUM_DISABLE_LIBJPEG_TURBO
|
||||
)
|
||||
else()
|
||||
target_link_libraries(
|
||||
CesiumGltfReader
|
||||
PRIVATE
|
||||
$<IF:$<TARGET_EXISTS:libjpeg-turbo::turbojpeg>,libjpeg-turbo::turbojpeg,libjpeg-turbo::turbojpeg-static>
|
||||
)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
// This file was generated by generate-classes.
|
||||
// DO NOT EDIT THIS FILE!
|
||||
#pragma once
|
||||
|
||||
#include <CesiumGltf/ExtensionKhrGaussianSplattingCompressionSpz2.h>
|
||||
#include <CesiumGltfReader/Library.h>
|
||||
#include <CesiumJsonReader/JsonReader.h>
|
||||
#include <CesiumJsonReader/JsonReaderOptions.h>
|
||||
|
||||
#include <rapidjson/fwd.h>
|
||||
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
namespace CesiumGltf {
|
||||
struct ExtensionKhrGaussianSplattingCompressionSpz2;
|
||||
} // namespace CesiumGltf
|
||||
|
||||
namespace CesiumGltfReader {
|
||||
|
||||
/**
|
||||
* @brief Reads \ref CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2
|
||||
* "ExtensionKhrGaussianSplattingCompressionSpz2" instances from JSON.
|
||||
*/
|
||||
class CESIUMGLTFREADER_API ExtensionKhrGaussianSplattingCompressionSpz2Reader {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a new instance.
|
||||
*/
|
||||
ExtensionKhrGaussianSplattingCompressionSpz2Reader();
|
||||
|
||||
/**
|
||||
* @brief Gets the options controlling how the JSON is read.
|
||||
*/
|
||||
CesiumJsonReader::JsonReaderOptions& getOptions();
|
||||
|
||||
/**
|
||||
* @brief Gets the options controlling how the JSON is read.
|
||||
*/
|
||||
const CesiumJsonReader::JsonReaderOptions& getOptions() const;
|
||||
|
||||
/**
|
||||
* @brief Reads an instance of ExtensionKhrGaussianSplattingCompressionSpz2
|
||||
* from a byte buffer.
|
||||
*
|
||||
* @param data The buffer from which to read the instance.
|
||||
* @return The result of reading the instance.
|
||||
*/
|
||||
CesiumJsonReader::ReadJsonResult<
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2>
|
||||
readFromJson(const std::span<const std::byte>& data) const;
|
||||
|
||||
/**
|
||||
* @brief Reads an instance of ExtensionKhrGaussianSplattingCompressionSpz2
|
||||
* from a rapidJson::Value.
|
||||
*
|
||||
* @param value The value from which to read the instance.
|
||||
* @return The result of reading the instance.
|
||||
*/
|
||||
CesiumJsonReader::ReadJsonResult<
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2>
|
||||
readFromJson(const rapidjson::Value& value) const;
|
||||
|
||||
/**
|
||||
* @brief Reads an array of instances of
|
||||
* ExtensionKhrGaussianSplattingCompressionSpz2 from a rapidJson::Value.
|
||||
*
|
||||
* @param value The value from which to read the array of instances.
|
||||
* @return The result of reading the array of instances.
|
||||
*/
|
||||
CesiumJsonReader::ReadJsonResult<
|
||||
std::vector<CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2>>
|
||||
readArrayFromJson(const rapidjson::Value& value) const;
|
||||
|
||||
private:
|
||||
CesiumJsonReader::JsonReaderOptions _options;
|
||||
};
|
||||
|
||||
} // namespace CesiumGltfReader
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
// This file was generated by generate-classes.
|
||||
// DO NOT EDIT THIS FILE!
|
||||
#pragma once
|
||||
|
||||
#include <CesiumGltf/ExtensionKhrGaussianSplattingHintsValue.h>
|
||||
#include <CesiumGltfReader/Library.h>
|
||||
#include <CesiumJsonReader/JsonReader.h>
|
||||
#include <CesiumJsonReader/JsonReaderOptions.h>
|
||||
|
||||
#include <rapidjson/fwd.h>
|
||||
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
namespace CesiumGltf {
|
||||
struct ExtensionKhrGaussianSplattingHintsValue;
|
||||
} // namespace CesiumGltf
|
||||
|
||||
namespace CesiumGltfReader {
|
||||
|
||||
/**
|
||||
* @brief Reads \ref CesiumGltf::ExtensionKhrGaussianSplattingHintsValue
|
||||
* "ExtensionKhrGaussianSplattingHintsValue" instances from JSON.
|
||||
*/
|
||||
class CESIUMGLTFREADER_API ExtensionKhrGaussianSplattingHintsValueReader {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a new instance.
|
||||
*/
|
||||
ExtensionKhrGaussianSplattingHintsValueReader();
|
||||
|
||||
/**
|
||||
* @brief Gets the options controlling how the JSON is read.
|
||||
*/
|
||||
CesiumJsonReader::JsonReaderOptions& getOptions();
|
||||
|
||||
/**
|
||||
* @brief Gets the options controlling how the JSON is read.
|
||||
*/
|
||||
const CesiumJsonReader::JsonReaderOptions& getOptions() const;
|
||||
|
||||
/**
|
||||
* @brief Reads an instance of ExtensionKhrGaussianSplattingHintsValue from a
|
||||
* byte buffer.
|
||||
*
|
||||
* @param data The buffer from which to read the instance.
|
||||
* @return The result of reading the instance.
|
||||
*/
|
||||
CesiumJsonReader::ReadJsonResult<
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingHintsValue>
|
||||
readFromJson(const std::span<const std::byte>& data) const;
|
||||
|
||||
/**
|
||||
* @brief Reads an instance of ExtensionKhrGaussianSplattingHintsValue from a
|
||||
* rapidJson::Value.
|
||||
*
|
||||
* @param value The value from which to read the instance.
|
||||
* @return The result of reading the instance.
|
||||
*/
|
||||
CesiumJsonReader::ReadJsonResult<
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingHintsValue>
|
||||
readFromJson(const rapidjson::Value& value) const;
|
||||
|
||||
/**
|
||||
* @brief Reads an array of instances of
|
||||
* ExtensionKhrGaussianSplattingHintsValue from a rapidJson::Value.
|
||||
*
|
||||
* @param value The value from which to read the array of instances.
|
||||
* @return The result of reading the array of instances.
|
||||
*/
|
||||
CesiumJsonReader::ReadJsonResult<
|
||||
std::vector<CesiumGltf::ExtensionKhrGaussianSplattingHintsValue>>
|
||||
readArrayFromJson(const rapidjson::Value& value) const;
|
||||
|
||||
private:
|
||||
CesiumJsonReader::JsonReaderOptions _options;
|
||||
};
|
||||
|
||||
} // namespace CesiumGltfReader
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// This file was generated by generate-classes.
|
||||
// DO NOT EDIT THIS FILE!
|
||||
#pragma once
|
||||
|
||||
#include <CesiumGltf/ExtensionKhrGaussianSplatting.h>
|
||||
#include <CesiumGltfReader/Library.h>
|
||||
#include <CesiumJsonReader/JsonReader.h>
|
||||
#include <CesiumJsonReader/JsonReaderOptions.h>
|
||||
|
||||
#include <rapidjson/fwd.h>
|
||||
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
namespace CesiumGltf {
|
||||
struct ExtensionKhrGaussianSplatting;
|
||||
} // namespace CesiumGltf
|
||||
|
||||
namespace CesiumGltfReader {
|
||||
|
||||
/**
|
||||
* @brief Reads \ref CesiumGltf::ExtensionKhrGaussianSplatting
|
||||
* "ExtensionKhrGaussianSplatting" instances from JSON.
|
||||
*/
|
||||
class CESIUMGLTFREADER_API ExtensionKhrGaussianSplattingReader {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a new instance.
|
||||
*/
|
||||
ExtensionKhrGaussianSplattingReader();
|
||||
|
||||
/**
|
||||
* @brief Gets the options controlling how the JSON is read.
|
||||
*/
|
||||
CesiumJsonReader::JsonReaderOptions& getOptions();
|
||||
|
||||
/**
|
||||
* @brief Gets the options controlling how the JSON is read.
|
||||
*/
|
||||
const CesiumJsonReader::JsonReaderOptions& getOptions() const;
|
||||
|
||||
/**
|
||||
* @brief Reads an instance of ExtensionKhrGaussianSplatting from a byte
|
||||
* buffer.
|
||||
*
|
||||
* @param data The buffer from which to read the instance.
|
||||
* @return The result of reading the instance.
|
||||
*/
|
||||
CesiumJsonReader::ReadJsonResult<CesiumGltf::ExtensionKhrGaussianSplatting>
|
||||
readFromJson(const std::span<const std::byte>& data) const;
|
||||
|
||||
/**
|
||||
* @brief Reads an instance of ExtensionKhrGaussianSplatting from a
|
||||
* rapidJson::Value.
|
||||
*
|
||||
* @param value The value from which to read the instance.
|
||||
* @return The result of reading the instance.
|
||||
*/
|
||||
CesiumJsonReader::ReadJsonResult<CesiumGltf::ExtensionKhrGaussianSplatting>
|
||||
readFromJson(const rapidjson::Value& value) const;
|
||||
|
||||
/**
|
||||
* @brief Reads an array of instances of ExtensionKhrGaussianSplatting from a
|
||||
* rapidJson::Value.
|
||||
*
|
||||
* @param value The value from which to read the array of instances.
|
||||
* @return The result of reading the array of instances.
|
||||
*/
|
||||
CesiumJsonReader::ReadJsonResult<
|
||||
std::vector<CesiumGltf::ExtensionKhrGaussianSplatting>>
|
||||
readArrayFromJson(const rapidjson::Value& value) const;
|
||||
|
||||
private:
|
||||
CesiumJsonReader::JsonReaderOptions _options;
|
||||
};
|
||||
|
||||
} // namespace CesiumGltfReader
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
// This file was generated by generate-classes.
|
||||
// DO NOT EDIT THIS FILE!
|
||||
#pragma once
|
||||
|
||||
#include <CesiumGltf/ExtensionKhrGaussianSplattingCompressionSpz2.h>
|
||||
#include <CesiumJsonReader/ExtensibleObjectJsonHandler.h>
|
||||
#include <CesiumJsonReader/IntegerJsonHandler.h>
|
||||
|
||||
namespace CesiumJsonReader {
|
||||
class JsonReaderOptions;
|
||||
} // namespace CesiumJsonReader
|
||||
|
||||
namespace CesiumGltfReader {
|
||||
class ExtensionKhrGaussianSplattingCompressionSpz2JsonHandler
|
||||
: public CesiumJsonReader::ExtensibleObjectJsonHandler,
|
||||
public CesiumJsonReader::IExtensionJsonHandler {
|
||||
public:
|
||||
using ValueType = CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2;
|
||||
|
||||
static constexpr const char* ExtensionName =
|
||||
"KHR_gaussian_splatting_compression_spz_2";
|
||||
|
||||
explicit ExtensionKhrGaussianSplattingCompressionSpz2JsonHandler(
|
||||
const CesiumJsonReader::JsonReaderOptions& options) noexcept;
|
||||
void reset(
|
||||
IJsonHandler* pParentHandler,
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2* pObject);
|
||||
|
||||
IJsonHandler* readObjectKey(const std::string_view& str) override;
|
||||
|
||||
void reset(
|
||||
IJsonHandler* pParentHandler,
|
||||
CesiumUtility::ExtensibleObject& o,
|
||||
const std::string_view& extensionName) override;
|
||||
|
||||
IJsonHandler& getHandler() override { return *this; }
|
||||
|
||||
protected:
|
||||
IJsonHandler* readObjectKeyExtensionKhrGaussianSplattingCompressionSpz2(
|
||||
const std::string& objectType,
|
||||
const std::string_view& str,
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2& o);
|
||||
|
||||
private:
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2* _pObject = nullptr;
|
||||
CesiumJsonReader::IntegerJsonHandler<int32_t> _bufferView;
|
||||
};
|
||||
} // namespace CesiumGltfReader
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// This file was generated by generate-classes.
|
||||
// DO NOT EDIT THIS FILE!
|
||||
#pragma once
|
||||
|
||||
#include <CesiumGltf/ExtensionKhrGaussianSplattingHintsValue.h>
|
||||
#include <CesiumJsonReader/ExtensibleObjectJsonHandler.h>
|
||||
#include <CesiumJsonReader/StringJsonHandler.h>
|
||||
|
||||
namespace CesiumJsonReader {
|
||||
class JsonReaderOptions;
|
||||
} // namespace CesiumJsonReader
|
||||
|
||||
namespace CesiumGltfReader {
|
||||
class ExtensionKhrGaussianSplattingHintsValueJsonHandler
|
||||
: public CesiumJsonReader::ExtensibleObjectJsonHandler {
|
||||
public:
|
||||
using ValueType = CesiumGltf::ExtensionKhrGaussianSplattingHintsValue;
|
||||
|
||||
explicit ExtensionKhrGaussianSplattingHintsValueJsonHandler(
|
||||
const CesiumJsonReader::JsonReaderOptions& options) noexcept;
|
||||
void reset(
|
||||
IJsonHandler* pParentHandler,
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingHintsValue* pObject);
|
||||
|
||||
IJsonHandler* readObjectKey(const std::string_view& str) override;
|
||||
|
||||
protected:
|
||||
IJsonHandler* readObjectKeyExtensionKhrGaussianSplattingHintsValue(
|
||||
const std::string& objectType,
|
||||
const std::string_view& str,
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingHintsValue& o);
|
||||
|
||||
private:
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingHintsValue* _pObject = nullptr;
|
||||
CesiumJsonReader::StringJsonHandler _projection;
|
||||
CesiumJsonReader::StringJsonHandler _sortingMethod;
|
||||
};
|
||||
} // namespace CesiumGltfReader
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// This file was generated by generate-classes.
|
||||
// DO NOT EDIT THIS FILE!
|
||||
#pragma once
|
||||
|
||||
#include <CesiumGltf/ExtensionKhrGaussianSplatting.h>
|
||||
#include <CesiumJsonReader/ExtensibleObjectJsonHandler.h>
|
||||
#include <CesiumJsonReader/StringJsonHandler.h>
|
||||
|
||||
namespace CesiumJsonReader {
|
||||
class JsonReaderOptions;
|
||||
} // namespace CesiumJsonReader
|
||||
|
||||
namespace CesiumGltfReader {
|
||||
class ExtensionKhrGaussianSplattingJsonHandler
|
||||
: public CesiumJsonReader::ExtensibleObjectJsonHandler,
|
||||
public CesiumJsonReader::IExtensionJsonHandler {
|
||||
public:
|
||||
using ValueType = CesiumGltf::ExtensionKhrGaussianSplatting;
|
||||
|
||||
static constexpr const char* ExtensionName = "KHR_gaussian_splatting";
|
||||
|
||||
explicit ExtensionKhrGaussianSplattingJsonHandler(
|
||||
const CesiumJsonReader::JsonReaderOptions& options) noexcept;
|
||||
void reset(
|
||||
IJsonHandler* pParentHandler,
|
||||
CesiumGltf::ExtensionKhrGaussianSplatting* pObject);
|
||||
|
||||
IJsonHandler* readObjectKey(const std::string_view& str) override;
|
||||
|
||||
void reset(
|
||||
IJsonHandler* pParentHandler,
|
||||
CesiumUtility::ExtensibleObject& o,
|
||||
const std::string_view& extensionName) override;
|
||||
|
||||
IJsonHandler& getHandler() override { return *this; }
|
||||
|
||||
protected:
|
||||
IJsonHandler* readObjectKeyExtensionKhrGaussianSplatting(
|
||||
const std::string& objectType,
|
||||
const std::string_view& str,
|
||||
CesiumGltf::ExtensionKhrGaussianSplatting& o);
|
||||
|
||||
private:
|
||||
CesiumGltf::ExtensionKhrGaussianSplatting* _pObject = nullptr;
|
||||
CesiumJsonReader::StringJsonHandler _kernel;
|
||||
CesiumJsonReader::StringJsonHandler _projection;
|
||||
CesiumJsonReader::StringJsonHandler _sortingMethod;
|
||||
CesiumJsonReader::StringJsonHandler _colorSpace;
|
||||
};
|
||||
} // namespace CesiumGltfReader
|
||||
|
|
@ -2974,6 +2974,260 @@ ExtensionExtPrimitiveVoxelsReader::readArrayFromJson(
|
|||
return CesiumJsonReader::JsonReader::readJson(value, handler);
|
||||
}
|
||||
|
||||
} // namespace CesiumGltfReader
|
||||
// This file was generated by generate-classes.
|
||||
// DO NOT EDIT THIS FILE!
|
||||
// NOLINTBEGIN(readability-duplicate-include)
|
||||
#include "ExtensionKhrGaussianSplattingJsonHandler.h"
|
||||
#include "registerReaderExtensions.h"
|
||||
|
||||
#include <CesiumGltf/ExtensionKhrGaussianSplatting.h>
|
||||
#include <CesiumGltfReader/ExtensionKhrGaussianSplattingReader.h>
|
||||
#include <CesiumJsonReader/ArrayJsonHandler.h>
|
||||
#include <CesiumJsonReader/ExtensibleObjectJsonHandler.h>
|
||||
#include <CesiumJsonReader/IJsonHandler.h>
|
||||
#include <CesiumJsonReader/JsonReader.h>
|
||||
#include <CesiumUtility/Assert.h>
|
||||
#include <CesiumUtility/ExtensibleObject.h>
|
||||
|
||||
#include <rapidjson/document.h>
|
||||
|
||||
#include <any>
|
||||
#include <cstddef>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
// NOLINTEND(readability-duplicate-include)
|
||||
|
||||
namespace CesiumGltfReader {
|
||||
|
||||
ExtensionKhrGaussianSplattingJsonHandler::
|
||||
ExtensionKhrGaussianSplattingJsonHandler(
|
||||
const CesiumJsonReader::JsonReaderOptions& options) noexcept
|
||||
: CesiumJsonReader::ExtensibleObjectJsonHandler(options),
|
||||
_kernel(),
|
||||
_projection(),
|
||||
_sortingMethod(),
|
||||
_colorSpace() {}
|
||||
|
||||
void ExtensionKhrGaussianSplattingJsonHandler::reset(
|
||||
CesiumJsonReader::IJsonHandler* pParentHandler,
|
||||
CesiumGltf::ExtensionKhrGaussianSplatting* pObject) {
|
||||
CesiumJsonReader::ExtensibleObjectJsonHandler::reset(pParentHandler, pObject);
|
||||
this->_pObject = pObject;
|
||||
}
|
||||
|
||||
CesiumJsonReader::IJsonHandler*
|
||||
ExtensionKhrGaussianSplattingJsonHandler::readObjectKey(
|
||||
const std::string_view& str) {
|
||||
CESIUM_ASSERT(this->_pObject);
|
||||
return this->readObjectKeyExtensionKhrGaussianSplatting(
|
||||
CesiumGltf::ExtensionKhrGaussianSplatting::TypeName,
|
||||
str,
|
||||
*this->_pObject);
|
||||
}
|
||||
|
||||
void ExtensionKhrGaussianSplattingJsonHandler::reset(
|
||||
CesiumJsonReader::IJsonHandler* pParentHandler,
|
||||
CesiumUtility::ExtensibleObject& o,
|
||||
const std::string_view& extensionName) {
|
||||
std::any& value =
|
||||
o.extensions
|
||||
.emplace(extensionName, CesiumGltf::ExtensionKhrGaussianSplatting())
|
||||
.first->second;
|
||||
this->reset(
|
||||
pParentHandler,
|
||||
&std::any_cast<CesiumGltf::ExtensionKhrGaussianSplatting&>(value));
|
||||
}
|
||||
|
||||
CesiumJsonReader::IJsonHandler* ExtensionKhrGaussianSplattingJsonHandler::
|
||||
readObjectKeyExtensionKhrGaussianSplatting(
|
||||
const std::string& objectType,
|
||||
const std::string_view& str,
|
||||
CesiumGltf::ExtensionKhrGaussianSplatting& o) {
|
||||
using namespace std::string_literals;
|
||||
|
||||
if ("kernel"s == str) {
|
||||
return property("kernel", this->_kernel, o.kernel);
|
||||
}
|
||||
if ("projection"s == str) {
|
||||
return property("projection", this->_projection, o.projection);
|
||||
}
|
||||
if ("sortingMethod"s == str) {
|
||||
return property("sortingMethod", this->_sortingMethod, o.sortingMethod);
|
||||
}
|
||||
if ("colorSpace"s == str) {
|
||||
return property("colorSpace", this->_colorSpace, o.colorSpace);
|
||||
}
|
||||
|
||||
return this->readObjectKeyExtensibleObject(objectType, str, *this->_pObject);
|
||||
}
|
||||
|
||||
ExtensionKhrGaussianSplattingReader::ExtensionKhrGaussianSplattingReader() {
|
||||
registerReaderExtensions(this->_options);
|
||||
}
|
||||
|
||||
CesiumJsonReader::JsonReaderOptions&
|
||||
ExtensionKhrGaussianSplattingReader::getOptions() {
|
||||
return this->_options;
|
||||
}
|
||||
|
||||
const CesiumJsonReader::JsonReaderOptions&
|
||||
ExtensionKhrGaussianSplattingReader::getOptions() const {
|
||||
return this->_options;
|
||||
}
|
||||
|
||||
CesiumJsonReader::ReadJsonResult<CesiumGltf::ExtensionKhrGaussianSplatting>
|
||||
ExtensionKhrGaussianSplattingReader::readFromJson(
|
||||
const std::span<const std::byte>& data) const {
|
||||
ExtensionKhrGaussianSplattingJsonHandler handler(this->_options);
|
||||
return CesiumJsonReader::JsonReader::readJson(data, handler);
|
||||
}
|
||||
|
||||
CesiumJsonReader::ReadJsonResult<CesiumGltf::ExtensionKhrGaussianSplatting>
|
||||
ExtensionKhrGaussianSplattingReader::readFromJson(
|
||||
const rapidjson::Value& value) const {
|
||||
ExtensionKhrGaussianSplattingJsonHandler handler(this->_options);
|
||||
return CesiumJsonReader::JsonReader::readJson(value, handler);
|
||||
}
|
||||
|
||||
CesiumJsonReader::ReadJsonResult<
|
||||
std::vector<CesiumGltf::ExtensionKhrGaussianSplatting>>
|
||||
ExtensionKhrGaussianSplattingReader::readArrayFromJson(
|
||||
const rapidjson::Value& value) const {
|
||||
CesiumJsonReader::ArrayJsonHandler<
|
||||
CesiumGltf::ExtensionKhrGaussianSplatting,
|
||||
ExtensionKhrGaussianSplattingJsonHandler>
|
||||
handler(this->_options);
|
||||
return CesiumJsonReader::JsonReader::readJson(value, handler);
|
||||
}
|
||||
|
||||
} // namespace CesiumGltfReader
|
||||
// This file was generated by generate-classes.
|
||||
// DO NOT EDIT THIS FILE!
|
||||
// NOLINTBEGIN(readability-duplicate-include)
|
||||
#include "ExtensionKhrGaussianSplattingCompressionSpz2JsonHandler.h"
|
||||
#include "registerReaderExtensions.h"
|
||||
|
||||
#include <CesiumGltf/ExtensionKhrGaussianSplattingCompressionSpz2.h>
|
||||
#include <CesiumGltfReader/ExtensionKhrGaussianSplattingCompressionSpz2Reader.h>
|
||||
#include <CesiumJsonReader/ArrayJsonHandler.h>
|
||||
#include <CesiumJsonReader/ExtensibleObjectJsonHandler.h>
|
||||
#include <CesiumJsonReader/IJsonHandler.h>
|
||||
#include <CesiumJsonReader/JsonReader.h>
|
||||
#include <CesiumUtility/Assert.h>
|
||||
#include <CesiumUtility/ExtensibleObject.h>
|
||||
|
||||
#include <rapidjson/document.h>
|
||||
|
||||
#include <any>
|
||||
#include <cstddef>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
// NOLINTEND(readability-duplicate-include)
|
||||
|
||||
namespace CesiumGltfReader {
|
||||
|
||||
ExtensionKhrGaussianSplattingCompressionSpz2JsonHandler::
|
||||
ExtensionKhrGaussianSplattingCompressionSpz2JsonHandler(
|
||||
const CesiumJsonReader::JsonReaderOptions& options) noexcept
|
||||
: CesiumJsonReader::ExtensibleObjectJsonHandler(options), _bufferView() {}
|
||||
|
||||
void ExtensionKhrGaussianSplattingCompressionSpz2JsonHandler::reset(
|
||||
CesiumJsonReader::IJsonHandler* pParentHandler,
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2* pObject) {
|
||||
CesiumJsonReader::ExtensibleObjectJsonHandler::reset(pParentHandler, pObject);
|
||||
this->_pObject = pObject;
|
||||
}
|
||||
|
||||
CesiumJsonReader::IJsonHandler*
|
||||
ExtensionKhrGaussianSplattingCompressionSpz2JsonHandler::readObjectKey(
|
||||
const std::string_view& str) {
|
||||
CESIUM_ASSERT(this->_pObject);
|
||||
return this->readObjectKeyExtensionKhrGaussianSplattingCompressionSpz2(
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2::TypeName,
|
||||
str,
|
||||
*this->_pObject);
|
||||
}
|
||||
|
||||
void ExtensionKhrGaussianSplattingCompressionSpz2JsonHandler::reset(
|
||||
CesiumJsonReader::IJsonHandler* pParentHandler,
|
||||
CesiumUtility::ExtensibleObject& o,
|
||||
const std::string_view& extensionName) {
|
||||
std::any& value =
|
||||
o.extensions
|
||||
.emplace(
|
||||
extensionName,
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2())
|
||||
.first->second;
|
||||
this->reset(
|
||||
pParentHandler,
|
||||
&std::any_cast<CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2&>(
|
||||
value));
|
||||
}
|
||||
|
||||
CesiumJsonReader::IJsonHandler*
|
||||
ExtensionKhrGaussianSplattingCompressionSpz2JsonHandler::
|
||||
readObjectKeyExtensionKhrGaussianSplattingCompressionSpz2(
|
||||
const std::string& objectType,
|
||||
const std::string_view& str,
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2& o) {
|
||||
using namespace std::string_literals;
|
||||
|
||||
if ("bufferView"s == str) {
|
||||
return property("bufferView", this->_bufferView, o.bufferView);
|
||||
}
|
||||
|
||||
return this->readObjectKeyExtensibleObject(objectType, str, *this->_pObject);
|
||||
}
|
||||
|
||||
ExtensionKhrGaussianSplattingCompressionSpz2Reader::
|
||||
ExtensionKhrGaussianSplattingCompressionSpz2Reader() {
|
||||
registerReaderExtensions(this->_options);
|
||||
}
|
||||
|
||||
CesiumJsonReader::JsonReaderOptions&
|
||||
ExtensionKhrGaussianSplattingCompressionSpz2Reader::getOptions() {
|
||||
return this->_options;
|
||||
}
|
||||
|
||||
const CesiumJsonReader::JsonReaderOptions&
|
||||
ExtensionKhrGaussianSplattingCompressionSpz2Reader::getOptions() const {
|
||||
return this->_options;
|
||||
}
|
||||
|
||||
CesiumJsonReader::ReadJsonResult<
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2>
|
||||
ExtensionKhrGaussianSplattingCompressionSpz2Reader::readFromJson(
|
||||
const std::span<const std::byte>& data) const {
|
||||
ExtensionKhrGaussianSplattingCompressionSpz2JsonHandler handler(
|
||||
this->_options);
|
||||
return CesiumJsonReader::JsonReader::readJson(data, handler);
|
||||
}
|
||||
|
||||
CesiumJsonReader::ReadJsonResult<
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2>
|
||||
ExtensionKhrGaussianSplattingCompressionSpz2Reader::readFromJson(
|
||||
const rapidjson::Value& value) const {
|
||||
ExtensionKhrGaussianSplattingCompressionSpz2JsonHandler handler(
|
||||
this->_options);
|
||||
return CesiumJsonReader::JsonReader::readJson(value, handler);
|
||||
}
|
||||
|
||||
CesiumJsonReader::ReadJsonResult<
|
||||
std::vector<CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2>>
|
||||
ExtensionKhrGaussianSplattingCompressionSpz2Reader::readArrayFromJson(
|
||||
const rapidjson::Value& value) const {
|
||||
CesiumJsonReader::ArrayJsonHandler<
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2,
|
||||
ExtensionKhrGaussianSplattingCompressionSpz2JsonHandler>
|
||||
handler(this->_options);
|
||||
return CesiumJsonReader::JsonReader::readJson(value, handler);
|
||||
}
|
||||
|
||||
} // namespace CesiumGltfReader
|
||||
// This file was generated by generate-classes.
|
||||
// DO NOT EDIT THIS FILE!
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
#include "ExtensionExtPrimitiveVoxelsJsonHandler.h"
|
||||
#include "ExtensionExtStructuralMetadataJsonHandler.h"
|
||||
#include "ExtensionKhrDracoMeshCompressionJsonHandler.h"
|
||||
#include "ExtensionKhrGaussianSplattingCompressionSpz2JsonHandler.h"
|
||||
#include "ExtensionKhrGaussianSplattingJsonHandler.h"
|
||||
#include "ExtensionKhrImplicitShapesJsonHandler.h"
|
||||
#include "ExtensionKhrMaterialsUnlitJsonHandler.h"
|
||||
#include "ExtensionKhrTextureBasisuJsonHandler.h"
|
||||
|
|
@ -30,6 +32,7 @@
|
|||
|
||||
#include <CesiumGltf/Buffer.h>
|
||||
#include <CesiumGltf/BufferView.h>
|
||||
#include <CesiumGltf/ExtensionKhrGaussianSplatting.h>
|
||||
#include <CesiumGltf/FeatureIdTexture.h>
|
||||
#include <CesiumGltf/Material.h>
|
||||
#include <CesiumGltf/MaterialNormalTextureInfo.h>
|
||||
|
|
@ -81,6 +84,9 @@ void registerReaderExtensions(CesiumJsonReader::JsonReaderOptions& options) {
|
|||
options.registerExtension<
|
||||
CesiumGltf::MeshPrimitive,
|
||||
ExtensionExtPrimitiveVoxelsJsonHandler>();
|
||||
options.registerExtension<
|
||||
CesiumGltf::MeshPrimitive,
|
||||
ExtensionKhrGaussianSplattingJsonHandler>();
|
||||
options.registerExtension<
|
||||
CesiumGltf::Node,
|
||||
ExtensionExtInstanceFeaturesJsonHandler>();
|
||||
|
|
@ -132,5 +138,8 @@ void registerReaderExtensions(CesiumJsonReader::JsonReaderOptions& options) {
|
|||
options.registerExtension<
|
||||
CesiumGltf::Shape,
|
||||
ExtensionExtImplicitCylinderRegionJsonHandler>();
|
||||
options.registerExtension<
|
||||
CesiumGltf::ExtensionKhrGaussianSplatting,
|
||||
ExtensionKhrGaussianSplattingCompressionSpz2JsonHandler>();
|
||||
}
|
||||
} // namespace CesiumGltfReader
|
||||
|
|
|
|||
|
|
@ -89,6 +89,13 @@ struct CESIUMGLTFREADER_API GltfReaderOptions {
|
|||
*/
|
||||
bool decodeMeshOptData = true;
|
||||
|
||||
/**
|
||||
* @brief Whether gaussian splatting data are decompressed as part of the load
|
||||
* process, or left in the compressed format according to the
|
||||
* KHR_gaussian_splatting_compression_spz extension.
|
||||
*/
|
||||
bool decodeSpz = true;
|
||||
|
||||
/**
|
||||
* @brief Whether the quantized mesh data are dequantized and converted to
|
||||
* floating-point values when loading, according to the KHR_mesh_quantization
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "decodeDataUrls.h"
|
||||
#include "decodeDraco.h"
|
||||
#include "decodeMeshOpt.h"
|
||||
#include "decodeSpz.h"
|
||||
#include "dequantizeMeshData.h"
|
||||
#include "registerReaderExtensions.h"
|
||||
|
||||
|
|
@ -245,7 +246,7 @@ GltfReaderResult readBinaryGltf(
|
|||
|
||||
buffer.cesium.data = std::vector<std::byte>(
|
||||
binaryChunk.begin(),
|
||||
binaryChunk.begin() + buffer.byteLength);
|
||||
binaryChunk.begin() + (ptrdiff_t)buffer.byteLength);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -359,6 +360,10 @@ void postprocess(GltfReaderResult& readGltf, const GltfReaderOptions& options) {
|
|||
decodeMeshOpt(model, readGltf);
|
||||
}
|
||||
|
||||
if (options.decodeSpz && hasSpzExtension(readGltf)) {
|
||||
decodeSpz(readGltf);
|
||||
}
|
||||
|
||||
if (options.dequantizeMeshData &&
|
||||
std::find(
|
||||
model.extensionsUsed.begin(),
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
#include <CesiumUtility/Tracing.h>
|
||||
|
||||
#include <ktx.h>
|
||||
#include <turbojpeg.h>
|
||||
#include <webp/decode.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
|
@ -28,6 +27,10 @@
|
|||
#define STB_IMAGE_RESIZE_STATIC
|
||||
#include <stb_image_resize2.h>
|
||||
|
||||
#ifndef CESIUM_DISABLE_LIBJPEG_TURBO
|
||||
#include <turbojpeg.h>
|
||||
#endif
|
||||
|
||||
namespace CesiumGltfReader {
|
||||
|
||||
using namespace CesiumGltf;
|
||||
|
|
@ -287,6 +290,7 @@ ImageReaderResult ImageDecoder::readImage(
|
|||
}
|
||||
|
||||
{
|
||||
#ifndef CESIUM_DISABLE_LIBJPEG_TURBO
|
||||
tjhandle tjInstance = tjInitDecompress();
|
||||
int inSubsamp, inColorspace;
|
||||
if (!tjDecompressHeader3(
|
||||
|
|
@ -316,7 +320,9 @@ ImageReaderResult ImageDecoder::readImage(
|
|||
result.errors.emplace_back("Unable to decode JPEG");
|
||||
result.pImage = nullptr;
|
||||
}
|
||||
} else {
|
||||
} else
|
||||
#endif // !CESIUM_DISABLE_LIBJPEG_TURBO
|
||||
{
|
||||
CESIUM_TRACE("Decode PNG");
|
||||
image.bytesPerChannel = 1;
|
||||
image.channels = 4;
|
||||
|
|
@ -349,7 +355,9 @@ ImageReaderResult ImageDecoder::readImage(
|
|||
result.errors.emplace_back(stbi_failure_reason());
|
||||
}
|
||||
}
|
||||
#ifndef CESIUM_DISABLE_LIBJPEG_TURBO
|
||||
tjDestroy(tjInstance);
|
||||
#endif
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ std::unique_ptr<draco::Mesh> decodeBufferViewToDracoMesh(
|
|||
|
||||
const std::span<const std::byte> data(
|
||||
buffer.cesium.data.data() + bufferView.byteOffset,
|
||||
static_cast<uint64_t>(bufferView.byteLength));
|
||||
static_cast<size_t>(bufferView.byteLength));
|
||||
|
||||
draco::DecoderBuffer decodeBuffer;
|
||||
decodeBuffer.Init(reinterpret_cast<const char*>(data.data()), data.size());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,483 @@
|
|||
#include "decodeSpz.h"
|
||||
|
||||
#include <CesiumGltf/Accessor.h>
|
||||
#include <CesiumGltf/Buffer.h>
|
||||
#include <CesiumGltf/BufferView.h>
|
||||
#include <CesiumGltf/ExtensionKhrGaussianSplatting.h>
|
||||
#include <CesiumGltf/ExtensionKhrGaussianSplattingCompressionSpz2.h>
|
||||
#include <CesiumGltf/Mesh.h>
|
||||
#include <CesiumGltf/MeshPrimitive.h>
|
||||
#include <CesiumGltf/Model.h>
|
||||
#include <CesiumGltfReader/GltfReader.h>
|
||||
#include <CesiumUtility/Assert.h>
|
||||
#include <CesiumUtility/JsonValue.h>
|
||||
#include <CesiumUtility/Tracing.h>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <glm/fwd.hpp>
|
||||
#include <load-spz.h>
|
||||
#include <splat-types.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace CesiumGltfReader {
|
||||
namespace {
|
||||
|
||||
const float SH_C0 = 0.282095f;
|
||||
|
||||
const std::string ALTERNATE_EXT_NAME1 = "KHR_spz_gaussian_splats_compression";
|
||||
const std::string ALTERNATE_EXT_NAME2 =
|
||||
"KHR_gaussian_splatting_compression_spz";
|
||||
|
||||
std::unique_ptr<spz::GaussianCloud> decodeBufferViewToGaussianCloud(
|
||||
GltfReaderResult& readGltf,
|
||||
CesiumGltf::MeshPrimitive& /* primitive */,
|
||||
const CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2& spz) {
|
||||
CESIUM_TRACE("CesiumGltfReader::decodeBufferViewToGaussianCloud");
|
||||
CESIUM_ASSERT(readGltf.model);
|
||||
CesiumGltf::Model& model = readGltf.model.value();
|
||||
|
||||
CesiumGltf::BufferView* pBufferView =
|
||||
CesiumGltf::Model::getSafe(&model.bufferViews, spz.bufferView);
|
||||
if (!pBufferView) {
|
||||
readGltf.warnings.emplace_back("SPZ bufferView index is invalid.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const CesiumGltf::BufferView& bufferView = *pBufferView;
|
||||
|
||||
CesiumGltf::Buffer* pBuffer =
|
||||
CesiumGltf::Model::getSafe(&model.buffers, bufferView.buffer);
|
||||
if (!pBuffer) {
|
||||
readGltf.warnings.emplace_back(
|
||||
"SPZ bufferView has an invalid buffer index.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CesiumGltf::Buffer& buffer = *pBuffer;
|
||||
|
||||
if (bufferView.byteOffset < 0 || bufferView.byteLength < 0 ||
|
||||
bufferView.byteOffset + bufferView.byteLength >
|
||||
static_cast<int64_t>(buffer.cesium.data.size())) {
|
||||
readGltf.warnings.emplace_back("SPZ bufferView extends beyond its buffer.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
spz::GaussianCloud gaussians = spz::loadSpz(
|
||||
reinterpret_cast<uint8_t*>(
|
||||
buffer.cesium.data.data() + bufferView.byteOffset),
|
||||
static_cast<int32_t>(bufferView.byteLength),
|
||||
spz::UnpackOptions{spz::CoordinateSystem::UNSPECIFIED});
|
||||
|
||||
return std::make_unique<spz::GaussianCloud>(std::move(gaussians));
|
||||
}
|
||||
|
||||
CesiumGltf::Accessor* findAccessor(
|
||||
GltfReaderResult& readGltf,
|
||||
CesiumGltf::MeshPrimitive& primitive,
|
||||
const std::string& attributeName) {
|
||||
const std::unordered_map<std::string, int32_t>::iterator attributeIt =
|
||||
primitive.attributes.find(attributeName);
|
||||
if (attributeIt == primitive.attributes.end()) {
|
||||
readGltf.warnings.emplace_back(
|
||||
"Failed to find " + attributeName +
|
||||
" attribute on KHR_gaussian_splatting_compression_spz_2 primitive");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CESIUM_ASSERT(readGltf.model);
|
||||
|
||||
CesiumGltf::Accessor* pAccessor = CesiumGltf::Model::getSafe(
|
||||
&readGltf.model->accessors,
|
||||
attributeIt->second);
|
||||
if (!pAccessor) {
|
||||
readGltf.warnings.emplace_back(
|
||||
"Failed to find accessor at index " +
|
||||
std::to_string(attributeIt->second));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return pAccessor;
|
||||
}
|
||||
|
||||
void copyShCoeff(
|
||||
GltfReaderResult& readGltf,
|
||||
CesiumGltf::MeshPrimitive& primitive,
|
||||
CesiumGltf::Buffer& buffer,
|
||||
spz::GaussianCloud* pGaussian,
|
||||
int degree,
|
||||
int coeffIndex) {
|
||||
size_t base = 0;
|
||||
size_t stride = 0;
|
||||
if (degree == 1) {
|
||||
stride = 9;
|
||||
} else if (degree == 2) {
|
||||
stride = 24;
|
||||
base = 9;
|
||||
} else if (degree == 3) {
|
||||
stride = 45;
|
||||
base = 24;
|
||||
}
|
||||
|
||||
CesiumGltf::Accessor* pAccessor = findAccessor(
|
||||
readGltf,
|
||||
primitive,
|
||||
fmt::format(
|
||||
"KHR_gaussian_splatting:SH_DEGREE_{}_COEF_{}",
|
||||
degree,
|
||||
coeffIndex));
|
||||
if (!pAccessor) {
|
||||
return;
|
||||
}
|
||||
|
||||
CESIUM_ASSERT(readGltf.model);
|
||||
|
||||
// Some gaussian splats seem to set this value as VEC4, even though the spec
|
||||
// requires VEC3.
|
||||
pAccessor->type = CesiumGltf::Accessor::Type::VEC3;
|
||||
|
||||
pAccessor->bufferView =
|
||||
static_cast<int32_t>(readGltf.model->bufferViews.size());
|
||||
CesiumGltf::BufferView& bufferView =
|
||||
readGltf.model->bufferViews.emplace_back();
|
||||
bufferView.buffer = static_cast<int32_t>(readGltf.model->buffers.size() - 1);
|
||||
bufferView.byteLength = static_cast<int64_t>(
|
||||
sizeof(float) * static_cast<size_t>(pGaussian->numPoints) * 3);
|
||||
|
||||
size_t start = buffer.cesium.data.size();
|
||||
bufferView.byteOffset = static_cast<int64_t>(start);
|
||||
buffer.cesium.data.resize(start + static_cast<size_t>(bufferView.byteLength));
|
||||
for (size_t i = 0; i < static_cast<size_t>(pGaussian->numPoints); i++) {
|
||||
const size_t idx = i * stride + base + static_cast<size_t>(coeffIndex) * 3;
|
||||
std::memcpy(
|
||||
buffer.cesium.data.data() + start,
|
||||
pGaussian->sh.data() + idx,
|
||||
sizeof(float) * 3);
|
||||
start += sizeof(float) * 3;
|
||||
}
|
||||
}
|
||||
|
||||
void decodePrimitive(
|
||||
GltfReaderResult& readGltf,
|
||||
CesiumGltf::MeshPrimitive& primitive,
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2& spz) {
|
||||
CESIUM_TRACE("CesiumGltfReader::decodePrimitive");
|
||||
CESIUM_ASSERT(readGltf.model);
|
||||
|
||||
// TODO: handle different accessor component types
|
||||
|
||||
std::unique_ptr<spz::GaussianCloud> pGaussian =
|
||||
decodeBufferViewToGaussianCloud(readGltf, primitive, spz);
|
||||
if (!pGaussian) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t bufferLength =
|
||||
sizeof(float) * (pGaussian->positions.size() + pGaussian->scales.size() +
|
||||
pGaussian->scales.size() + pGaussian->rotations.size() +
|
||||
pGaussian->alphas.size() + pGaussian->colors.size() +
|
||||
pGaussian->sh.size());
|
||||
|
||||
CesiumGltf::Buffer& buffer = readGltf.model->buffers.emplace_back();
|
||||
buffer.byteLength = static_cast<int64_t>(bufferLength);
|
||||
buffer.cesium.data.reserve(bufferLength);
|
||||
|
||||
// Position and rotation can be copied verbatim
|
||||
CesiumGltf::Accessor* pPosAccessor =
|
||||
findAccessor(readGltf, primitive, "POSITION");
|
||||
if (pPosAccessor) {
|
||||
pPosAccessor->type = CesiumGltf::Accessor::Type::VEC3;
|
||||
pPosAccessor->bufferView =
|
||||
static_cast<int32_t>(readGltf.model->bufferViews.size());
|
||||
CesiumGltf::BufferView& bufferView =
|
||||
readGltf.model->bufferViews.emplace_back();
|
||||
bufferView.buffer =
|
||||
static_cast<int32_t>(readGltf.model->buffers.size() - 1);
|
||||
bufferView.byteLength =
|
||||
static_cast<int64_t>(sizeof(float) * pGaussian->positions.size());
|
||||
|
||||
size_t start = buffer.cesium.data.size();
|
||||
bufferView.byteOffset = static_cast<int64_t>(start);
|
||||
buffer.cesium.data.resize(
|
||||
start + static_cast<size_t>(bufferView.byteLength));
|
||||
memcpy(
|
||||
buffer.cesium.data.data() + start,
|
||||
pGaussian->positions.data(),
|
||||
sizeof(float) * pGaussian->positions.size());
|
||||
}
|
||||
|
||||
CesiumGltf::Accessor* pRotAccessor =
|
||||
findAccessor(readGltf, primitive, "KHR_gaussian_splatting:ROTATION");
|
||||
if (pRotAccessor) {
|
||||
pRotAccessor->type = CesiumGltf::Accessor::Type::VEC4;
|
||||
pRotAccessor->bufferView =
|
||||
static_cast<int32_t>(readGltf.model->bufferViews.size());
|
||||
CesiumGltf::BufferView& bufferView =
|
||||
readGltf.model->bufferViews.emplace_back();
|
||||
bufferView.buffer =
|
||||
static_cast<int32_t>(readGltf.model->buffers.size() - 1);
|
||||
bufferView.byteLength =
|
||||
static_cast<int64_t>(sizeof(float) * pGaussian->rotations.size());
|
||||
|
||||
size_t start = buffer.cesium.data.size();
|
||||
bufferView.byteOffset = static_cast<int64_t>(start);
|
||||
buffer.cesium.data.resize(
|
||||
start + static_cast<size_t>(bufferView.byteLength));
|
||||
memcpy(
|
||||
buffer.cesium.data.data() + start,
|
||||
pGaussian->rotations.data(),
|
||||
sizeof(float) * pGaussian->rotations.size());
|
||||
}
|
||||
|
||||
// Color needs to be interleaved with alphas and have its values converted
|
||||
CesiumGltf::Accessor* pColorAccessor =
|
||||
findAccessor(readGltf, primitive, "COLOR_0");
|
||||
if (pColorAccessor) {
|
||||
pColorAccessor->type = CesiumGltf::Accessor::Type::VEC4;
|
||||
pColorAccessor->componentType = CesiumGltf::Accessor::ComponentType::FLOAT;
|
||||
pColorAccessor->bufferView =
|
||||
static_cast<int32_t>(readGltf.model->bufferViews.size());
|
||||
CesiumGltf::BufferView& bufferView =
|
||||
readGltf.model->bufferViews.emplace_back();
|
||||
bufferView.buffer =
|
||||
static_cast<int32_t>(readGltf.model->buffers.size() - 1);
|
||||
bufferView.byteLength = static_cast<int64_t>(
|
||||
(pGaussian->colors.size() + pGaussian->alphas.size()) * sizeof(float));
|
||||
|
||||
size_t start = buffer.cesium.data.size();
|
||||
buffer.cesium.data.resize(
|
||||
start + static_cast<size_t>(bufferView.byteLength));
|
||||
bufferView.byteOffset = static_cast<int64_t>(start);
|
||||
for (size_t i = 0; i < pGaussian->alphas.size(); i++) {
|
||||
glm::fvec4 color(
|
||||
0.5 + pGaussian->colors[i * 3] * SH_C0,
|
||||
0.5 + pGaussian->colors[i * 3 + 1] * SH_C0,
|
||||
0.5 + pGaussian->colors[i * 3 + 2] * SH_C0,
|
||||
1.0 / (1.0 + exp(-pGaussian->alphas[i])));
|
||||
memcpy(
|
||||
buffer.cesium.data.data() + start + i * sizeof(glm::fvec4),
|
||||
&color,
|
||||
sizeof(glm::fvec4));
|
||||
}
|
||||
}
|
||||
|
||||
// Scale needs to be converted
|
||||
CesiumGltf::Accessor* pScaleAccessor =
|
||||
findAccessor(readGltf, primitive, "KHR_gaussian_splatting:SCALE");
|
||||
if (pScaleAccessor) {
|
||||
pScaleAccessor->type = CesiumGltf::Accessor::Type::VEC3;
|
||||
pScaleAccessor->bufferView =
|
||||
static_cast<int32_t>(readGltf.model->bufferViews.size());
|
||||
CesiumGltf::BufferView& bufferView =
|
||||
readGltf.model->bufferViews.emplace_back();
|
||||
bufferView.buffer =
|
||||
static_cast<int32_t>(readGltf.model->buffers.size() - 1);
|
||||
bufferView.byteLength =
|
||||
static_cast<int64_t>(sizeof(float) * pGaussian->scales.size());
|
||||
|
||||
size_t start = buffer.cesium.data.size();
|
||||
buffer.cesium.data.resize(
|
||||
start + static_cast<size_t>(bufferView.byteLength));
|
||||
bufferView.byteOffset = static_cast<int64_t>(start);
|
||||
for (size_t i = 0; i < pGaussian->scales.size(); i++) {
|
||||
float scale = exp(pGaussian->scales[i]);
|
||||
memcpy(
|
||||
buffer.cesium.data.data() + start + i * sizeof(float),
|
||||
&scale,
|
||||
sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
if (pGaussian->shDegree > 0) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
copyShCoeff(readGltf, primitive, buffer, pGaussian.get(), 1, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (pGaussian->shDegree > 1) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
copyShCoeff(readGltf, primitive, buffer, pGaussian.get(), 2, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (pGaussian->shDegree > 2) {
|
||||
for (int i = 0; i < 7; i++) {
|
||||
copyShCoeff(readGltf, primitive, buffer, pGaussian.get(), 3, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2*
|
||||
addExtensionFromJsonValue(
|
||||
const std::string& extName,
|
||||
CesiumGltfReader::GltfReaderResult& readGltf,
|
||||
CesiumGltf::ExtensionKhrGaussianSplatting& splatting,
|
||||
CesiumUtility::JsonValue* pKhrJson) {
|
||||
if (!pKhrJson->isObject()) {
|
||||
readGltf.errors.push_back(fmt::format("Invalid {} extension", extName));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const CesiumUtility::JsonValue::Object::const_iterator it =
|
||||
pKhrJson->getObject().find("bufferView");
|
||||
if (it == pKhrJson->getObject().end()) {
|
||||
readGltf.errors.push_back(
|
||||
fmt::format("No `bufferView` property found on {} extension", extName));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!it->second.isInt64() && !it->second.isUint64()) {
|
||||
readGltf.errors.push_back(fmt::format(
|
||||
"`bufferView` property on {} extension must be an integer value",
|
||||
extName));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2& ext =
|
||||
splatting.addExtension<
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2>();
|
||||
ext.bufferView = it->second.isInt64()
|
||||
? static_cast<int32_t>(it->second.getInt64())
|
||||
: static_cast<int32_t>(it->second.getUint64());
|
||||
return &ext;
|
||||
}
|
||||
|
||||
// Maps attribute names from older versions of the extension to the names from
|
||||
// the current version of the extension.
|
||||
void fixAttributeNames(CesiumGltf::MeshPrimitive& primitive) {
|
||||
std::vector<std::string> attributesToConvert;
|
||||
attributesToConvert.reserve(primitive.attributes.size());
|
||||
for (std::pair<const std::string, int32_t>& attribute :
|
||||
primitive.attributes) {
|
||||
if (attribute.first == "_SCALE" || attribute.first == "_ROTATION" ||
|
||||
attribute.first.starts_with("_SH_DEGREE_")) {
|
||||
attributesToConvert.push_back(attribute.first);
|
||||
}
|
||||
}
|
||||
|
||||
for (const std::string& oldName : attributesToConvert) {
|
||||
const int32_t accessorIndex = primitive.attributes[oldName];
|
||||
primitive.attributes.erase(oldName);
|
||||
primitive.attributes.emplace(
|
||||
"KHR_gaussian_splatting:" + oldName.substr(1),
|
||||
accessorIndex);
|
||||
}
|
||||
}
|
||||
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2*
|
||||
getAndMaybeConvertSpzExtension(
|
||||
CesiumGltfReader::GltfReaderResult& readGltf,
|
||||
CesiumGltf::MeshPrimitive& primitive,
|
||||
CesiumGltf::ExtensionKhrGaussianSplatting& splatting) {
|
||||
|
||||
// Check for the real thing.
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2* pSpz =
|
||||
splatting.getExtension<
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2>();
|
||||
if (pSpz) {
|
||||
return pSpz;
|
||||
}
|
||||
|
||||
// Check for the old versions.
|
||||
CesiumUtility::JsonValue* pKhrSpz =
|
||||
primitive.getGenericExtension(ALTERNATE_EXT_NAME1);
|
||||
if (pKhrSpz != nullptr) {
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2* pResult =
|
||||
addExtensionFromJsonValue(
|
||||
ALTERNATE_EXT_NAME1,
|
||||
readGltf,
|
||||
splatting,
|
||||
pKhrSpz);
|
||||
primitive.extensions.erase(ALTERNATE_EXT_NAME1);
|
||||
return pResult;
|
||||
}
|
||||
|
||||
CesiumUtility::JsonValue* pSpzNoVersion =
|
||||
splatting.getGenericExtension(ALTERNATE_EXT_NAME2);
|
||||
if (pSpzNoVersion != nullptr) {
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2* pResult =
|
||||
addExtensionFromJsonValue(
|
||||
ALTERNATE_EXT_NAME2,
|
||||
readGltf,
|
||||
splatting,
|
||||
pSpzNoVersion);
|
||||
primitive.extensions.erase(ALTERNATE_EXT_NAME2);
|
||||
return pResult;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void decodeSpz(CesiumGltfReader::GltfReaderResult& readGltf) {
|
||||
CESIUM_TRACE("CesiumGltfReader::decodeSpz");
|
||||
if (!readGltf.model) {
|
||||
return;
|
||||
}
|
||||
|
||||
CesiumGltf::Model& model = readGltf.model.value();
|
||||
|
||||
for (CesiumGltf::Mesh& mesh : model.meshes) {
|
||||
for (CesiumGltf::MeshPrimitive& primitive : mesh.primitives) {
|
||||
// KHR_spz_gaussian_splats_compression has no KHR_gaussian_splatting
|
||||
// extension attached Just throw one on there to make this easier
|
||||
if (primitive.extensions.contains(ALTERNATE_EXT_NAME1)) {
|
||||
primitive.addExtension<CesiumGltf::ExtensionKhrGaussianSplatting>();
|
||||
}
|
||||
|
||||
CesiumGltf::ExtensionKhrGaussianSplatting* pSplat =
|
||||
primitive.getExtension<CesiumGltf::ExtensionKhrGaussianSplatting>();
|
||||
if (!pSplat) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2* pSpz =
|
||||
getAndMaybeConvertSpzExtension(readGltf, primitive, *pSplat);
|
||||
if (!pSpz) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fixAttributeNames(primitive);
|
||||
decodePrimitive(readGltf, primitive, *pSpz);
|
||||
|
||||
// Remove the SPZ extension as it no longer applies.
|
||||
pSplat->extensions.erase(
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2::
|
||||
ExtensionName);
|
||||
}
|
||||
}
|
||||
|
||||
model.removeExtensionRequired(
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2::ExtensionName);
|
||||
model.removeExtensionRequired(ALTERNATE_EXT_NAME1);
|
||||
model.removeExtensionRequired(ALTERNATE_EXT_NAME2);
|
||||
}
|
||||
|
||||
bool hasSpzExtension(GltfReaderResult& readGltf) {
|
||||
CESIUM_ASSERT(readGltf.model);
|
||||
|
||||
if (readGltf.model->isExtensionUsed(
|
||||
CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2::
|
||||
ExtensionName)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (readGltf.model->isExtensionUsed(ALTERNATE_EXT_NAME1)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (readGltf.model->isExtensionUsed(ALTERNATE_EXT_NAME2)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
} // namespace CesiumGltfReader
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
namespace CesiumGltfReader {
|
||||
struct GltfReaderResult;
|
||||
|
||||
void decodeSpz(GltfReaderResult& readGltf);
|
||||
bool hasSpzExtension(GltfReaderResult& readGltf);
|
||||
} // namespace CesiumGltfReader
|
||||
|
|
@ -813,3 +813,54 @@ TEST_CASE("GltfReader::postprocessGltf") {
|
|||
CHECK(s == "test");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("SPZ decoding works properly") {
|
||||
SUBCASE("Basic model with one vertex no spherical harmonics") {
|
||||
GltfReader reader;
|
||||
GltfReaderResult result = reader.readGltf(readFile(
|
||||
std::filesystem::path(CesiumGltfReader_TEST_DATA_DIR) / "SpzSplat" /
|
||||
"basic.glb"));
|
||||
REQUIRE(result.model);
|
||||
const Model& model = result.model.value();
|
||||
|
||||
REQUIRE(model.meshes.size() == 1);
|
||||
REQUIRE(model.meshes[0].primitives.size() == 1);
|
||||
|
||||
const std::unordered_map<std::string, int32_t>& attributes =
|
||||
model.meshes[0].primitives[0].attributes;
|
||||
|
||||
CHECK(attributes.size() == 4);
|
||||
|
||||
REQUIRE(attributes.contains("POSITION"));
|
||||
AccessorView<glm::vec3> positionView(model, attributes.at("POSITION"));
|
||||
REQUIRE(positionView.status() == AccessorViewStatus::Valid);
|
||||
REQUIRE(positionView.size() == 1);
|
||||
CHECK(positionView[0] == glm::vec3(1.0, 2.0, 3.0));
|
||||
|
||||
REQUIRE(attributes.contains("COLOR_0"));
|
||||
AccessorView<glm::vec4> colorView(model, attributes.at("COLOR_0"));
|
||||
REQUIRE(colorView.status() == AccessorViewStatus::Valid);
|
||||
REQUIRE(colorView.size() == 1);
|
||||
CHECK(
|
||||
colorView[0] ==
|
||||
glm::vec4(0.570062876, 0.643813193, 0.710188448, 0.501960814));
|
||||
|
||||
REQUIRE(attributes.contains("KHR_gaussian_splatting:ROTATION"));
|
||||
AccessorView<glm::vec4> rotationView(
|
||||
model,
|
||||
attributes.at("KHR_gaussian_splatting:ROTATION"));
|
||||
REQUIRE(rotationView.status() == AccessorViewStatus::Valid);
|
||||
REQUIRE(rotationView.size() == 1);
|
||||
CHECK(
|
||||
rotationView[0] ==
|
||||
glm::vec4(0.003921628, -0.709803939, 0.709804058, 0.0));
|
||||
|
||||
REQUIRE(attributes.contains("KHR_gaussian_splatting:SCALE"));
|
||||
AccessorView<glm::vec3> scaleView(
|
||||
model,
|
||||
attributes.at("KHR_gaussian_splatting:SCALE"));
|
||||
REQUIRE(scaleView.status() == AccessorViewStatus::Valid);
|
||||
REQUIRE(scaleView.size() == 1);
|
||||
CHECK(scaleView[0] == glm::vec3(20.085537, 7.38905621, 2.71828175));
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
|
@ -38,6 +38,8 @@
|
|||
#include <CesiumGltf/ExtensionExtPrimitiveVoxels.h>
|
||||
#include <CesiumGltf/ExtensionExtStructuralMetadata.h>
|
||||
#include <CesiumGltf/ExtensionKhrDracoMeshCompression.h>
|
||||
#include <CesiumGltf/ExtensionKhrGaussianSplatting.h>
|
||||
#include <CesiumGltf/ExtensionKhrGaussianSplattingCompressionSpz2.h>
|
||||
#include <CesiumGltf/ExtensionKhrImplicitShapes.h>
|
||||
#include <CesiumGltf/ExtensionKhrMaterialsUnlit.h>
|
||||
#include <CesiumGltf/ExtensionKhrTextureBasisu.h>
|
||||
|
|
@ -218,6 +220,16 @@ void writeJson(
|
|||
CesiumJsonWriter::JsonWriter& jsonWriter,
|
||||
const CesiumJsonWriter::ExtensionWriterContext& context);
|
||||
|
||||
void writeJson(
|
||||
const CesiumGltf::ExtensionKhrGaussianSplatting& obj,
|
||||
CesiumJsonWriter::JsonWriter& jsonWriter,
|
||||
const CesiumJsonWriter::ExtensionWriterContext& context);
|
||||
|
||||
void writeJson(
|
||||
const CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2& obj,
|
||||
CesiumJsonWriter::JsonWriter& jsonWriter,
|
||||
const CesiumJsonWriter::ExtensionWriterContext& context);
|
||||
|
||||
void writeJson(
|
||||
const CesiumGltf::Padding& obj,
|
||||
CesiumJsonWriter::JsonWriter& jsonWriter,
|
||||
|
|
@ -1174,6 +1186,56 @@ void writeJson(
|
|||
jsonWriter.EndObject();
|
||||
}
|
||||
|
||||
void writeJson(
|
||||
const CesiumGltf::ExtensionKhrGaussianSplatting& obj,
|
||||
CesiumJsonWriter::JsonWriter& jsonWriter,
|
||||
const CesiumJsonWriter::ExtensionWriterContext& context) {
|
||||
jsonWriter.StartObject();
|
||||
|
||||
if (obj.kernel != "ellipse") {
|
||||
jsonWriter.Key("kernel");
|
||||
writeJson(obj.kernel, jsonWriter, context);
|
||||
}
|
||||
|
||||
if (obj.projection !=
|
||||
CesiumGltf::ExtensionKhrGaussianSplatting::Projection::perspective) {
|
||||
jsonWriter.Key("projection");
|
||||
writeJson(obj.projection, jsonWriter, context);
|
||||
}
|
||||
|
||||
if (obj.sortingMethod != CesiumGltf::ExtensionKhrGaussianSplatting::
|
||||
SortingMethod::cameraDistance) {
|
||||
jsonWriter.Key("sortingMethod");
|
||||
writeJson(obj.sortingMethod, jsonWriter, context);
|
||||
}
|
||||
|
||||
if (obj.colorSpace !=
|
||||
CesiumGltf::ExtensionKhrGaussianSplatting::ColorSpace::BT_709) {
|
||||
jsonWriter.Key("colorSpace");
|
||||
writeJson(obj.colorSpace, jsonWriter, context);
|
||||
}
|
||||
|
||||
writeExtensibleObject(obj, jsonWriter, context);
|
||||
|
||||
jsonWriter.EndObject();
|
||||
}
|
||||
|
||||
void writeJson(
|
||||
const CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2& obj,
|
||||
CesiumJsonWriter::JsonWriter& jsonWriter,
|
||||
const CesiumJsonWriter::ExtensionWriterContext& context) {
|
||||
jsonWriter.StartObject();
|
||||
|
||||
if (obj.bufferView > -1) {
|
||||
jsonWriter.Key("bufferView");
|
||||
writeJson(obj.bufferView, jsonWriter, context);
|
||||
}
|
||||
|
||||
writeExtensibleObject(obj, jsonWriter, context);
|
||||
|
||||
jsonWriter.EndObject();
|
||||
}
|
||||
|
||||
void writeJson(
|
||||
const CesiumGltf::Padding& obj,
|
||||
CesiumJsonWriter::JsonWriter& jsonWriter,
|
||||
|
|
@ -2892,6 +2954,20 @@ void ExtensionExtPrimitiveVoxelsJsonWriter::write(
|
|||
writeJson(obj, jsonWriter, context);
|
||||
}
|
||||
|
||||
void ExtensionKhrGaussianSplattingJsonWriter::write(
|
||||
const CesiumGltf::ExtensionKhrGaussianSplatting& obj,
|
||||
CesiumJsonWriter::JsonWriter& jsonWriter,
|
||||
const CesiumJsonWriter::ExtensionWriterContext& context) {
|
||||
writeJson(obj, jsonWriter, context);
|
||||
}
|
||||
|
||||
void ExtensionKhrGaussianSplattingCompressionSpz2JsonWriter::write(
|
||||
const CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2& obj,
|
||||
CesiumJsonWriter::JsonWriter& jsonWriter,
|
||||
const CesiumJsonWriter::ExtensionWriterContext& context) {
|
||||
writeJson(obj, jsonWriter, context);
|
||||
}
|
||||
|
||||
void PaddingJsonWriter::write(
|
||||
const CesiumGltf::Padding& obj,
|
||||
CesiumJsonWriter::JsonWriter& jsonWriter,
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ struct ExtensionKhrImplicitShapes;
|
|||
struct ExtensionExtImplicitEllipsoidRegion;
|
||||
struct ExtensionExtImplicitCylinderRegion;
|
||||
struct ExtensionExtPrimitiveVoxels;
|
||||
struct ExtensionKhrGaussianSplatting;
|
||||
struct ExtensionKhrGaussianSplattingCompressionSpz2;
|
||||
struct Padding;
|
||||
struct Shape;
|
||||
struct Cylinder;
|
||||
|
|
@ -402,6 +404,33 @@ struct ExtensionExtPrimitiveVoxelsJsonWriter {
|
|||
const CesiumJsonWriter::ExtensionWriterContext& context);
|
||||
};
|
||||
|
||||
struct ExtensionKhrGaussianSplattingJsonWriter {
|
||||
using ValueType = CesiumGltf::ExtensionKhrGaussianSplatting;
|
||||
|
||||
/** @brief The official name of the extension. This should be the same as its
|
||||
* key in the `extensions` object. */
|
||||
static constexpr const char* ExtensionName = "KHR_gaussian_splatting";
|
||||
|
||||
static void write(
|
||||
const CesiumGltf::ExtensionKhrGaussianSplatting& obj,
|
||||
CesiumJsonWriter::JsonWriter& jsonWriter,
|
||||
const CesiumJsonWriter::ExtensionWriterContext& context);
|
||||
};
|
||||
|
||||
struct ExtensionKhrGaussianSplattingCompressionSpz2JsonWriter {
|
||||
using ValueType = CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2;
|
||||
|
||||
/** @brief The official name of the extension. This should be the same as its
|
||||
* key in the `extensions` object. */
|
||||
static constexpr const char* ExtensionName =
|
||||
"KHR_gaussian_splatting_compression_spz_2";
|
||||
|
||||
static void write(
|
||||
const CesiumGltf::ExtensionKhrGaussianSplattingCompressionSpz2& obj,
|
||||
CesiumJsonWriter::JsonWriter& jsonWriter,
|
||||
const CesiumJsonWriter::ExtensionWriterContext& context);
|
||||
};
|
||||
|
||||
struct PaddingJsonWriter {
|
||||
using ValueType = CesiumGltf::Padding;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <CesiumGltf/Buffer.h>
|
||||
#include <CesiumGltf/BufferView.h>
|
||||
#include <CesiumGltf/ExtensionKhrGaussianSplatting.h>
|
||||
#include <CesiumGltf/FeatureIdTexture.h>
|
||||
#include <CesiumGltf/Material.h>
|
||||
#include <CesiumGltf/MaterialNormalTextureInfo.h>
|
||||
|
|
@ -34,6 +35,8 @@
|
|||
#include <CesiumGltf/ExtensionExtPrimitiveVoxels.h>
|
||||
#include <CesiumGltf/ExtensionExtStructuralMetadata.h>
|
||||
#include <CesiumGltf/ExtensionKhrDracoMeshCompression.h>
|
||||
#include <CesiumGltf/ExtensionKhrGaussianSplatting.h>
|
||||
#include <CesiumGltf/ExtensionKhrGaussianSplattingCompressionSpz2.h>
|
||||
#include <CesiumGltf/ExtensionKhrImplicitShapes.h>
|
||||
#include <CesiumGltf/ExtensionKhrMaterialsUnlit.h>
|
||||
#include <CesiumGltf/ExtensionKhrTextureBasisu.h>
|
||||
|
|
@ -86,6 +89,9 @@ void registerWriterExtensions(
|
|||
context.registerExtension<
|
||||
CesiumGltf::MeshPrimitive,
|
||||
ExtensionExtPrimitiveVoxelsJsonWriter>();
|
||||
context.registerExtension<
|
||||
CesiumGltf::MeshPrimitive,
|
||||
ExtensionKhrGaussianSplattingJsonWriter>();
|
||||
context.registerExtension<
|
||||
CesiumGltf::Node,
|
||||
ExtensionExtInstanceFeaturesJsonWriter>();
|
||||
|
|
@ -136,5 +142,8 @@ void registerWriterExtensions(
|
|||
context.registerExtension<
|
||||
CesiumGltf::Shape,
|
||||
ExtensionExtImplicitCylinderRegionJsonWriter>();
|
||||
context.registerExtension<
|
||||
CesiumGltf::ExtensionKhrGaussianSplatting,
|
||||
ExtensionKhrGaussianSplattingCompressionSpz2JsonWriter>();
|
||||
}
|
||||
} // namespace CesiumGltfWriter
|
||||
|
|
|
|||
|
|
@ -613,6 +613,7 @@ TEST_CASE("Writes glb with binaryChunkByteAlignment of 8") {
|
|||
REQUIRE(glbBytesExtraPadding.size() == 88);
|
||||
}
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
TEST_CASE("Reports an error if asked to write a GLB larger than 4GB") {
|
||||
CesiumGltf::Model model;
|
||||
model.asset.version = "2.0";
|
||||
|
|
@ -628,3 +629,4 @@ TEST_CASE("Reports an error if asked to write a GLB larger than 4GB") {
|
|||
REQUIRE(!result.errors.empty());
|
||||
CHECK(result.gltfBytes.empty());
|
||||
}
|
||||
#endif // __EMSCRIPTEN__
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ using namespace CesiumNativeTests;
|
|||
using namespace CesiumUtility;
|
||||
|
||||
namespace {
|
||||
const std::string& REDIRECT_PATH = "/dummy/auth/path";
|
||||
const std::string REDIRECT_PATH = "/dummy/auth/path";
|
||||
const int REDIRECT_PORT = 49013;
|
||||
|
||||
std::shared_ptr<Connection>
|
||||
|
|
@ -169,4 +169,4 @@ TEST_CASE("CesiumITwinClient::Connection::geospatialFeatureCollections") {
|
|||
collection.storageCrs ==
|
||||
"https://www.opengis.net/def/crs/EPSG/0/32615");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,14 @@ cesium_glob_files(test_headers
|
|||
)
|
||||
set(test_include_directories ${CMAKE_CURRENT_LIST_DIR}/include)
|
||||
|
||||
if(CESIUM_TARGET_WASM)
|
||||
target_link_options(
|
||||
cesium-native-tests
|
||||
PRIVATE
|
||||
"-sEXIT_RUNTIME=1"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Iterate through all targets, extracting their private sources and test sources / test headers
|
||||
foreach(target ${cesium_native_targets})
|
||||
get_target_property(target_test_sources ${target} TEST_SOURCES)
|
||||
|
|
@ -75,6 +83,41 @@ foreach(target ${cesium_native_targets})
|
|||
endif()
|
||||
endforeach()
|
||||
|
||||
if(CESIUM_TARGET_WASM)
|
||||
file(GLOB directories_list LIST_DIRECTORIES true "${CMAKE_SOURCE_DIR}/Cesium*")
|
||||
set(FILE_PACKAGER_ARGS "")
|
||||
set(TEST_DATA_FILES "")
|
||||
foreach(dir ${directories_list})
|
||||
if(IS_DIRECTORY ${dir}/test/data)
|
||||
list(APPEND FILE_PACKAGER_ARGS "--embed" "${dir}/test/data")
|
||||
|
||||
file(GLOB_RECURSE data_files "${dir}/test/data/*")
|
||||
list(APPEND TEST_DATA_FILES ${data_files})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
list(APPEND FILE_PACKAGER_ARGS "--embed" "${CMAKE_SOURCE_DIR}/data")
|
||||
|
||||
if(CESIUM_WASM64)
|
||||
list(APPEND FILE_PACKAGER_ARGS "--wasm64")
|
||||
endif()
|
||||
|
||||
set(CESIUM_NATIVE_TESTS_DATA_OBJ ${CMAKE_CURRENT_BINARY_DIR}/cesium-native-tests-data.o)
|
||||
add_custom_command(
|
||||
COMMENT "Generating test data object file"
|
||||
OUTPUT ${CESIUM_NATIVE_TESTS_DATA_OBJ}
|
||||
COMMAND ${EMSCRIPTEN_ROOT_PATH}/tools/file_packager none.data ${FILE_PACKAGER_ARGS} --obj-output=${CESIUM_NATIVE_TESTS_DATA_OBJ}
|
||||
VERBATIM
|
||||
DEPENDS ${TEST_DATA_FILES}
|
||||
)
|
||||
|
||||
target_sources(
|
||||
cesium-native-tests
|
||||
PRIVATE
|
||||
${CESIUM_NATIVE_TESTS_DATA_OBJ}
|
||||
)
|
||||
endif()
|
||||
|
||||
target_sources(
|
||||
cesium-native-tests
|
||||
PRIVATE
|
||||
|
|
@ -99,9 +142,12 @@ PRIVATE
|
|||
|
||||
target_compile_definitions(cesium-native-tests
|
||||
PRIVATE
|
||||
CESIUM_NATIVE_DATA_DIR=\"${CMAKE_CURRENT_LIST_DIR}/../data\"
|
||||
CESIUM_NATIVE_DATA_DIR=\"${CMAKE_SOURCE_DIR}/data\"
|
||||
)
|
||||
|
||||
include(CTest)
|
||||
include(doctest)
|
||||
doctest_discover_tests(cesium-native-tests)
|
||||
if(NOT CESIUM_TARGET_WASM)
|
||||
# doctest_discover_tests can't handle the target being an html file, so we just avoid it on a wasm build
|
||||
doctest_discover_tests(cesium-native-tests)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -43,10 +43,10 @@ std::unique_ptr<SimpleAssetResponse> readFileUri(const std::string& uri) {
|
|||
if (!file) {
|
||||
return response(404);
|
||||
}
|
||||
std::streamsize size = file.tellg();
|
||||
std::streamoff size = file.tellg();
|
||||
file.seekg(0, std::ios::beg);
|
||||
result.resize(static_cast<size_t>(size));
|
||||
file.read(reinterpret_cast<char*>(result.data()), size);
|
||||
result.resize(size_t(size));
|
||||
file.read(reinterpret_cast<char*>(result.data()), std::streamsize(size));
|
||||
if (!file) {
|
||||
return response(503);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@ std::vector<std::byte> readFile(const std::filesystem::path& fileName) {
|
|||
std::ifstream file(fileName, std::ios::binary | std::ios::ate);
|
||||
REQUIRE(file);
|
||||
|
||||
std::streamsize size = file.tellg();
|
||||
std::streamoff size = file.tellg();
|
||||
file.seekg(0, std::ios::beg);
|
||||
|
||||
std::vector<std::byte> buffer(static_cast<size_t>(size));
|
||||
file.read(reinterpret_cast<char*>(buffer.data()), size);
|
||||
std::vector<std::byte> buffer{size_t(size)};
|
||||
file.read(reinterpret_cast<char*>(buffer.data()), std::streamsize(size));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -506,7 +506,7 @@ void addSkirts(
|
|||
westEdgeIndices.begin(),
|
||||
westEdgeIndices.end(),
|
||||
sortEdgeIndices.begin(),
|
||||
sortEdgeIndices.begin() + westVertexCount,
|
||||
sortEdgeIndices.begin() + ptrdiff_t(westVertexCount),
|
||||
[&uvsAndHeights](auto lhs, auto rhs) noexcept {
|
||||
return uvsAndHeights[lhs].y < uvsAndHeights[rhs].y;
|
||||
});
|
||||
|
|
@ -539,7 +539,7 @@ void addSkirts(
|
|||
southEdgeIndices.begin(),
|
||||
southEdgeIndices.end(),
|
||||
sortEdgeIndices.begin(),
|
||||
sortEdgeIndices.begin() + southVertexCount,
|
||||
sortEdgeIndices.begin() + ptrdiff_t(southVertexCount),
|
||||
[&uvsAndHeights](auto lhs, auto rhs) noexcept {
|
||||
return uvsAndHeights[lhs].x > uvsAndHeights[rhs].x;
|
||||
});
|
||||
|
|
@ -572,7 +572,7 @@ void addSkirts(
|
|||
eastEdgeIndices.begin(),
|
||||
eastEdgeIndices.end(),
|
||||
sortEdgeIndices.begin(),
|
||||
sortEdgeIndices.begin() + eastVertexCount,
|
||||
sortEdgeIndices.begin() + ptrdiff_t(eastVertexCount),
|
||||
[&uvsAndHeights](auto lhs, auto rhs) noexcept {
|
||||
return uvsAndHeights[lhs].y > uvsAndHeights[rhs].y;
|
||||
});
|
||||
|
|
@ -605,7 +605,7 @@ void addSkirts(
|
|||
northEdgeIndices.begin(),
|
||||
northEdgeIndices.end(),
|
||||
sortEdgeIndices.begin(),
|
||||
sortEdgeIndices.begin() + northVertexCount,
|
||||
sortEdgeIndices.begin() + ptrdiff_t(northVertexCount),
|
||||
[&uvsAndHeights](auto lhs, auto rhs) noexcept {
|
||||
return uvsAndHeights[lhs].x < uvsAndHeights[rhs].x;
|
||||
});
|
||||
|
|
@ -754,11 +754,10 @@ QuantizedMeshMetadataResult processMetadata(
|
|||
// decode position without skirt, but preallocate position buffer to include
|
||||
// skirt as well
|
||||
std::vector<std::byte> outputPositionsBuffer(
|
||||
static_cast<uint64_t>((vertexCount + skirtVertexCount) * 3) *
|
||||
sizeof(float));
|
||||
size_t((vertexCount + skirtVertexCount) * 3) * sizeof(float));
|
||||
std::span<float> outputPositions(
|
||||
reinterpret_cast<float*>(outputPositionsBuffer.data()),
|
||||
static_cast<size_t>((vertexCount + skirtVertexCount) * 3));
|
||||
size_t((vertexCount + skirtVertexCount) * 3));
|
||||
size_t positionOutputIndex = 0;
|
||||
|
||||
const glm::dvec3 center(
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ target_link_libraries(CesiumRasterOverlays
|
|||
CesiumUtility
|
||||
CesiumVectorData
|
||||
nonstd::expected-lite
|
||||
spdlog::spdlog
|
||||
PRIVATE
|
||||
tinyxml2::tinyxml2
|
||||
)
|
||||
|
|
|
|||
|
|
@ -591,7 +591,7 @@ RasterOverlayUtilities::upsampleGltfForRasterOverlays(
|
|||
// We're assuming here that nothing references primitives by index, so we
|
||||
// can remove them without any drama.
|
||||
if (!keep) {
|
||||
mesh.primitives.erase(mesh.primitives.begin() + int64_t(i));
|
||||
mesh.primitives.erase(mesh.primitives.begin() + ptrdiff_t(i));
|
||||
--i;
|
||||
}
|
||||
containsPrimitives |= !mesh.primitives.empty();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace CesiumUtility {
|
||||
|
||||
|
|
@ -17,7 +18,7 @@ struct Hash {
|
|||
* @param second The second hash value.
|
||||
* @return A new hash value which is a combination of the two.
|
||||
*/
|
||||
static std::size_t combine(std::size_t first, std::size_t second);
|
||||
static size_t combine(size_t first, size_t second);
|
||||
};
|
||||
|
||||
} // namespace CesiumUtility
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#include <CesiumUtility/Hash.h>
|
||||
|
||||
#include <climits>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace CesiumUtility {
|
||||
|
||||
|
|
@ -59,23 +61,50 @@ namespace CesiumUtility {
|
|||
// (https://mostlymangling.blogspot.com/2019/12/stronger-better-morer-moremur-better.html)
|
||||
namespace {
|
||||
|
||||
inline std::size_t mix(std::size_t x) {
|
||||
std::size_t const m = 0xe9846af9b1a615d;
|
||||
template <size_t Bits> struct hash_mix_impl;
|
||||
|
||||
x ^= x >> 32;
|
||||
x *= m;
|
||||
x ^= x >> 32;
|
||||
x *= m;
|
||||
x ^= x >> 28;
|
||||
template <> struct hash_mix_impl<64> {
|
||||
inline static uint64_t fn(uint64_t x) {
|
||||
uint64_t const m = 0xe9846af9b1a615d;
|
||||
|
||||
return x;
|
||||
}
|
||||
x ^= x >> 32;
|
||||
x *= m;
|
||||
x ^= x >> 32;
|
||||
x *= m;
|
||||
x ^= x >> 28;
|
||||
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
// This function is adapted from Boost v1.86.0, `hash_mix_impl<32>` function.
|
||||
//
|
||||
// hash_mix for 32 bit size_t
|
||||
//
|
||||
// We use the "best xmxmx" implementation from
|
||||
// https://github.com/skeeto/hash-prospector/issues/19
|
||||
template <> struct hash_mix_impl<32> {
|
||||
inline static uint32_t fn(uint32_t x) {
|
||||
uint32_t const m1 = 0x21f0aaad;
|
||||
uint32_t const m2 = 0x735a2d97;
|
||||
|
||||
x ^= x >> 16;
|
||||
x *= m1;
|
||||
x ^= x >> 15;
|
||||
x *= m2;
|
||||
x ^= x >> 15;
|
||||
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// This function is adapted from Boost's `hash_combine`.
|
||||
std::size_t Hash::combine(std::size_t first, std::size_t second) {
|
||||
return mix(first + 0x9e3779b9 + second);
|
||||
size_t Hash::combine(size_t first, size_t second) {
|
||||
// This will truncate bits on 32-bit builds.
|
||||
return hash_mix_impl<sizeof(size_t) * CHAR_BIT>::fn(
|
||||
first + size_t(0x9e3779b9) + second);
|
||||
}
|
||||
|
||||
} // namespace CesiumUtility
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ cesium_target_include_directories(
|
|||
${CMAKE_CURRENT_LIST_DIR}/src
|
||||
)
|
||||
|
||||
if(NOT IOS AND NOT VCPKG_CMAKE_SYSTEM_NAME MATCHES "iOS")
|
||||
if(NOT CESIUM_TARGET_WASM AND NOT IOS AND NOT VCPKG_CMAKE_SYSTEM_NAME MATCHES "iOS")
|
||||
set(CESIUM_VECTOR_DATA_ASMJIT_DEPENDENCY asmjit::asmjit)
|
||||
endif()
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ VectorRasterizer::VectorRasterizer(
|
|||
imageHeight,
|
||||
BL_FORMAT_PRGB32,
|
||||
reinterpret_cast<void*>(pData),
|
||||
(int64_t)imageWidth * (int64_t)this->_imageAsset->channels);
|
||||
intptr_t(imageWidth) * intptr_t(this->_imageAsset->channels));
|
||||
|
||||
this->_context.begin(this->_image);
|
||||
// Initialize the image as all transparent.
|
||||
|
|
|
|||
|
|
@ -3,3 +3,14 @@
|
|||
# else()
|
||||
# add_compile_options(-Werror -Wall -Wextra -Wconversion -Wpedantic -Wshadow -Wsign-conversion)
|
||||
# endif()
|
||||
|
||||
if(CESIUM_TARGET_WASM)
|
||||
add_compile_options(-pthread -msimd128 -mnontrapping-fptoint -mbulk-memory -fwasm-exceptions -sSUPPORT_LONGJMP=wasm)
|
||||
add_link_options(-pthread -sALLOW_MEMORY_GROWTH=1 -sPTHREAD_POOL_SIZE=4 -sMAXIMUM_MEMORY=4294967296 -sMIN_NODE_VERSION=200000 -sINITIAL_MEMORY=268435456 -sSTACK_SIZE=1048576 -fwasm-exceptions -mbulk-memory -mnontrapping-fptoint -msse4.2 -sWASM_BIGINT -sSUPPORT_LONGJMP=wasm -sFORCE_FILESYSTEM -sPROXY_TO_PTHREAD)
|
||||
add_link_options($<$<CONFIG:Debug>:-gsource-map>)
|
||||
|
||||
if (CESIUM_WASM64)
|
||||
add_compile_options(-sMEMORY64=1)
|
||||
add_link_options(-sMEMORY64=1)
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ find_dependency(meshoptimizer CONFIG REQUIRED)
|
|||
find_dependency(OpenSSL REQUIRED)
|
||||
find_dependency(s2 CONFIG REQUIRED)
|
||||
find_dependency(spdlog CONFIG REQUIRED)
|
||||
find_dependency(spz CONFIG REQUIRED)
|
||||
find_dependency(tinyxml2 CONFIG REQUIRED)
|
||||
find_dependency(unofficial-sqlite3 CONFIG REQUIRED)
|
||||
find_dependency(WebP CONFIG REQUIRED)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
if(ANDROID)
|
||||
if(CESIUM_TARGET_WASM)
|
||||
set(DETECTED_VCPKG_TRIPLET "wasm32-emscripten")
|
||||
elseif(ANDROID)
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
|
||||
set(DETECTED_VCPKG_TRIPLET "x64-android")
|
||||
else()
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ macro(EZVCPKG_BOOTSTRAP)
|
|||
endmacro()
|
||||
|
||||
macro(EZVCPKG_BUILD)
|
||||
set(INSTALL_COMMAND "${EZVCPKG_EXE}" --vcpkg-root "${EZVCPKG_DIR}" install --triplet ${VCPKG_TRIPLET})
|
||||
set(INSTALL_COMMAND "${EZVCPKG_EXE}" --allow-unsupported --vcpkg-root "${EZVCPKG_DIR}" install --triplet ${VCPKG_TRIPLET})
|
||||
|
||||
if (DEFINED VCPKG_OVERLAY_PORTS)
|
||||
if (CMAKE_HOST_WIN32)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ find_library(modp_b64_DEBUG_LIBRARIES
|
|||
|
||||
# vcpkg specific locations for debug libraries if they are not already found
|
||||
set(modpbase64SavePrefixPath ${CMAKE_PREFIX_PATH})
|
||||
list(FILTER CMAKE_PREFIX_PATH INCLUDE REGEX "/debug")
|
||||
list(FILTER CMAKE_PREFIX_PATH INCLUDE REGEX "/debug$")
|
||||
find_library(modp_b64_DEBUG_LIBRARIES
|
||||
NAMES
|
||||
modpbase64
|
||||
|
|
@ -18,7 +18,7 @@ find_library(modp_b64_DEBUG_LIBRARIES
|
|||
set(CMAKE_PREFIX_PATH ${modpbase64SavePrefixPath})
|
||||
|
||||
set(modpbase64SavePrefixPath ${CMAKE_PREFIX_PATH})
|
||||
list(FILTER CMAKE_PREFIX_PATH EXCLUDE REGEX "/debug")
|
||||
list(FILTER CMAKE_PREFIX_PATH EXCLUDE REGEX "/debug$")
|
||||
find_library(modp_b64_LIBRARIES NAMES modpbase64 libmodpbase64)
|
||||
set(CMAKE_PREFIX_PATH ${modpbase64SavePrefixPath})
|
||||
|
||||
|
|
|
|||
|
|
@ -19,4 +19,4 @@ target_include_directories(earcut INTERFACE "${EARCUT_HPP_INCLUDE_DIRS}")
|
|||
add_library(picosha2::picosha2 IMPORTED INTERFACE GLOBAL)
|
||||
set_target_properties(picosha2::picosha2 PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${PACKAGE_BUILD_DIR}/include"
|
||||
)
|
||||
)
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
vcpkg_from_github(
|
||||
OUT_SOURCE_PATH SOURCE_PATH
|
||||
REPO kring/KTX-Software # KhronosGroup/KTX-Software
|
||||
REF "v${VERSION}"
|
||||
SHA512 fa20457fc0f0b117f4d6b406baa338091a85bcc46f60ca440dcd483388c67c550c81da3618d70d748e12850e32e0c1d82e9e8dc8522849074f40cc455723ac97
|
||||
HEAD_REF master
|
||||
)
|
||||
file(REMOVE "${SOURCE_PATH}/other_include/zstd_errors.h")
|
||||
file(REMOVE_RECURSE "${SOURCE_PATH}/external/basisu/zstd")
|
||||
file(REMOVE_RECURSE "${SOURCE_PATH}/lib/basisu/zstd")
|
||||
|
||||
vcpkg_list(SET OPTIONS)
|
||||
if(VCPKG_TARGET_IS_WINDOWS)
|
||||
vcpkg_acquire_msys(MSYS_ROOT
|
||||
PACKAGES
|
||||
bash
|
||||
DIRECT_PACKAGES
|
||||
# Required for "getopt"
|
||||
"https://mirror.msys2.org/msys/x86_64/util-linux-2.40.2-2-x86_64.pkg.tar.zst"
|
||||
bf45b16cd470f8d82a9fe03842a09da2e6c60393c11f4be0bab354655072c7a461afc015b9c07f9f5c87a0e382cd867e4f079ede0d42f1589aa99ebbb3f76309
|
||||
# Required for "dos2unix"
|
||||
"https://mirror.msys2.org/msys/x86_64/dos2unix-7.5.3-1-x86_64.pkg.tar.zst"
|
||||
ab5f88b10577b1d195d9b7b74c1a46d9e715c5fac21e8da3d590f345294190ed1ce7fde37d765f51ba01c2f6706c077123d4c69cfd0981729fdcb3d30f85bc6d
|
||||
)
|
||||
vcpkg_add_to_path("${MSYS_ROOT}/usr/bin")
|
||||
vcpkg_list(APPEND OPTIONS "-DBASH_EXECUTABLE=${MSYS_ROOT}/usr/bin/bash.exe")
|
||||
endif()
|
||||
|
||||
vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
|
||||
FEATURES
|
||||
tools KTX_FEATURE_TOOLS
|
||||
vulkan LIBKTX_FEATURE_VK_UPLOAD
|
||||
js KTX_FEATURE_JS
|
||||
)
|
||||
|
||||
vcpkg_cmake_configure(
|
||||
SOURCE_PATH "${SOURCE_PATH}"
|
||||
OPTIONS
|
||||
-DKTX_GIT_VERSION_FULL=v${VERSION}
|
||||
-DKTX_FEATURE_TESTS=OFF
|
||||
-DKTX_FEATURE_LOADTEST_APPS=OFF
|
||||
-DKTX_FEATURE_EMBEDDED_ZSTD=OFF
|
||||
-DKTX_FEATURE_EMBEDDED_TOOLS_DEPENDENCIES=OFF
|
||||
-DLIBKTX_FEATURE_APPLE_FRAMEWORK=OFF
|
||||
${FEATURE_OPTIONS}
|
||||
${OPTIONS}
|
||||
DISABLE_PARALLEL_CONFIGURE
|
||||
)
|
||||
|
||||
vcpkg_cmake_install()
|
||||
|
||||
if(tools IN_LIST FEATURES)
|
||||
vcpkg_copy_tools(
|
||||
TOOL_NAMES
|
||||
ktx
|
||||
toktx
|
||||
ktxsc
|
||||
ktxinfo
|
||||
ktx2ktx2
|
||||
ktx2check
|
||||
AUTO_CLEAN
|
||||
)
|
||||
else()
|
||||
vcpkg_copy_pdbs()
|
||||
endif()
|
||||
|
||||
vcpkg_cmake_config_fixup(CONFIG_PATH lib/cmake/ktx)
|
||||
|
||||
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include")
|
||||
|
||||
if(VCPKG_LIBRARY_LINKAGE STREQUAL "static")
|
||||
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/bin" "${CURRENT_PACKAGES_DIR}/debug/bin")
|
||||
endif()
|
||||
|
||||
file(GLOB LICENSE_FILES "${SOURCE_PATH}/LICENSES/*")
|
||||
file(COPY ${LICENSE_FILES} DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}/LICENSES")
|
||||
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.md")
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
"name": "ktx",
|
||||
"version-semver": "4.4.2-plus-vcpkg-patches",
|
||||
"description": [
|
||||
"The Khronos KTX library and tools.",
|
||||
"Functions for writing and reading KTX files, and instantiating OpenGL®, OpenGL ES™️ and Vulkan® textures from them."
|
||||
],
|
||||
"homepage": "https://github.com/KhronosGroup/KTX-Software",
|
||||
"license": null,
|
||||
"supports": "arm64 | x64 | !windows",
|
||||
"dependencies": [
|
||||
{
|
||||
"name": "vcpkg-cmake",
|
||||
"host": true
|
||||
},
|
||||
{
|
||||
"name": "vcpkg-cmake-config",
|
||||
"host": true
|
||||
},
|
||||
"zstd"
|
||||
],
|
||||
"features": {
|
||||
"tools": {
|
||||
"description": "Build tools",
|
||||
"supports": "!android & !uwp",
|
||||
"dependencies": [
|
||||
"cxxopts",
|
||||
"fmt"
|
||||
]
|
||||
},
|
||||
"vulkan": {
|
||||
"description": "Build Vulkan support",
|
||||
"supports": "!emscripten"
|
||||
},
|
||||
"js": {
|
||||
"description": "Build JavaScript interface wrappers",
|
||||
"supports": "emscripten"
|
||||
}
|
||||
},
|
||||
"default-features": [
|
||||
{
|
||||
"name": "js",
|
||||
"platform": "emscripten"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
set(VCPKG_ENV_PASSTHROUGH_UNTRACKED EMSCRIPTEN_ROOT EMSDK PATH EM_CONFIG)
|
||||
|
||||
if(NOT DEFINED ENV{EMSCRIPTEN_ROOT})
|
||||
find_path(EMSCRIPTEN_ROOT "emcc")
|
||||
else()
|
||||
set(EMSCRIPTEN_ROOT "$ENV{EMSCRIPTEN_ROOT}")
|
||||
endif()
|
||||
|
||||
if(NOT EMSCRIPTEN_ROOT)
|
||||
if(NOT DEFINED ENV{EMSDK})
|
||||
message(FATAL_ERROR "The emcc compiler not found in PATH")
|
||||
endif()
|
||||
set(EMSCRIPTEN_ROOT "$ENV{EMSDK}/upstream/emscripten")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${EMSCRIPTEN_ROOT}/cmake/Modules/Platform/Emscripten.cmake")
|
||||
message(FATAL_ERROR "Emscripten.cmake toolchain file not found")
|
||||
endif()
|
||||
|
||||
set(VCPKG_TARGET_ARCHITECTURE wasm32)
|
||||
set(VCPKG_CRT_LINKAGE dynamic)
|
||||
set(VCPKG_LIBRARY_LINKAGE static)
|
||||
set(VCPKG_CMAKE_SYSTEM_NAME Emscripten)
|
||||
set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE "${EMSCRIPTEN_ROOT}/cmake/Modules/Platform/Emscripten.cmake")
|
||||
|
||||
# These lines are the key difference between this triplet and the wasm32-emscripten that comes with vcpkg.
|
||||
# They set specific compiler and linker flags needed to use cesium-native on the web, particularly as part of Unity.
|
||||
set(_configureFlags "-pthread -msimd128 -mnontrapping-fptoint -mbulk-memory -fwasm-exceptions -sSUPPORT_LONGJMP=wasm -DSIZEOF_SIZE_T=4")
|
||||
set(VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_C_FLAGS=${_configureFlags} -DCMAKE_CXX_FLAGS=${_configureFlags} -DCMAKE_EXE_LINKER_FLAGS=${_configureFlags})
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
set(VCPKG_ENV_PASSTHROUGH_UNTRACKED EMSCRIPTEN_ROOT EMSDK PATH EM_CONFIG)
|
||||
|
||||
if(NOT DEFINED ENV{EMSCRIPTEN_ROOT})
|
||||
find_path(EMSCRIPTEN_ROOT "emcc")
|
||||
else()
|
||||
set(EMSCRIPTEN_ROOT "$ENV{EMSCRIPTEN_ROOT}")
|
||||
endif()
|
||||
|
||||
if(NOT EMSCRIPTEN_ROOT)
|
||||
if(NOT DEFINED ENV{EMSDK})
|
||||
message(FATAL_ERROR "The emcc compiler not found in PATH")
|
||||
endif()
|
||||
set(EMSCRIPTEN_ROOT "$ENV{EMSDK}/upstream/emscripten")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${EMSCRIPTEN_ROOT}/cmake/Modules/Platform/Emscripten.cmake")
|
||||
message(FATAL_ERROR "Emscripten.cmake toolchain file not found")
|
||||
endif()
|
||||
|
||||
set(VCPKG_TARGET_ARCHITECTURE wasm32)
|
||||
set(VCPKG_CRT_LINKAGE dynamic)
|
||||
set(VCPKG_LIBRARY_LINKAGE static)
|
||||
set(VCPKG_CMAKE_SYSTEM_NAME Emscripten)
|
||||
set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE "${EMSCRIPTEN_ROOT}/cmake/Modules/Platform/Emscripten.cmake")
|
||||
|
||||
# These lines are the key difference between this triplet and the wasm32-emscripten that comes with vcpkg.
|
||||
# They set specific compiler and linker flags needed to use cesium-native on the web, particularly as part of Unity.
|
||||
set(_configureFlags "-sMEMORY64=1 -pthread -msimd128 -mnontrapping-fptoint -mbulk-memory -fwasm-exceptions -sSUPPORT_LONGJMP=wasm -DSIZEOF_SIZE_T=8")
|
||||
set(VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_C_FLAGS=${_configureFlags} -DCMAKE_CXX_FLAGS=${_configureFlags} -DCMAKE_EXE_LINKER_FLAGS=${_configureFlags})
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "cesium-native",
|
||||
"version": "0.53.0",
|
||||
"version": "0.54.0",
|
||||
"description": "Cesium 3D Geospatial for C++",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
|
|
@ -12,7 +12,8 @@
|
|||
"generate-gltf": "cd tools/generate-classes && npm run generate-gltf && cd ../.. && npm run format",
|
||||
"generate-3d-tiles": "cd tools/generate-classes && npm run generate-3d-tiles && cd ../.. && npm run format",
|
||||
"generate-quantized-mesh-terrain": "cd tools/generate-classes && npm run generate-quantized-mesh-terrain && cd ../.. && npm run format",
|
||||
"conform-includes": "node tools/conform-includes.js"
|
||||
"conform-includes": "node tools/conform-includes.js",
|
||||
"test-wasm": "node tools/test-wasm-server"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
@ -31,6 +32,7 @@
|
|||
"homepage": "https://github.com/CesiumGS/cesium-native#readme",
|
||||
"devDependencies": {
|
||||
"clang-format": "^1.5.0",
|
||||
"doxygen-awesome-css": "https://github.com/jothepro/doxygen-awesome-css#v2.3.4"
|
||||
"doxygen-awesome-css": "https://github.com/jothepro/doxygen-awesome-css#v2.3.4",
|
||||
"express": "^5.1.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,6 +163,12 @@
|
|||
},
|
||||
"EXT_primitive_voxels glTF Mesh Primitive extension": {
|
||||
"overrideName": "ExtensionExtPrimitiveVoxels"
|
||||
},
|
||||
"KHR_gaussian_splatting glTF Mesh Primitive Extension": {
|
||||
"overrideName": "ExtensionKhrGaussianSplatting"
|
||||
},
|
||||
"KHR_gaussian_splatting_compression_spz_2 glTF Mesh Primitive Extension": {
|
||||
"overrideName": "ExtensionKhrGaussianSplattingCompressionSpz2"
|
||||
}
|
||||
},
|
||||
"extensions": [
|
||||
|
|
@ -287,6 +293,20 @@
|
|||
{
|
||||
"extensionName": "EXT_primitive_voxels",
|
||||
"schema": "Vendor/EXT_primitive_voxels/schema/mesh.primitive.EXT_primitive_voxels.schema.json"
|
||||
},
|
||||
{
|
||||
"extensionName": "KHR_gaussian_splatting",
|
||||
"schema": "Khronos/KHR_gaussian_splatting/schema/mesh.primitive.KHR_gaussian_splatting.schema.json",
|
||||
"attachTo": [
|
||||
"mesh.primitive"
|
||||
]
|
||||
},
|
||||
{
|
||||
"extensionName": "KHR_gaussian_splatting_compression_spz_2",
|
||||
"schema": "Khronos/KHR_gaussian_splatting_compression_spz_2/schema/mesh.primitive.KHR_gaussian_splatting_compression_spz_2.schema.json",
|
||||
"attachTo": [
|
||||
"mesh.primitive.KHR_gaussian_splatting"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
function makeIdentifier(s) {
|
||||
return s.replace(/\//g, "_");
|
||||
return s.replace(/[\/\.-]/g, "_");
|
||||
}
|
||||
|
||||
module.exports = makeIdentifier;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
const express = require("express");
|
||||
const fs = require("fs");
|
||||
|
||||
const app = express();
|
||||
const port = 3123;
|
||||
|
||||
app.use(express.static("./", {
|
||||
setHeaders: (res, path, stat) => {
|
||||
res.set("Cross-Origin-Opener-Policy", "same-origin");
|
||||
res.set("Cross-Origin-Embedder-Policy", "require-corp");
|
||||
}
|
||||
}));
|
||||
|
||||
const emsdk = process.env.EMSDK;
|
||||
|
||||
if (emsdk && emsdk.length > 0) {
|
||||
console.log(`Using emsdk at: ${emsdk}`);
|
||||
|
||||
app.use("/emsdk/emscripten", express.static(`${emsdk}/upstream/emscripten`, {
|
||||
setHeaders: (res, path, stat) => {
|
||||
res.set("Cross-Origin-Opener-Policy", "same-origin");
|
||||
res.set("Cross-Origin-Embedder-Policy", "require-corp");
|
||||
}
|
||||
}));
|
||||
|
||||
app.use("/emsdk/upstream", express.static(`${emsdk}/upstream`, {
|
||||
setHeaders: (res, path, stat) => {
|
||||
res.set("Cross-Origin-Opener-Policy", "same-origin");
|
||||
res.set("Cross-Origin-Embedder-Policy", "require-corp");
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
console.log("Not mapping emsdk path because EMSDK environment variable is not set.");
|
||||
}
|
||||
|
||||
const ezvcpkg = process.env.EZVCPKG_BASEDIR;
|
||||
if (!ezvcpkg || ezvcpkg.length === 0) {
|
||||
ezvcpkg = `${process.env.HOME ?? ""}/.ezvcpkg`;
|
||||
}
|
||||
|
||||
if (fs.existsSync(ezvcpkg)) {
|
||||
console.log(`Using ezvcpkg at: ${ezvcpkg}`);
|
||||
|
||||
app.use("/ezvcpkg", express.static(ezvcpkg, {
|
||||
setHeaders: (res, path, stat) => {
|
||||
res.set("Cross-Origin-Opener-Policy", "same-origin");
|
||||
res.set("Cross-Origin-Embedder-Policy", "require-corp");
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
console.log("Not mapping ezvcpkg path because EZVCPKG_BASEDIR environment variable is not set or directory does not exist.");
|
||||
}
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`listening on port ${port}`);
|
||||
});
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"default-registry": {
|
||||
"kind": "git",
|
||||
"baseline": "4334d8b4c8916018600212ab4dd4bbdc343065d1",
|
||||
"baseline": "afc0a2e01ae104a2474216a2df0e8d78516fd5af",
|
||||
"repository": "https://github.com/microsoft/vcpkg"
|
||||
},
|
||||
"registries": [
|
||||
|
|
|
|||
18
vcpkg.json
18
vcpkg.json
|
|
@ -2,7 +2,10 @@
|
|||
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json",
|
||||
"dependencies": [
|
||||
"asyncplusplus",
|
||||
"curl",
|
||||
{
|
||||
"name": "curl",
|
||||
"platform": "!wasm32"
|
||||
},
|
||||
"doctest",
|
||||
"expected-lite",
|
||||
"glm",
|
||||
|
|
@ -24,7 +27,10 @@
|
|||
"zlib-ng",
|
||||
"picosha2",
|
||||
"earcut-hpp",
|
||||
"cpp-httplib",
|
||||
{
|
||||
"name": "cpp-httplib",
|
||||
"platform": "!wasm32"
|
||||
},
|
||||
"libmorton",
|
||||
"zstd",
|
||||
{
|
||||
|
|
@ -33,14 +39,16 @@
|
|||
"features": [
|
||||
{
|
||||
"name": "jit",
|
||||
"platform": "!ios"
|
||||
"platform": "!ios&!wasm32"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "asmjit",
|
||||
"platform": "!ios"
|
||||
}
|
||||
"platform": "!ios&!wasm32"
|
||||
},
|
||||
"spz",
|
||||
"zlib"
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue