diff --git a/common/api/core-frontend.api.md b/common/api/core-frontend.api.md index b40ba285ce5f..efc0eb042164 100644 --- a/common/api/core-frontend.api.md +++ b/common/api/core-frontend.api.md @@ -8430,7 +8430,7 @@ export class RealityTile extends Tile { selectSecondaryTiles(_args: TileDrawArgs, _context: TraversalSelectionContext): void; // @internal (undocumented) setContent(content: RealityTileContent): void; - // @internal (undocumented) + // @internal readonly transformToRoot?: Transform; // @internal (undocumented) readonly tree: RealityTileTree; diff --git a/common/changes/@itwin/core-frontend/eringram-reprojectgeometry-bugfix_2025-12-01-20-32.json b/common/changes/@itwin/core-frontend/eringram-reprojectgeometry-bugfix_2025-12-01-20-32.json new file mode 100644 index 000000000000..ac11a63efe7e --- /dev/null +++ b/common/changes/@itwin/core-frontend/eringram-reprojectgeometry-bugfix_2025-12-01-20-32.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/core-frontend", + "comment": "", + "type": "none" + } + ], + "packageName": "@itwin/core-frontend" +} \ No newline at end of file diff --git a/core/frontend/src/internal/tile/RealityModelTileTree.ts b/core/frontend/src/internal/tile/RealityModelTileTree.ts index 3b75afeac28e..6ef9ca94e056 100644 --- a/core/frontend/src/internal/tile/RealityModelTileTree.ts +++ b/core/frontend/src/internal/tile/RealityModelTileTree.ts @@ -534,6 +534,7 @@ class RealityModelTileLoader extends RealityTileLoader { const thisParentId = parentId.length ? (`${parentId}_${childId}`) : childId; if (foundChild.transform) { const thisTransform = RealityModelTileUtils.transformFromJson(foundChild.transform); + // Accumulate tile's transform to apply it to this tile's children transformToRoot = transformToRoot ? transformToRoot.multiplyTransformTransform(thisTransform) : thisTransform; } diff --git a/core/frontend/src/internal/tile/RealityTileLoader.ts b/core/frontend/src/internal/tile/RealityTileLoader.ts index 88b6b0b1bb12..17832d996bc7 100644 --- a/core/frontend/src/internal/tile/RealityTileLoader.ts +++ b/core/frontend/src/internal/tile/RealityTileLoader.ts @@ -88,7 +88,13 @@ export abstract class RealityTileLoader { if (reader) reader.defaultWrapMode = GltfWrapMode.ClampToEdge; - const geom = reader?.readGltfAndCreateGeometry(tile.tree.iModelTransform); + let transform = tile.tree.iModelTransform; + if (tile.transformToRoot) { + transform = transform.multiplyTransformTransform(tile.transformToRoot); + } + + const geom = reader?.readGltfAndCreateGeometry(transform); + // See RealityTileTree.reprojectAndResolveChildren for how reprojectionTransform is calculated const xForm = tile.reprojectionTransform; if (tile.tree.reprojectGeometry && geom?.polyfaces && xForm) { const polyfaces = geom.polyfaces.map((pf) => pf.cloneTransformed(xForm)); diff --git a/core/frontend/src/tile/RealityTile.ts b/core/frontend/src/tile/RealityTile.ts index 7fb851901009..63c240735903 100644 --- a/core/frontend/src/tile/RealityTile.ts +++ b/core/frontend/src/tile/RealityTile.ts @@ -56,7 +56,9 @@ const scratchFrustum = new Frustum(); * @public */ export class RealityTile extends Tile { - /** @internal */ + /** Transform to go from tile's local coordinate system to the root tile's corodinate system. + * @see [[RealityModelTileLoader.findTileInJson]] to see how the transformToRoot is calculated. + * @internal */ public readonly transformToRoot?: Transform; /** @internal */ public readonly additiveRefinement?: boolean; diff --git a/core/frontend/src/tile/RealityTileTree.ts b/core/frontend/src/tile/RealityTileTree.ts index 1548216b836f..fc8f698d296d 100644 --- a/core/frontend/src/tile/RealityTileTree.ts +++ b/core/frontend/src/tile/RealityTileTree.ts @@ -415,6 +415,7 @@ export class RealityTileTree extends TileTree { const reprojectedCoords = response.iModelCoords; const dbToRoot = expectDefined(rootToDb.inverse()); + // Interpolate between the original and reprojected points const getReprojectedPoint = (original: Point3d, reprojectedXYZ: XYZProps) => { scratchPoint.setFromJSON(reprojectedXYZ); const cartesianDistance = this.cartesianRange.distanceToPoint(scratchPoint);