three.js: 将外部纹理应用到 glTF
three.js: Apply external texture to glTF
我有两个文件:“model.gltf”和“texture.jpeg”。我想将纹理文件应用到模型并使用 three.js 渲染它,但经过 3 天的持续研究和数百次尝试,我无法让它正常工作。我在场景中设置当前对象的方法:
/**
* SET method: Sets object in the scene (deleting previous one)
*
* @author Anton Pernisch <anton@pernisch.dev>
* @param {string} modelPath - Path to object in glTF format
* @param {string} texturePath - Path to texture
* @returns {boolean}
*
* @todo Texture
*/
SET_Object: function(modelPath, texturePath) {
// Clear out the scene
for (var i = this.prodconf3_scene.children.length - 1; i >= 0; i--) {
obj = this.prodconf3_scene.children[i];
this.prodconf3_scene.remove(obj);
}
const modelLoader = new THREE.GLTFLoader();
modelLoader.load(modelPath, (gltf) => {
// HERE? apply texture from texturePath to this gltf
this.prodconf3_obj = gltf.scene;
this.prodconf3_scene.add(this.prodconf3_obj);
});
return true;
}
这段代码导入 glTF 很好,只是黑色。最终,我能够将 .jpeg 纹理应用于此模型,但仅此而已。这是我能得到的最好结果:
here
那是通过这种方法:
/**
* SET method: Sets current object to scene (deleting previous one)
*
* @author Anton Pernisch <anton@pernisch.dev>
* @param {string} modelPath - Path to object in glTF format
* @param {string} texturePath - Path to texture
* @returns {boolean}
*
* @todo Texture
*/
SET_Object: function(modelPath, texturePath) {
// Clear out the scene
for (var i = this.prodconf3_scene.children.length - 1; i >=0 ; i--) {
obj = this.prodconf3_scene.children[i];
this.prodconf3_scene.remove(obj);
}
const modelLoader = new THREE.GLTFLoader();
const textureLoader = new THREE.TextureLoader();
modelLoader.load(modelPath, (gltf) => {
var model = gltf.scene;
model.traverse((o) => {
if (o.isMesh) {
o.material = new THREE.MeshBasicMaterial({map: textureLoader.load(texturePath)});
}
});
this.prodconf3_obj = model;
this.prodconf3_scene.add(this.prodconf3_obj);
});
return true;
}
我还尝试通过 TextureLoader 加载方法创建纹理,然后将其与 modelLoader.load
函数中的 gltf.scene
网格化。那根本不起作用,我得到了
Uncaught TypeError: Cannot read property 'center' of undefined
错误(我不确定使用 gltf.scene
作为 THREE.Mesh()
中的第一个参数)。
所以,我的问题是,在 three.js 中将纹理正确应用到 glTF 的正确和更新方法是什么?
我觉得这很好,但我想知道我们是否应该传递对已加载纹理的引用。
Object3D#Traverse
不是异步的,因此我们必须同步更新 material。
SET_Object: async function(modelPath, texturePath) {
// Clear out the scene
for (let i = this.prodconf3_scene.children.length - 1; i >= 0; i--) {
obj = this.prodconf3_scene.children[i];
this.prodconf3_scene.remove(obj);
}
const modelLoader = new THREE.GLTFLoader();
const textureLoader = new THREE.TextureLoader();
// Load texture
const texture = await textureLoader.loadAsync(texturePath);
texture.flipY = false;
// Load model
const { scene: model } = await modelLoader.loadAsync(modelPath);
// Update model
model.traverse((o) => {
if (o.isMesh) {
o.material.map = texture;
o.material.needsUpdate = true;
}
});
this.prodconf3_obj = model;
this.prodconf3_scene.add(this.prodconf3_obj);
return this.prodconf3_obj;
}
我有两个文件:“model.gltf”和“texture.jpeg”。我想将纹理文件应用到模型并使用 three.js 渲染它,但经过 3 天的持续研究和数百次尝试,我无法让它正常工作。我在场景中设置当前对象的方法:
/**
* SET method: Sets object in the scene (deleting previous one)
*
* @author Anton Pernisch <anton@pernisch.dev>
* @param {string} modelPath - Path to object in glTF format
* @param {string} texturePath - Path to texture
* @returns {boolean}
*
* @todo Texture
*/
SET_Object: function(modelPath, texturePath) {
// Clear out the scene
for (var i = this.prodconf3_scene.children.length - 1; i >= 0; i--) {
obj = this.prodconf3_scene.children[i];
this.prodconf3_scene.remove(obj);
}
const modelLoader = new THREE.GLTFLoader();
modelLoader.load(modelPath, (gltf) => {
// HERE? apply texture from texturePath to this gltf
this.prodconf3_obj = gltf.scene;
this.prodconf3_scene.add(this.prodconf3_obj);
});
return true;
}
这段代码导入 glTF 很好,只是黑色。最终,我能够将 .jpeg 纹理应用于此模型,但仅此而已。这是我能得到的最好结果: here
那是通过这种方法:
/**
* SET method: Sets current object to scene (deleting previous one)
*
* @author Anton Pernisch <anton@pernisch.dev>
* @param {string} modelPath - Path to object in glTF format
* @param {string} texturePath - Path to texture
* @returns {boolean}
*
* @todo Texture
*/
SET_Object: function(modelPath, texturePath) {
// Clear out the scene
for (var i = this.prodconf3_scene.children.length - 1; i >=0 ; i--) {
obj = this.prodconf3_scene.children[i];
this.prodconf3_scene.remove(obj);
}
const modelLoader = new THREE.GLTFLoader();
const textureLoader = new THREE.TextureLoader();
modelLoader.load(modelPath, (gltf) => {
var model = gltf.scene;
model.traverse((o) => {
if (o.isMesh) {
o.material = new THREE.MeshBasicMaterial({map: textureLoader.load(texturePath)});
}
});
this.prodconf3_obj = model;
this.prodconf3_scene.add(this.prodconf3_obj);
});
return true;
}
我还尝试通过 TextureLoader 加载方法创建纹理,然后将其与 modelLoader.load
函数中的 gltf.scene
网格化。那根本不起作用,我得到了
Uncaught TypeError: Cannot read property 'center' of undefined
错误(我不确定使用 gltf.scene
作为 THREE.Mesh()
中的第一个参数)。
所以,我的问题是,在 three.js 中将纹理正确应用到 glTF 的正确和更新方法是什么?
我觉得这很好,但我想知道我们是否应该传递对已加载纹理的引用。
Object3D#Traverse
不是异步的,因此我们必须同步更新 material。
SET_Object: async function(modelPath, texturePath) {
// Clear out the scene
for (let i = this.prodconf3_scene.children.length - 1; i >= 0; i--) {
obj = this.prodconf3_scene.children[i];
this.prodconf3_scene.remove(obj);
}
const modelLoader = new THREE.GLTFLoader();
const textureLoader = new THREE.TextureLoader();
// Load texture
const texture = await textureLoader.loadAsync(texturePath);
texture.flipY = false;
// Load model
const { scene: model } = await modelLoader.loadAsync(modelPath);
// Update model
model.traverse((o) => {
if (o.isMesh) {
o.material.map = texture;
o.material.needsUpdate = true;
}
});
this.prodconf3_obj = model;
this.prodconf3_scene.add(this.prodconf3_obj);
return this.prodconf3_obj;
}