Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I3dm misc fixes #912

Merged
merged 14 commits into from
Jun 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@

##### Fixes :wrench:

- When a 3D Tiles Instanced 3D Mesh (i3dm) file contains an instance transform that cannot be decomposed into position, rotation, and scale, a warning will now be logged and an identity transformation will be used. Previously, an undefined transformation would be used.
- Fixed several problems with the loader for the 3D Tiles Instanced 3D Mesh (i3dm) format:
- When an instance transform cannot be decomposed into position, rotation, and scale, a warning will now be logged and an identity transformation will be used. Previously, an undefined transformation would be used.
- The `gltfUpAxis` property is now accounted for, if present.
- Paths to images in i3dm content are now resolved correctly.
- Extraneous spaces at the end of an external glTF URI are now ignored. These are sometimes added as padding in order to meet alignment requirements.
- Removed an overly-eager degenerate triangle test in the 2D version of `IntersectionTests::pointInTriangle` that could discard intersections in small - but valid - triangles.
- Fixed a bug while upsampling tiles for raster overlays that could cause them to have an incorrect bounding box, which in some cases would lead to the raster overlay being missing entirely from the upsampled tile.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ struct BinaryToGltfConverter {
private:
static GltfConverterResult convertImmediate(
const gsl::span<const std::byte>& gltfBinary,
const CesiumGltfReader::GltfReaderOptions& options);
const CesiumGltfReader::GltfReaderOptions& options,
const AssetFetcher& assetFetcher);
static CesiumGltfReader::GltfReader _gltfReader;
};
} // namespace Cesium3DTilesContent
16 changes: 10 additions & 6 deletions Cesium3DTilesContent/include/Cesium3DTilesContent/GltfConverters.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <Cesium3DTilesContent/GltfConverterResult.h>
#include <CesiumAsync/Future.h>
#include <CesiumAsync/IAssetAccessor.h>
#include <CesiumGeometry/Axis.h>
#include <CesiumGltfReader/GltfReader.h>

#include <gsl/span>
Expand All @@ -30,21 +31,24 @@ struct CESIUM3DTILESCONTENT_API AssetFetcher {
const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor_,
const std::string& baseUrl_,
const glm::dmat4 tileTransform_,
const std::vector<CesiumAsync::IAssetAccessor::THeader>& requestHeaders_)
const std::vector<CesiumAsync::IAssetAccessor::THeader>& requestHeaders_,
CesiumGeometry::Axis upAxis_)
: asyncSystem(asyncSystem_),
pAssetAccessor(pAssetAccessor_),
baseUrl(baseUrl_),
tileTransform(tileTransform_),
requestHeaders(requestHeaders_) {}
requestHeaders(requestHeaders_),
upAxis(upAxis_) {}

CesiumAsync::Future<AssetFetcherResult>
get(const std::string& relativeUrl) const;

const CesiumAsync::AsyncSystem& asyncSystem;
const std::shared_ptr<CesiumAsync::IAssetAccessor> pAssetAccessor;
const std::string baseUrl;
CesiumAsync::AsyncSystem asyncSystem;
std::shared_ptr<CesiumAsync::IAssetAccessor> pAssetAccessor;
std::string baseUrl;
glm::dmat4 tileTransform; // For ENU transforms in i3dm
const std::vector<CesiumAsync::IAssetAccessor::THeader>& requestHeaders;
std::vector<CesiumAsync::IAssetAccessor::THeader> requestHeaders;
CesiumGeometry::Axis upAxis;
};

/**
Expand Down
10 changes: 8 additions & 2 deletions Cesium3DTilesContent/src/BinaryToGltfConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@ CesiumGltfReader::GltfReader BinaryToGltfConverter::_gltfReader;

GltfConverterResult BinaryToGltfConverter::convertImmediate(
const gsl::span<const std::byte>& gltfBinary,
const CesiumGltfReader::GltfReaderOptions& options) {
const CesiumGltfReader::GltfReaderOptions& options,
const AssetFetcher& assetFetcher) {
CesiumGltfReader::GltfReaderResult loadedGltf =
_gltfReader.readGltf(gltfBinary, options);

if (loadedGltf.model) {
loadedGltf.model->extras["gltfUpAxis"] =
static_cast<std::underlying_type_t<CesiumGeometry::Axis>>(
assetFetcher.upAxis);
}
GltfConverterResult result;
result.model = std::move(loadedGltf.model);
result.errors.errors = std::move(loadedGltf.errors);
Expand All @@ -22,6 +28,6 @@ CesiumAsync::Future<GltfConverterResult> BinaryToGltfConverter::convert(
const CesiumGltfReader::GltfReaderOptions& options,
const AssetFetcher& assetFetcher) {
return assetFetcher.asyncSystem.createResolvedFuture(
convertImmediate(gltfBinary, options));
convertImmediate(gltfBinary, options, assetFetcher));
}
} // namespace Cesium3DTilesContent
112 changes: 75 additions & 37 deletions Cesium3DTilesContent/src/I3dmToGltfConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <CesiumGltfContent/GltfUtilities.h>
#include <CesiumUtility/AttributeCompression.h>
#include <CesiumUtility/Math.h>
#include <CesiumUtility/Uri.h>

#include <glm/gtx/matrix_decompose.hpp>

Expand Down Expand Up @@ -420,8 +421,8 @@ CesiumAsync::Future<ConvertedI3dm> convertI3dmContent(
CesiumGeospatial::LocalHorizontalCoordinateSystem enu(
(glm::dvec3(worldPos)));
const glm::dmat4& ecef = enu.getLocalToEcefTransformation();
// Express the rotation in the tile's coordinate system, like explicit
// I3dm instance rotations.
// Express the rotation in the tile's coordinate system, just like
// explicit i3dm instance rotations.
glm::dmat4 tileFrame = worldTransformInv * ecef;
return rotationFromUpRight(
glm::vec3(tileFrame[1]),
Expand Down Expand Up @@ -454,44 +455,81 @@ CesiumAsync::Future<ConvertedI3dm> convertI3dmContent(
});
}
repositionInstances(decodedInstances);
AssetFetcherResult assetFetcherResult;
std::string baseUri;
if (header.gltfFormat == 0) {
// Recursively fetch and read the glTF content.
auto gltfUri = std::string(
reinterpret_cast<const char*>(gltfData.data()),
gltfData.size());
return assetFetcher.get(gltfUri)
.thenImmediately(
[options, assetFetcher](AssetFetcherResult&& assetFetcherResult)
-> CesiumAsync::Future<GltfConverterResult> {
if (assetFetcherResult.errorList.hasErrors()) {
GltfConverterResult errorResult;
errorResult.errors.merge(assetFetcherResult.errorList);
return assetFetcher.asyncSystem.createResolvedFuture(
std::move(errorResult));
}
return BinaryToGltfConverter::convert(
assetFetcherResult.bytes,
options,
assetFetcher);
})
.thenImmediately([convertedI3dm = std::move(convertedI3dm)](
GltfConverterResult&& converterResult) mutable {
if (converterResult.model)
convertedI3dm.gltfResult.model = std::move(converterResult.model);
convertedI3dm.gltfResult.errors.merge(converterResult.errors);
return convertedI3dm;
// The spec says that the URL can be padded with ' ' (0x20) characters in
// order to make the size of the whole i3dm file 8-byte aligned.
auto rLastNotSpace =
std::find_if_not(gltfData.rbegin(), gltfData.rend(), [](auto&& b) {
return b == std::byte(' ');
});
auto spaceDistance = static_cast<size_t>(gltfData.rend() - rLastNotSpace);
std::string gltfUri(
reinterpret_cast<const char*>(gltfData.data()),
spaceDistance);
baseUri = CesiumUtility::Uri::resolve(assetFetcher.baseUrl, gltfUri);
} else {
return BinaryToGltfConverter::convert(gltfData, options, assetFetcher)
.thenImmediately([convertedI3dm = std::move(convertedI3dm)](
GltfConverterResult&& converterResult) mutable {
if (converterResult.model)
convertedI3dm.gltfResult.model = std::move(converterResult.model);
convertedI3dm.gltfResult.errors.merge(converterResult.errors);
return convertedI3dm;
});
}
baseUri = assetFetcher.baseUrl;
}

auto getGltf = [&]() -> CesiumAsync::Future<GltfConverterResult> {
if (header.gltfFormat == 0) {
// Recursively fetch and read the glTF content.
return assetFetcher.get(baseUri).thenImmediately(
[options, assetFetcher](AssetFetcherResult&& assetFetcherResult)
-> CesiumAsync::Future<GltfConverterResult> {
if (assetFetcherResult.errorList.hasErrors()) {
GltfConverterResult errorResult;
errorResult.errors.merge(assetFetcherResult.errorList);
return assetFetcher.asyncSystem.createResolvedFuture(
std::move(errorResult));
}
return BinaryToGltfConverter::convert(
assetFetcherResult.bytes,
options,
assetFetcher);
});
} else {
return BinaryToGltfConverter::convert(gltfData, options, assetFetcher);
}
};

return getGltf()
.thenImmediately([options, assetFetcher, baseUri](
GltfConverterResult&& converterResult) {
if (converterResult.model.has_value()) {
CesiumGltfReader::GltfReaderResult readerResult{
std::move(*converterResult.model),
{},
{}};
CesiumAsync::HttpHeaders externalRequestHeaders(
assetFetcher.requestHeaders.begin(),
assetFetcher.requestHeaders.end());
return CesiumGltfReader::GltfReader::resolveExternalData(
assetFetcher.asyncSystem,
baseUri,
externalRequestHeaders,
assetFetcher.pAssetAccessor,
options,
std::move(readerResult));
}
return assetFetcher.asyncSystem.createResolvedFuture(
CesiumGltfReader::GltfReaderResult{
std::nullopt,
std::move(converterResult.errors.errors),
{}});
})
.thenImmediately(
[convertedI3dm = std::move(convertedI3dm)](
CesiumGltfReader::GltfReaderResult&& readerResult) mutable {
if (readerResult.model)
convertedI3dm.gltfResult.model = std::move(readerResult.model);
CesiumUtility::ErrorList resolvedExternalErrors{
std::move(readerResult.errors),
{}};
convertedI3dm.gltfResult.errors.merge(resolvedExternalErrors);
return convertedI3dm;
});
}

glm::dmat4
Expand Down
3 changes: 2 additions & 1 deletion Cesium3DTilesContent/test/ConvertTileToGltf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ AssetFetcher ConvertTileToGltf::makeAssetFetcher(const std::string& baseUrl) {
fileAccessor,
baseUrl,
glm::dmat4(1.0),
requestHeaders);
requestHeaders,
CesiumGeometry::Axis::Y);
}

GltfConverterResult ConvertTileToGltf::fromB3dm(
Expand Down
3 changes: 2 additions & 1 deletion Cesium3DTilesSelection/src/ImplicitOctreeLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@ CesiumAsync::Future<TileLoadResult> requestTileContent(
pAssetAccessor,
tileUrl,
tileTransform,
requestHeaders};
requestHeaders,
CesiumGeometry::Axis::Y};
return converter(responseData, gltfOptions, assetFetcher)
.thenImmediately([pLogger, tileUrl, pCompletedRequest, ellipsoid](
GltfConverterResult&& result) {
Expand Down
3 changes: 2 additions & 1 deletion Cesium3DTilesSelection/src/ImplicitQuadtreeLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,8 @@ CesiumAsync::Future<TileLoadResult> requestTileContent(
pAssetAccessor,
tileUrl,
tileTransform,
requestHeaders};
requestHeaders,
CesiumGeometry::Axis::Y};
return converter(responseData, gltfOptions, assetFetcher)
.thenImmediately([ellipsoid, pLogger, tileUrl, pCompletedRequest](
GltfConverterResult&& result) {
Expand Down
3 changes: 2 additions & 1 deletion Cesium3DTilesSelection/src/TilesetJsonLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -939,7 +939,8 @@ TilesetJsonLoader::loadTileContent(const TileLoadInput& loadInput) {
pAssetAccessor,
tileUrl,
tileTransform,
requestHeaders};
requestHeaders,
upAxis};
CesiumGltfReader::GltfReaderOptions gltfOptions;
gltfOptions.ktx2TranscodeTargets =
contentOptions.ktx2TranscodeTargets;
Expand Down
Loading