[SOLVED] Changing a texture

I must be missing something really basic here. I have a scene which has some objs imported into it. I want to be able to change the material and texture at the click of a button. It all works fine for standard THREE geometry (box,sphere etc). However the same function run on my models never sets the texture correct but I do get the colour of the texture. I cannot share my models, and since it works on standard geometry seems pointless to put a codepen up, however here is my change material function…

function changeTexture(object){
let texture = new THREE.TextureLoader().load("tests/textures/WoodFineDark004_COL_3K.jpg");
let bumpMap = new THREE.TextureLoader().load("tests/textures/WoodFineDark004_DISP_3K.jpg");
let normalMap = new THREE.TextureLoader().load("tests/textures/WoodFineDark004_NRM_3K.jpg");
let material = new THREE.MeshStandardMaterial({
map: texture,
bumpMap: bumpMap,
bumpScale: 0.5,
 normalMap: normalMap,
});

object.material = material;
object.material.needsUpdate = true;
object.geometry.buffersNeedUpdate = true;
object.geometry.uvsNeedUpdate = true;
}

heres the result I get - notice the cube looks like wood, whereas the other shape is just brown

image

All the topics I can find on this suggest the updates that I have put in, but they have made no difference whatsoever, what am i missing!?

None of those updates matter.

they would matter if you did something like

let material = new THREE.MeshStandardMaterial()
...
renderer.render(scene, camera)

material.texture = new THREE.TextureLoader().load('...')

material.needsUpdate = true //have to call this

renderer.render(scene, camera) //if you want to see it here

Why? Because you first construct a material with no textures and three optimizes that. It makes a shader that consumes no textures and compiles that. When you add a texture to the Material, the shader represantation of it doesn’t know how to handle it. You need to recompile the material (which is what needsUpdate does) and make three create a shader that knows how to use textures internally.

You’re most likely missing uvs or have incorrect uvs set. Maybe the first stab would be

someOfYourTextures.wrapS = someOfYourTextures.wrapT = THREE.RepeatWrapping

someOfYourTextures.repeat(0.1,.0.1) //maybe the texture is repeated too much

thanks alot for your response @pailhead , I didnt know any of that and its lead me to do some further research in to the whole area

unfortunatley setting the repeat and wrapt and wraps didnt help in my case so I assume that means theres no uvs

It sounds as though theres no automatic/neat solution if I want to be able to apply a texture to any imported model (e.g a complex/irregular shape) whose origin is unknown?

It’s hard to know what the root cause is, since we don’t have access to your model. My hunch is that your cube has UVs defined, but the other shape doesn’t have any UVs. Without UVs, the engine doesn’t know how to map the texture, so nothing shows up.

What do you get when you do console.log(object.geometry.attributes)? Is there an attribute called uv, and if so, how long is it?

you where perfectly correct my model didnt have any UVs in it. I suspect its from the conversion process that I shall have to look into.

I didnt know anything about them before the answers on hear, hence didnt know to search for them to understand them better.

I shall mark this as solved, as its an issue with my file. thanks to both of you

This is not quite true i think. It wouldn’t know how to map it true, but something should show up, the number would either be garbage or 0 depending on the platform, but it would look up into something. So you and I visiting the same page “without” uvs could yield two different renderings, with two different texture lookups. I’m not sure what options there would be, i think it’s either two different uniform colors (different lookups) or a uniform color at 0,0, and DMT fueled hallucination.

“Box/Cube mapping” and i think someone posted a fiddle on stack overflow or three slack recently.