ThreeJs add Texture to a GLTF object surface - three.js

I am trying to apply an image dynamically on a gltf loaded mesh.
The code to load the model looks like:
const gltfLoader = new GLTFLoader();
const url = 'resources/models/mesh.gltf';
gltfLoader.load(url, (gltf) => {
const root = gltf.scene;
scene.add(root);
})
When looking from top the element looks like a rounded rect:
When inspecting the imported mesh I can see that the BufferGeometry has a count of 18.000 points:
Everything works fine however if I apply the texture like this:
const texture = new THREE.TextureLoader().load( 'textures/land_ocean_ice_cloud_2048.jpg' );
const material = new THREE.MeshBasicMaterial( { map: texture } );
root.children[0].material = material;
The image is not visible but the mesh is now colored in 1 color.
Is it possible to apply the image just on the top face of the rect?

Hard to tell what the problem is without seeing the resulting image. However, I would just assign a new texture like this: root.children[0].material.map = texture instead of creating a whole new material, since you don't want to lose all the material attributes that came in the GLTF.
Additionally, MeshBasicMaterial always looks flat because it is not affected by lights.

Related

Three.js adding texture gives complete object color of 1 pixel

I have this texture of 20x20pixels and and object from a collada 1.4.1 model.
So I want to give this object this new texture for testing
I do the following
var loader = new THREE.TextureLoader();
loader.load("/assets/images/texture2/TextureResource129.png", texture => {
var material = new THREE.MeshLambertMaterial({
map: texture
});
node.material = material;
material.needsUpdate = true;
});
Now what happens is that the object is in 1 color
How can I change the texture so it is just as the texture?
Instead of creating a new material that behaves differently than the one that comes in your Collada import, just change the texture of the existing material. Do this inside your texture loader callback:
node.material.uniforms.MatDiff2.value = texture;
That way you just change the texture input to the existing material.

unable to apply three.js texture to JSON model imported from blender

I am trying to apply a texture to a simple 3-d cube model exported from Blender 2.78b (as a matter of fact, the default blender cube). I exported the model in the standard three.js JSON format. I realize that I should be able to apply a texture in Blender on top of the geometry, but I want to "style" the blender model in three.js at runtime. Thus I am only interested in using blender to provide the geometry for my mesh.
I have created a plunker illustrating the situation.
I load in a blender model as blenderGeom, and then apply a MeshBasicMaterial with map set to a brick texture (unfortunately, I have to load the texture as Base64, since plunker doesn't allow you to upload images). I then apply the exact same material/texture to a native three.js BoxGeometry nonBlenderCubeGeom:
function loadModel() {
console.log('now in loadModel');
var promise = new Promise( (resolve, reject) => {
var loader = new THREE.JSONLoader();
// load a resource
loader.load(
'cube.json', (blenderGeom, materials) => {
console.log(`loadModel: now loading cube: geomery=${geometry}`);
let cubeMaterial = new THREE.MeshBasicMaterial({
color: 0xff8080,
wireframe: false,
map: brickTexture
})
nonBlenderCubeGeom = new THREE.BoxGeometry(50, 50, 50);
blenderCubeGeom = blenderGeom;
blenderCube = new THREE.Mesh(blenderGeom, cubeMaterial); //no work
blenderCube.position.x = -20;
nonBlenderCube = new THREE.Mesh(nonBlenderCubeGeom, cubeMaterial); //work
nonBlenderCube.position.x = 20;
blenderCube.scale.set(10, 10, 10);
scene.add(blenderCube);
scene.add(nonBlenderCube);
As you can see from running the plunker, only the native three.js object on the right is textured, and the blender model on the left is not:
Am I doing something wrong? Is it simply a restriction that you can only texture a model in Blender?
Three.js r84. Blender 2.78b. I'm assuming this on three.js side, but I'm opening it up to blender as well.
Many Thanks.

Three.js: Add a texture to an object just on the outside

I'm very new with Three.js and I'm trying to make a ring:
http://www.websuvius.it/atma/myring/preview.html
I have a background texture ( the silver one ) and another one with a text.
I want the text only on the ring external face.
This is part of my code:
var loader = new THREE.OBJLoader( manager );
var textureLoader = new THREE.TextureLoader( manager );
loader.load( 'assets/3d/ring.obj', function ( event ) {
var object = event;
var geometry = object.children[ 0 ].geometry;
var materials = [];
var backgroundTexture = textureLoader.load('img/texture/silver.jpg');
backgroundTexture.flipY = false;
var background = new THREE.MeshBasicMaterial({
map: backgroundTexture,
color: 0xffffff
});
materials.push(background);
var customTexture = textureLoader.load('img/text.png');
customTexture.flipY = false;
var custom = new THREE.MeshBasicMaterial({
map: customTexture,
transparent: true,
opacity: 1,
color: 0xffffff
});
materials.push(custom);
mesh = THREE.SceneUtils.createMultiMaterialObject(geometry, materials);
mesh.position.y=-50;
scene.add(mesh);
}, onProgress, onError );
It is possible?
Thanks
The reason behind your issue appears to be in your .obj file. Judging from a quick glance at the texture coordinates stored in the file, the inside of the ring uses the same part of the texture image as the outside of the ring.
Increasing the transparent parts of the image won't help. Neither will the attempts to stop the texture from repeating. Those would help if the texture coordinates were larger than 1 but this is not your case unfortunately.
However, there are several solutions:
Split the object in a 3D modeling software to two objects - outside and inside of the ring - and apply the texture only to the first one.
Adjust the UV coordinates of the object in a 3D modeling software.
Adjust the UV coordinates of the vertices programmatically after loading the object to Three.JS

Setting texture on mesh in three.js

I have a mesh that I load as a .dae (collada). However, my texture file is separate (as a PNG)
Currently, my loading code is
loader.load("./assets/map_tutorial.dae", function(collada) {
var terrain = collada.scene.children[0];
var texture = new THREE.ImageUtils.loadTexture("./assets/map_tutorial_tex.png");
terrain.rotation.x = Math.PI / 2;
terrain.rotation.y = Math.PI;
scene.add(terrain);
console.log("There are " + collada.scene.children.length + " meshes!");
});
However, I'm uncertain as to how to apply the texture to my mesh (terrain)
Thanks in advance!
You will definitely have to create new material object from your texture. Assuming you want lambert, it would be like this:
var material = new THREE.MeshLambertMaterial( { map:texture } );
I am not familiar with collada loader, but it seems that it already created a mesh for you. In this case I am not sure whether you can change material of this mesh. What should definitely work is to create new mesh from geometry that you loaded from .dae file and material that you created from png image.
var mesh = new THREE.Mesh( terrain.geometry, material );
scene.add( mesh );
I hope this helps, normally I use three.js native JSON model files where this approach is working. Difference is that THREE.JSONLoader gives you two objects for your usage: geometry and materials. Collada loader seems to provide you with already created mesh so try to change it's geometry if possible or "steal" the geometry from this mesh and create a new one like I did in the example.

Mesh with texture background color

I create a Mesh having a PlaneGeometry and the material defined by a texture loaded from a JPEG image. Everything is fine, excepting that there is a small amount of time before the texture image is loaded when the plane is displayed using a dark color. Is there a way to change this color to something else?
I tried the color option for material, but it is not applied.
var texture = new THREE.ImageUtils.loadTexture('/path/to/image');
texture.minFilter = THREE.LinearMipMapLinearFilter;
texture.magFilter = THREE.NearestFilter;
var material = new THREE.MeshBasicMaterial({
side : THREE.DoubleSide,
map : texture,
color : 0xf0f0f0
// this doesn't seem to work
});
var geometry = new THREE.PlaneGeometry(Math.abs(line.x1 - line.x0), depth);
var mesh = new THREE.Mesh(geometry, material);
That black color is the texture rendering without any texture data. The easiest fix is to load the texture and the mesh, but do not render the mesh until both have fully loaded.
Another option is to create a very small 1x1 texture that is the color you want, use that as your texture initially, and then change the mesh material to your final texture once the desired texture has fully loaded.

Resources