Static images on 3D Model

Hi,
Need help I want to have two static images on this 3D apple model (this model is working fine with provided texture), one image will be displaying on front and second image will display when hover or click on the model.

var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath( "assets/" );
mtlLoader.load('Manzana.mtl', function( materials ) {

materials.preload();

	var objLoader = new THREE.OBJLoader();
	objLoader.setMaterials( materials );
	objLoader.setPath( "assets/" );
	objLoader.load( 'Manzana.obj', function ( object ) {
		mesh = object;
		mesh.position.y = 2;
		mesh.position.x = 0.1;
		mesh.scale.set(0.2, 0.2, 0.2);
		scene.add( mesh );
	} );
} );

Thank you

Regards,
Hasnain Khan

Here is a basic fiddle that shows how a texture is changed when the respective mesh is hovered with the mouse. As you can see, raycasting is used to implement the interaction:

https://jsfiddle.net/wmbvu70h/

You can basically do the same in your application.

Full code:

let camera, scene, renderer, mesh, raycaster, texture1, texture2;

const mouse = new THREE.Vector2( - 1, - 1 );

init();
animate();

function init() {

		camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
		camera.position.z = 1;

		scene = new THREE.Scene();
		
		const loader = new THREE.TextureLoader();
		
		texture1 = loader.load( '//cdn.rawgit.com/mrdoob/three.js/master/examples/textures/brick_diffuse.jpg' );
		texture2 = loader.load( '//cdn.rawgit.com/mrdoob/three.js/master/examples/textures/floors/FloorsCheckerboard_S_Diffuse.jpg' );

		const geometry = new THREE.PlaneBufferGeometry();
		const material = new THREE.MeshBasicMaterial( { map: texture1 } );

		mesh = new THREE.Mesh( geometry, material );
		scene.add( mesh );

		renderer = new THREE.WebGLRenderer( { antialias: true } );
		renderer.setPixelRatio( window.devicePixelRatio );
		renderer.setSize( window.innerWidth, window.innerHeight );
		document.body.appendChild( renderer.domElement );
		
		raycaster = new THREE.Raycaster();
		
		document.addEventListener( 'mousemove', onDocumentMouseMove, false );

		window.addEventListener( 'resize', onWindowResize, false );

}

function onWindowResize() {

		camera.aspect = window.innerWidth / window.innerHeight;
		camera.updateProjectionMatrix();
		renderer.setSize( window.innerWidth, window.innerHeight );

}

function onDocumentMouseMove( event ) {

		event.preventDefault();

		mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
		mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
		
}

function animate() {

		requestAnimationFrame( animate );
		
		raycaster.setFromCamera( mouse, camera );
		var intersection = raycaster.intersectObject( mesh );
		
		if ( intersection.length > 0 ) {
		
			mesh.material.map = texture2;
		
		} else {
		
			mesh.material.map = texture1;
		
		}
		
		
		renderer.render( scene, camera );

}
2 Likes

Thank you so much Michael for your reply.
But I want to add two images on a 3D model one will always showing and other will be showing when hover 3D Model, so that images will look like a part of that 3D model.

  • Image one
  • 3d Model
  • Image two(will show on hover on 3D Model)

Do you mean show one or both, but not the second alone? @Mugen87’s answer shows how you can change texture on a single material. A texture will, as you describe, look like a part of the 3D model. But the model needs to have texture coordinates defined.

An alternative if you need to render both texture at the same time, will be to use rendergroups on the geometry and multiple materials on the same mesh (passing an array of materials to the constructor). Typically, you will then enable or disable the second material depending on the intersection state. The render groups will both contain all elements of the geometry. The two materials will have one texture each.

1 Like

Yea! almost got it.

In my application, there are more then one 3D models of spheres on different positions.

Now each sphere should have company logo(Image) and product of company(Image), product(Image) will be hidden will show when hover on sphere.

Do you have any example of render groups?

I don’t think you have to work with BufferGeometry.groups. You can also use SceneUtils.createMultiMaterialObject(). Just pass in your geometry and the respective materials (with different textures).

1 Like

Checking the linked source, I notice that the function will create one mesh per material. Will the renderer reuse the geometry with negligible overhead?

1 Like

spheres are not geometry anymore as you can see code i have posted with question. It’s already created with MTLLoader and OBJLoader so how can i add materials (with different textures)?

Yes. It’s basically the same like using groups resulting in two independent render items.

You can access the geometry via mesh.geometry.

2 Likes