如何让我的 gltf 加载程序在 three.js 中同步?
How do I make my gltf loader synchronous in three.js?
这是我的代码,我试图使 loadCone()
与 await/async 同步,但它不起作用。
import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import conePath from "../../static/cone.glb";
import coneBaked from "../../static/coneBake.png";
import "regenerator-runtime/runtime";
export default class Cone {
constructor() {
this.cone;
const textureLoader = new THREE.TextureLoader();
const bakedTexture = textureLoader.load(coneBaked);
const bakedMaterial = new THREE.MeshBasicMaterial({
map: bakedTexture,
});
this.loadCone();
}
async loadCone() {
// GLTF loader
const gltfLoader = new GLTFLoader();
const cone = await gltfLoader.load(
conePath,
(gltf) => {
console.log("success");
console.log(gltf.scene);
this.cone = gltf.scene;
},
(progress) => {
// console.log("progress");
// console.log(progress);
},
(error) => {
console.log("error");
console.log(error);
}
);
}
getCone() {
return this.cone;
}
}
在另一个文件中我有这个:
const cone = new Cone();
this.scene.add(cone.getCone());
但是,因为 getCone()
是同步的,它会在我的 loadCone()
加载圆锥之前执行,所以我得到 undefined
而不是圆锥。
如何使我的函数 asynch loadCone()
同步?我试过 *.loadAsync()` 但它没有改变任何东西。
提前致谢。我没有收到任何错误,除了它说“undefined is not instance of THREE.Object.3d”,我希望它说的。
根据文档,有一个来自 threejs 加载器的 loadAsync 方法,您可以按如下方式使用。
await gltfLoader.loadAsync( 'model.gltf' ),
我不太明白你在做什么。
我用这个成功了:
// Load a glTF resource
async loadGltf(url) {
// console.log('===== start loadGltf async')
let urlString = url.toString() // load doesn't like the url structure; it requires a string and then builds it up again
let gltf = await gltfLoader.loadAsync(urlString)
// console.log('========== end loadGltf')
return gltf
}
根据结果,访问result.scene
我不知道 three.js,但是 new
需要同步 return 一个初始化对象,所以它不能(或调用其他东西)异步。
// ...
constructor() {
this.cone;
const textureLoader = new THREE.TextureLoader();
const bakedTexture = textureLoader.load(coneBaked);
const bakedMaterial = new THREE.MeshBasicMaterial({
map: bakedTexture,
});
// don't call an async method here
// this.loadCone();
}
//...
在来电方...
import Cone from 'path to js that defines the class'
// inside an async function
async function doConeStuff() {
const cone = new Cone();
await cone.loadCone();
this.scene.add(cone.getCone());
}
// or, at the top level
const cone = new Cone();
cone.loadCone().then(() => {
this.scene.add(cone.getCone())
});
注意到 loadCone
混淆了承诺和回调,我们可以承诺您正在使用的版本,或者采纳@Leon.Z 关于 promise-returning 版本的建议。如果那个有效(同样,我不知道 three.js),那么圆锥体 class 可以像这样简化...
export default class Cone {
constructor() {
const textureLoader = new THREE.TextureLoader();
const bakedTexture = textureLoader.load(coneBaked);
const bakedMaterial = new THREE.MeshBasicMaterial({
map: bakedTexture,
});
this.cone = null;
}
async loadCone() {
// GLTF loader
if (this.cone) Promise.resolve(this.cone);
const giltf = await gltfLoader.loadAsync( 'model.gltf' ),
this.cone = gilt.scene;
return this.cone;
}
getCone() { return this.cone; }
}
最后,如果由于某种原因,@Leon.Z 对 promise 方法不正确,请按以下方式对加载程序进行 promise...
async loadCone() {
const gltfLoader = new GLTFLoader();
return new Promise((resolve, reject) => {
gltfLoader.load(
conePath,
gltf => resolve(gilt.scene),
error => reject(error)
);
});
}
这是我的代码,我试图使 loadCone()
与 await/async 同步,但它不起作用。
import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import conePath from "../../static/cone.glb";
import coneBaked from "../../static/coneBake.png";
import "regenerator-runtime/runtime";
export default class Cone {
constructor() {
this.cone;
const textureLoader = new THREE.TextureLoader();
const bakedTexture = textureLoader.load(coneBaked);
const bakedMaterial = new THREE.MeshBasicMaterial({
map: bakedTexture,
});
this.loadCone();
}
async loadCone() {
// GLTF loader
const gltfLoader = new GLTFLoader();
const cone = await gltfLoader.load(
conePath,
(gltf) => {
console.log("success");
console.log(gltf.scene);
this.cone = gltf.scene;
},
(progress) => {
// console.log("progress");
// console.log(progress);
},
(error) => {
console.log("error");
console.log(error);
}
);
}
getCone() {
return this.cone;
}
}
在另一个文件中我有这个:
const cone = new Cone();
this.scene.add(cone.getCone());
但是,因为 getCone()
是同步的,它会在我的 loadCone()
加载圆锥之前执行,所以我得到 undefined
而不是圆锥。
如何使我的函数 asynch loadCone()
同步?我试过 *.loadAsync()` 但它没有改变任何东西。
提前致谢。我没有收到任何错误,除了它说“undefined is not instance of THREE.Object.3d”,我希望它说的。
根据文档,有一个来自 threejs 加载器的 loadAsync 方法,您可以按如下方式使用。
await gltfLoader.loadAsync( 'model.gltf' ),
我不太明白你在做什么。
我用这个成功了:
// Load a glTF resource
async loadGltf(url) {
// console.log('===== start loadGltf async')
let urlString = url.toString() // load doesn't like the url structure; it requires a string and then builds it up again
let gltf = await gltfLoader.loadAsync(urlString)
// console.log('========== end loadGltf')
return gltf
}
根据结果,访问result.scene
我不知道 three.js,但是 new
需要同步 return 一个初始化对象,所以它不能(或调用其他东西)异步。
// ...
constructor() {
this.cone;
const textureLoader = new THREE.TextureLoader();
const bakedTexture = textureLoader.load(coneBaked);
const bakedMaterial = new THREE.MeshBasicMaterial({
map: bakedTexture,
});
// don't call an async method here
// this.loadCone();
}
//...
在来电方...
import Cone from 'path to js that defines the class'
// inside an async function
async function doConeStuff() {
const cone = new Cone();
await cone.loadCone();
this.scene.add(cone.getCone());
}
// or, at the top level
const cone = new Cone();
cone.loadCone().then(() => {
this.scene.add(cone.getCone())
});
注意到 loadCone
混淆了承诺和回调,我们可以承诺您正在使用的版本,或者采纳@Leon.Z 关于 promise-returning 版本的建议。如果那个有效(同样,我不知道 three.js),那么圆锥体 class 可以像这样简化...
export default class Cone {
constructor() {
const textureLoader = new THREE.TextureLoader();
const bakedTexture = textureLoader.load(coneBaked);
const bakedMaterial = new THREE.MeshBasicMaterial({
map: bakedTexture,
});
this.cone = null;
}
async loadCone() {
// GLTF loader
if (this.cone) Promise.resolve(this.cone);
const giltf = await gltfLoader.loadAsync( 'model.gltf' ),
this.cone = gilt.scene;
return this.cone;
}
getCone() { return this.cone; }
}
最后,如果由于某种原因,@Leon.Z 对 promise 方法不正确,请按以下方式对加载程序进行 promise...
async loadCone() {
const gltfLoader = new GLTFLoader();
return new Promise((resolve, reject) => {
gltfLoader.load(
conePath,
gltf => resolve(gilt.scene),
error => reject(error)
);
});
}