javascript - Change texture of loaded .obj in three.js at runtime -
i'm trying swap image texture @ runtime on loaded three.js .obj. here's code straight three.js examples 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 global var 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 thing added newtexture function , reference mesh mymesh. here's original example (http://threejs.org/examples/webgl_loader_obj.html). function doesn't throw errors .obj not update. know i'm missing fundamental here..
update: per excellent answer below, here's correct code additions swap texture via 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 .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 global var reference later when changing textures child; //apply texture child.material.map = three.imageutils.loadtexture(newtexturepath); child.material.needsupdate = true; } }); }
the problem here there multiple child meshes in object
variable. having 1 mymesh
global variable, storing last child mesh. when try update texture using global variable, 1 of meshes gets texture update, small hidden part not visible.
the solution either:
- store
mymeshes
array global variable , pushmymesh
every time there one. innewtexture()
function, iterate through items in array , update maps/materials. - or, store
object
variable (the 1 returnedobjloader
's callback) 1 single global variable. innewtexture()
function, iterate through meshes how done in code (usingtraverse()
,if
statement), , update maps/materials.
lastly, calling newtexture() somewhere in code ;)
Comments
Post a Comment