three.js - 将模型加载到 a-entity
问题描述
我正在尝试将模型有条件地加载到一个实体中。这样做的原因是我有一个场景,我想让用户选择是否加载大型模型。到目前为止,我有一个包含以下实体的场景:
id="modelname-entity"
scale="2 2 2"
position="0 0 -5"
drag-rotate="rotateY:false;"
model-rotate-loadprogress="modelUrl:modelname.gltf;modelRef:modelname-model"
></a-entity>
它有一个model-rotate-loadprogress
使用 THREE.js 语法加载 gltf 模型的组件:
AFRAME.registerComponent('model-rotate-loadprogress',{
schema : {
modelUrl: {
type: "string"
},
modelRef: {
type: "string"
}
},
init : function(){
this.loadModel();
},
loadModel: function() {
if (!this.data.modelUrl || !this.data.modelRef) {
console.warn("Model details not given for model rotate loader");
return;
}
if ( document.getElementById(this.data.modelRef) ) {
console.warn("Assets already has an asset with the ID of " , this.data.modelRef );
}
// Using THREE.js file loader
var dis = this;
var loader = new THREE.GLTFLoader().setPath( '/assets/static/models/' );
loader.load(
this.data.modelUrl,
gltf => {
// Add the model to the scene for now.
dis.el.sceneEl.object3D.add(gltf.scene);
},
xhr => {
console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
},
error => {
console.error( error );
}
);
}
}
模型加载并显示到场景中,但是如何将它附加到实体上呢?
解决方案
我得到模型的填充<a-entity>
方式与我将它附加到场景的方式类似。这是最终的代码:
loadGLTFModel: function() {
var dis = this;
var loader = new THREE.GLTFLoader().setPath( this.PATH_MODELS );
loader.load(
`${this.PATH_MODELS}${this.data.gltfModel}`,
gltf => {
dis.el.object3D.add(gltf.scene)
},
progress => {
this.onProgress(progress);
},
error => {
console.error( "ERROR : " , error );
}
);
},
onProgress: function(progress) {
this.progressBar.setAttribute("geometry", {
thetaLength: (progress.loaded / progress.total * 360)
})
},
如果我将重型模型添加到<a-assets>
推荐的处理方式中,将导致整个应用程序被阻塞,直到所有资产都加载并准备好。在我的场景中,用户可以选择跳过下载。如果用户选择加载模型,那么他/她会得到一个更新的进度条(实际上是一个环)。下面是如何加载 obj 和 mtl 模型的代码:
loadOBJModel: function() {
var dis = this;
if (!this.data.mtlMaterial) {
console.error("No material given for model");
return;
}
var mtlLoader = new THREE.MTLLoader();
mtlLoader.load(
`${this.PATH_MODELS}${this.data.mtlMaterial}`,
materials => {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( this.PATH_MODELS );
objLoader.load(
this.data.objModel,
object => {
dis.el.object3D.add(object)
},
progress => {
this.onProgress(progress);
},
error => {
console.error( "ERROR : " , error );
}
);
}
);
},