0

I'm am trying to set loading counter for gltf file. Problem is that, my file is gltf, not glb, so I have three files (.gltf .bin .jpg). When I set onProgress callback for gltf file, it does not handle those files (.bin and .jpg), so I get 100% on the start of loading. How can I set onProgress callback to calculate all three files?

const gltfLoader = new GLTFLoader();

// Show loader while the glTF is loading
document.getElementById('loader').style.display = 'block';

// Hide loader when done
  function hideLoader() {
    const loaderContainer = document.getElementById('loader');
    loaderContainer.style.display = 'none';
  }

// LOADING ELEMENTS FROM GLTF //
gltfLoader.load('./Model/Model.gltf', function (gltf) {
    scene.add(gltf.scene);
   // Hide the loader when loading completes
   hideLoader();

function (xhr) {
    // Update progress percentage
    const loaderText = document.getElementById('loader-text');
    
    let progress = 0;
    if (xhr.total && xhr.total > 0) {
      progress = Math.round((xhr.loaded / xhr.total) * 100);
    }     
    loaderText.textContent = `${progress}%`;
},
function (error) {
// Handle loading error
console.error('An error occurred while loading the model:', error);
}
);

1 Answer 1

1

You should use LoadingManager since it handles the progress of all associated files.

import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);
camera.position.z = 1;
camera.position.y = 0.5;

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

const loadingManager = new THREE.LoadingManager();

const loaderContainer = document.getElementById("loader");
const loaderText = document.getElementById("loader-text");

loadingManager.onStart = function () {
  loaderContainer.style.display = "flex";
  loaderText.textContent = `Loading... 0%`;
};

loadingManager.onProgress = function (url, itemsLoaded, itemsTotal) {
  const progress = Math.round((itemsLoaded / itemsTotal) * 100);
  loaderText.textContent = `Loading... ${progress}%`;
};

loadingManager.onLoad = function () {
  loaderContainer.style.display = "none";
};

const gltfLoader = new GLTFLoader(loadingManager);

gltfLoader.load("./static/FlightHelmet.gltf", (gltf) => {
  scene.add(gltf.scene);
});

const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(5, 5, 5);
scene.add(light);

function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}
animate();

Sandbox

Sign up to request clarification or add additional context in comments.

4 Comments

But with this line: "const progress = Math.round((itemsLoaded / itemsTotal) * 100)", I will get progress bar calculated with number of files. I want to be calculated with total size of all dependent files.
I'm not sure why you need to create this loader based on the size... But if so, you need to fetch the size - when you don't know the sizes... because if you know sizes, you'll need to calculate everything and simulate the loader, and then connect it to the LoadingManager.
With code that count number of files loaded, and represent that as %, I got 25%, 50%, 75%. This is some kind of boring, and time between steps is different because of different size of files (1 MB, 300 MB). My intention is to track loading of all three or more file, and represent that with steps of 1%, so I will have counter 1-100. Maybe i can take size of files from Headers/content-length, to get final sum of bytes that should be loaded (itemsTotal), but how to follow how many bytes is loaded (itemsLoaded)?
As I wrote, you have two options: 1. If you don't know the file sizes, you need to fetch them dynamically (eg. using a HEAD request) and pass the retrieved information to the manager; 2. If you already know the file sizes, you can use this data directly to calculate progress, avoiding dynamic fetching.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.