I have two glb files, loadingScene.glb and mainScene.glb. The loadingScene.glb file consists of three meshes- text, a plane(to receive shadows), and a cactus that I’m using as part of a loading screen displayed to the user, while the mainScene.glb and all of its associated assets are still loading. In order to indicate the loading progress, I wanted to have a little fun and have a shadow shift from the left to the right to suggest the current loading progress(pictured below).
Therefore, I needed the loadingScene.glb file to load first, then after, I load the mainScene.glb content. I achieved this in the THREE.LoadingManager() onProgress callback by checking for when itemUrl==="./loadingScene.glb"
, indicating that, that file has been loaded, then calling a loadMainScene()
function which then loads the mainScene.glb. However, when I added a console.log("itemUrl", itemUrl)
inside of the onProgress callback, I see ./mainScene.glb multiple times, indicating that it is loading more than once. Why is this?
import * as THREE from "three"
import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader.js"
import {RGBELoader} from "three/examples/jsm/loaders/RGBELoader.js"
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls.js"
const gScene = new THREE.Scene()
const canvas = document.querySelector("#c")
const gCamera = new THREE.PerspectiveCamera(50, canvas.clientWidth/canvas.clientHeight, 0.1, 1000)
const gRenderer = new THREE.WebGLRenderer({canvas, alpha: true, antialias: true})
gRenderer.setPixelRatio( window.devicePixelRatio );
gRenderer.setSize( window.innerWidth, window.innerHeight );
gRenderer.toneMapping = THREE.ACESFilmicToneMapping;
gRenderer.shadowMap.enabled = true
gRenderer.toneMappingExposure = 1;
gRenderer.outputEncoding = THREE.sRGBEncoding;
gCamera.position.x = 24
gCamera.position.y = 123
gCamera.position.z = 0
const loadingManager = new THREE.LoadingManager(
() => {
},
(itemUrl, itemsLoaded, itemsTotal) =>
{
console.log("itemUrl", itemUrl)
if(itemUrl === "./loadingScene.glb"){
loadMainScene()
}
let loadedRatio = itemsLoaded / itemsTotal
if(directionalLight.position.z < 30){
directionalLight.position.set(-20, 130, -30 + (60 * loadedRatio))
}
}
)
const gltfLoader = new GLTFLoader(loadingManager)
function loadMainScene(){
gltfLoader.load('./mainScene.glb', (glb) => {
})
}
const controls = new OrbitControls(gCamera, canvas)
controls.target.set(0,0,0)
controls.update()
const directionalLight = new THREE.DirectionalLight(0xffffff, 5)
directionalLight.castShadow = true
directionalLight.position.set(-10, 130, -30)
directionalLight.target.position.set(7.5, 115,0)
directionalLight.shadow.camera['left'] = -15
directionalLight.shadow.camera['right'] = 15
directionalLight.shadow.camera['bottom'] = -15
directionalLight.shadow.camera['top'] = 15
directionalLight.shadow.mapSize.width = 1024
directionalLight.shadow.mapSize.height = 1024
directionalLight.shadow.camera.updateProjectionMatrix();
gScene.add(directionalLight)
gScene.add(directionalLight.target)
gCamera.lookAt(7.5,115,0)
gltfLoader.load('./loadingScene.glb', (glb) => {
glb.scene.traverse((child) => {
if(child.isMesh){
if(child.name.toLowerCase().includes('backdrop')){
child.material = new THREE.ShadowMaterial()
child.receiveShadow = true
}
else if(child.name.toLowerCase().includes("saguaro")){
child.material = new THREE.MeshBasicMaterial({color:0x000000})
child.castShadow = true
}
else{
child.material = new THREE.MeshBasicMaterial({color:0x1a1004})
child.castShadow = true
}
}
})
gScene.add(glb.scene)
})
window.addEventListener('resize', onWindowResize)
function onWindowResize(){
gCamera.aspect = window.innerWidth / window.innerHeight
gCamera.updateProjectionMatrix()
gRenderer.setSize(window.innerWidth, window.innerHeight)
}
function render(){
gRenderer.render(gScene,gCamera)
requestAnimationFrame(render)
}
requestAnimationFrame(render)