NASA-AMMOS / 3DTilesRendererJS

Renderer for 3D Tiles in Javascript using three.js
https://nasa-ammos.github.io/3DTilesRendererJS/example/bundle/mars.html
Apache License 2.0
1.47k stars 266 forks source link

3D Tiles model not loading with 3DTilesRendererJS #506

Closed lanvada closed 3 months ago

lanvada commented 3 months ago

Description

I am experiencing an issue where my 3D Tiles model is not loading using 3DTilesRendererJS in a Three.js scene. The model is known to load and display correctly in Cesium, but when attempting to load the same model in Three.js using 3DTilesRendererJS, there is no visible output or errors in the console. The network tab indicates that only the tileset.json file is being requested.

I am attaching the model and the relevant code snippet. Any guidance or assistance in resolving this issue would be greatly appreciated. rac_basic_sample_project.zip

Steps to Reproduce

  1. Set up a basic Three.js scene.
  2. Initialize 3DTilesRendererJS with the path to tileset.json.
  3. Add the rendered group to the scene.
  4. Call the update method on the TilesRenderer within the animation loop.

Expected Behavior

The 3D Tiles model should load and be visible in the Three.js scene, as it does in Cesium.

Actual Behavior

The model does not appear in the Three.js scene. There are no errors in the console, and only the tileset.json file is requested without any subsequent tile requests.

Code Snippet

import * as THREE from 'three';
import { TilesRenderer } from '3d-tiles-renderer';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

const localMinioAddress = import.meta.env.VITE_LOCAL_MINIO_ADDRESS;
// Create a renderer
const renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xd8cec0);
// Append the renderer to the DOM
const container = document.getElementById('threeContainer')!;
container.appendChild(renderer.domElement);
// Create a scene and a camera
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000,
);
// Set the position of the camera
camera.position.set(20, 10, 20);
const controls = new OrbitControls(camera, renderer.domElement);
// update the camera position and controls target
const center = new THREE.Vector3();
new THREE.Box3().setFromObject(scene).getCenter(center);
camera.position.set(center.x, center.y + 1, center.z);
controls.target.set(center.x, center.y + 1, center.z + 2);
controls.update();

// lights
const dirLight = new THREE.DirectionalLight(0xffffff);
dirLight.position.set(1, 2, 3);
scene.add(dirLight);
const ambLight = new THREE.AmbientLight(0xffffff, 0.2);
scene.add(ambLight);

// Add the environment
const environment = new RoomEnvironment(renderer);
scene.add(environment);

// Add the tiles parent
const tilesParent = new THREE.Group();
tilesParent.rotation.set(Math.PI / 2, 0, 0);
scene.add(tilesParent);

const url = `${localMinioAddress}rac_basic_sample_project/tileset.json`;
// Create a 3D Tiles Renderer
const tilesRenderer = new TilesRenderer(url);
tilesParent.add(tilesRenderer.group);
tilesRenderer.fetchOptions.mode = 'cors';
console.debug(tilesRenderer);

function animate() {
  requestAnimationFrame(animate);

  camera.updateMatrixWorld();

  tilesRenderer.setCamera(camera);
  tilesRenderer.setResolutionFromRenderer(camera, renderer);
  tilesRenderer.update();

  // Render the scene
  renderer.render(scene, camera);
}

animate();
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Demo</title>
  <style>
    html,
    body {
      margin: 0;
      padding: 0;
      width: 100%;
      height: 100%;
    }
    #threeContainer {
      width: 100%;
      height: 100%;
    }
  </style>
</head>

<body>
  <div id="threeContainer"></div>
  <script type="module" src="./tilesRenderRaw.ts"></script>
  </div>
</body>

</html>

Additional Notes

The project is built using Vite. To run the project without Vite, the relevant JavaScript files need to be included manually in the HTML or a standalone build needs to be created using a module bundler.

gkjohnson commented 3 months ago

The model is visible and loadable in the main "kitchen sink" example in the project:

image

The file is very far offset center because it looks as thought it's designed for use on the surface of a globe tile set. If you'd like to center the model at the origin you'll have to center it based on the bounding boxes (see the example page).

Also see https://github.com/NASA-AMMOS/3DTilesRendererJS/issues/395 for related discussions.

lanvada commented 3 months ago

The model is visible and loadable in the main "kitchen sink" example in the project:

image

The file is very far offset center because it looks as thought it's designed for use on the surface of a globe tile set. If you'd like to center the model at the origin you'll have to center it based on the bounding boxes (see the example page).

Also see #395 for related discussions.

Thank you for your prompt response and for pointing me towards the example page and issue #395 for guidance on centering the model. I attempted to center the model at the origin by calculating the bounding box as suggested. However, I seem to be running into an issue extracting the correct values for the bounding box. Here's the TypeScript code snippet I used:

const box = new THREE.Box3();
const sphere = new THREE.Sphere();

// Attempt to update tiles center
if (tilesRenderer.getBoundingBox(box)) {
  box.getCenter(tilesRenderer.group.position).multiplyScalar(-1);
  tilesRenderer.group.position.multiplyScalar(-1);
} else if (tilesRenderer.getBoundingSphere(sphere)) {
  tilesRenderer.group.position.copy(sphere.center).multiplyScalar(-1);
}

console.debug('Bounding Box:', box);
console.debug('Bounding Sphere:', sphere);

When I run this code, the console output for the bounding box and sphere does not seem to reflect the expected values. image Could you provide any insights on what might be going wrong? Is there a specific step or adjustment that I might be missing? Any further assistance would be greatly appreciated.

Additionally, I've noticed that in Cesium, as well as with the 3D Tiles specification, the position of the tileset can be adjusted by modifying the transform attribute in the root tile node. This feature is quite useful for aligning models in non-geospatial contexts. In my current usage of 3DTilesRendererJS, I couldn't locate a similar attribute or method that allows for such transformations. The ability to manipulate the root transform directly, or at least to clear any transforms present in the root and other tiles, would be incredibly beneficial for displaying models in a non-geographic space within Three.js. Do you have plans to incorporate a feature in 3DTilesRendererJS that would allow for adjusting the root tile transform? Or is there an existing approach to reset or clear the transforms in the root and other tiles that I might have overlooked?

I look forward to your thoughts on this matter.

gkjohnson commented 3 months ago

Could you provide any insights on what might be going wrong? Is there a specific step or adjustment that I might be missing?

Additionally, I've noticed that in Cesium, as well as with the 3D Tiles specification, the position of the tileset can be adjusted by modifying the transform attribute in the root tile node. This feature is quite useful for aligning models in non-geospatial contexts. In my current usage of 3DTilesRendererJS, I couldn't locate a similar attribute or method that allows for such transformations.

Please read the documentation for the class members and functions you are using instead of just copying the code. The descriptions for the bounding box and bounding sphere functions should answer your question. group is also described in the docs as the container group for the 3d tiles objects.

If you have more specific questions from the documentation I can answer those here but please take a look at the README.