问题描述
我试图交换图像的纹理在运行时加载的three.js的obj。下面是three.js例子稍加修改code直:
VAR容器,统计;
VAR摄像,场景,渲染器;
变种mouseX = 0,mouseY的= 0;
变种windowHalfX = window.innerWidth / 2;
变种windowHalfY = window.innerHeight / 2;
在里面();
动画();
功能的init(){
容器= document.createElement方法('格');
document.body.appendChild(容器);
摄像头=新THREE.PerspectiveCamera(45,window.innerWidth / window.innerHeight,1,2000年);
camera.position.z = 100;
//现场
现场=新THREE.Scene();
VAR环境=新THREE.AmbientLight(0x101030);
scene.add(环境);
VAR平行光=新THREE.DirectionalLight(0xffeedd);
directionalLight.position.set(0,0,1);
scene.add(平行光);
//经理
VAR经理=新THREE.LoadingManager();
manager.onProgress =函数(项目,装载,总数){
的console.log(项目,装载,总数);
};
//模型
VAR装载机=新THREE.OBJLoader(经理);
loader.load('OBJ / female02 / female02.obj',函数(对象){
object.traverse(函数(子){
如果(孩子的instanceof THREE.Mesh){
//改变纹理时创建一个全局变量以后参考
myMesh =子女;
//应用纹理
myMesh.material.map = THREE.ImageUtils.loadTexture('纹理/ ash_uvgrid01.jpg');
myMesh.material.needsUpdate = TRUE;
}
});
object.position.y = - 80;
scene.add(对象);
});
//渲染
渲染器=新THREE.WebGLRenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
container.appendChild(renderer.domElement);
document.addEventListener(鼠标移动,onDocumentMouseMove,假);
window.addEventListener('调整',onWindowResize,假);
}
功能newTexture(){
myMesh.material.map = THREE.ImageUtils.loadTexture('纹理/ land_ocean_ice_cloud_2048.jpg');
myMesh.material.needsUpdate = TRUE;
}
功能onWindowResize(){
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth,window.innerHeight);
}
功能onDocumentMouseMove(事件){
mouseX =(event.clientX - windowHalfX)/ 2;
mouseY的=(event.clientY - windowHalfY)/ 2;
}
//动画
功能动画(){
requestAnimationFrame(动画);
渲染();
}
功能渲染(){
camera.position.x + =(mouseX - camera.position.x)* 0.05;
camera.position.y + =( - mouseY的 - camera.position.y)* 0.05;
camera.lookAt(scene.position);
renderer.render(场景,摄像头);
}
我说的唯一的事情就是newTexture功能和引用网格作为myMesh。这里是最初的例子( http://threejs.org/examples/webgl_loader_obj.html )。该功能不抛出任何错误,但.OBJ不会更新。我知道,我只是失去了一些东西根本在这里..
更新的每下面的出色答卷,这里是正确的code添加了一些新通过输入域交换的质感
VAR容器,统计;
VAR摄像,场景,渲染器;
变种mouseX = 0,mouseY的= 0;
变种windowHalfX = window.innerWidth / 2;
变种windowHalfY = window.innerHeight / 2;
VAR globalObject;
在里面();
动画();
功能的init(){
容器= document.createElement方法('格');
document.body.appendChild(容器);
摄像头=新THREE.PerspectiveCamera(45,window.innerWidth / window.innerHeight,1,2000年);
camera.position.z = 100;
//现场
现场=新THREE.Scene();
VAR环境=新THREE.AmbientLight(0x101030);
scene.add(环境);
VAR平行光=新THREE.DirectionalLight(0xffeedd);
directionalLight.position.set(0,0,1);
scene.add(平行光);
//经理
VAR经理=新THREE.LoadingManager();
manager.onProgress =函数(项目,装载,总数){
的console.log(项目,装载,总数);
};
//模型
VAR装载机=新THREE.OBJLoader(经理);
loader.load('OBJ / female02 / female02.obj',函数(对象){
//存储全局引用.OBJ
globalObject =对象;
object.traverse(函数(子){
如果(孩子的instanceof THREE.Mesh){
child.material.map = THREE.ImageUtils.loadTexture('纹理/ grid.jpg');
child.material.needsUpdate = TRUE;
}
});
object.position.y = - 80;
scene.add(对象);
});
//渲染
渲染器=新THREE.WebGLRenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
container.appendChild(renderer.domElement);
document.addEventListener(鼠标移动,onDocumentMouseMove,假);
window.addEventListener('调整',onWindowResize,假);
}
功能onWindowResize(){
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth,window.innerHeight);
}
功能onDocumentMouseMove(事件){
mouseX =(event.clientX - windowHalfX)/ 2;
mouseY的=(event.clientY - windowHalfY)/ 2;
}
//动画
功能动画(){
requestAnimationFrame(动画);
渲染();
}
功能渲染(){
camera.position.x + =(mouseX - camera.position.x)* 0.05;
camera.position.y + =( - mouseY的 - camera.position.y)* 0.05;
camera.lookAt(scene.position);
renderer.render(场景,摄像头);
}
功能newTexture(){
。VAR newTexturePath =材质/+的document.getElementById(纹理)值+;
globalObject.traverse(函数(子){
如果(孩子的instanceof THREE.Mesh){
//改变纹理时创建一个全局变量以后参考
儿童;
//应用纹理
child.material.map = THREE.ImageUtils.loadTexture(newTexturePath);
child.material.needsUpdate = TRUE;
}
});
}
这里的问题是,有多个子网格中的对象
变量。通过只有一个 myMesh
全局变量,你只存储的最后一个子网。因此,当您尝试使用这个全局变量来更新纹理,只有一个网格得到纹理更新,可能是一个小的隐藏部分是不清晰可见。
的解决办法是将两种:
- 存储一个
myMeshes
数组的全局变量,推动myMesh
到它的每一次有一个。然后在你的newTexture()
功能,遍历此数组中的所有项目,并更新他们的地图/材料。 - 或者,
对象
变量(从OBJLoader
的回调之一返回)存储到一个单一的全局变量。然后在你的newTexture()
功能,通过像它是如何在code做了所有网(使用移动()迭代code>和
如果
语句),并更新他们的地图/材料。
最后,调用newTexture()放在你的code也有助于;)
I'm trying to swap image texture at runtime on a loaded three.js .obj. Here's the code straight from three.js examples with slight modification:
var container, stats;
var camera, scene, renderer;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.z = 100;
//scene
scene = new THREE.Scene();
var ambient = new THREE.AmbientLight( 0x101030 );
scene.add( ambient );
var directionalLight = new THREE.DirectionalLight( 0xffeedd );
directionalLight.position.set( 0, 0, 1 );
scene.add( directionalLight );
//manager
var manager = new THREE.LoadingManager();
manager.onProgress = function ( item, loaded, total ) {
console.log( item, loaded, total );
};
//model
var loader = new THREE.OBJLoader( manager );
loader.load( 'obj/female02/female02.obj', function ( object ) {
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
//create a global var to reference later when changing textures
myMesh = child;
//apply texture
myMesh.material.map = THREE.ImageUtils.loadTexture( 'textures/ash_uvgrid01.jpg');
myMesh.material.needsUpdate = true;
}
} );
object.position.y = - 80;
scene.add( object );
} );
//render
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function newTexture() {
myMesh.material.map = THREE.ImageUtils.loadTexture( 'textures/land_ocean_ice_cloud_2048.jpg');
myMesh.material.needsUpdate = true;
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseMove( event ) {
mouseX = ( event.clientX - windowHalfX ) / 2;
mouseY = ( event.clientY - windowHalfY ) / 2;
}
//animate
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
camera.position.x += ( mouseX - camera.position.x ) * .05;
camera.position.y += ( - mouseY - camera.position.y ) * .05;
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
The only thing I added was the newTexture function and a reference to the mesh as myMesh. Here's the original example (http://threejs.org/examples/webgl_loader_obj.html). The function doesn't throw any errors but the .obj does not update. I know I'm just missing something fundamental here..
Update: Per the excellent answer below, here's the correct code with some additions to swap texture via an input field:
var container, stats;
var camera, scene, renderer;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var globalObject;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);
camera.position.z = 100;
//scene
scene = new THREE.Scene();
var ambient = new THREE.AmbientLight( 0x101030 );
scene.add( ambient );
var directionalLight = new THREE.DirectionalLight( 0xffeedd );
directionalLight.position.set( 0, 0, 1 );
scene.add( directionalLight );
//manager
var manager = new THREE.LoadingManager();
manager.onProgress = function (item, loaded, total) {
console.log( item, loaded, total );
};
//model
var loader = new THREE.OBJLoader( manager );
loader.load( 'obj/female02/female02.obj', function (object) {
//store global reference to .obj
globalObject = object;
object.traverse( function (child) {
if ( child instanceof THREE.Mesh ) {
child.material.map = THREE.ImageUtils.loadTexture( 'textures/grid.jpg');
child.material.needsUpdate = true;
}
});
object.position.y = - 80;
scene.add( object );
});
//render
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseMove( event ) {
mouseX = ( event.clientX - windowHalfX ) / 2;
mouseY = ( event.clientY - windowHalfY ) / 2;
}
//animate
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
camera.position.x += ( mouseX - camera.position.x ) * .05;
camera.position.y += ( - mouseY - camera.position.y ) * .05;
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
function newTexture() {
var newTexturePath = "textures/" + document.getElementById("texture").value + "";
globalObject.traverse( function ( child ) {
if (child instanceof THREE.Mesh) {
//create a global var to reference later when changing textures
child;
//apply texture
child.material.map = THREE.ImageUtils.loadTexture(newTexturePath);
child.material.needsUpdate = true;
}
});
}
The problem here is that there are multiple child meshes in the object
variable. By having only one myMesh
global variable, you are storing only the last child mesh. Thus when you try to update the texture using this global variable, only one of the meshes gets a texture update, probably a small hidden part that is not clearly visible.
The solution would be to either:
- Store a
myMeshes
array global variable and pushmyMesh
into it every time there is one. Then in yournewTexture()
function, iterate through all items in this array and update their maps/materials. - Or, store the
object
variable (the one returned fromOBJLoader
's callback) into one single global variable. Then in yournewTexture()
function, iterate through all the meshes like how it is done in the code (usingtraverse()
andif
statement), and update their maps/materials.
Lastly, calling newTexture() somewhere in your code would also help ;)
这篇关于更改three.js在运行时的纹理加载的obj的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!