Search code examples
three.jscolor-picker

Change the color of 3D model using colorPicker three.js


I am trying to change the color of 3D object where intersected using color picker.I am trying with dat.gui.I want to change the color of 3d part where it gets clicked and change the selected from the colorPicker.I tried out some possible ways but it doesn't work out.Please,refer to the code I tried out. Help me out with some solution and draw my attention to where I am getting wrong. Thanks.

<!DOCTYPE html>
<html lang="en">
	<head>
		<title>color</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		<style>
			body {
				font-family: Monospace;
				background-color: #000;
				color: #fff;
				margin: 0px;
				overflow: hidden;
			}
			
		</style>
	</head>

	<body>
		<script src="three.js"></script>
		<script src="OrbitControls.js"></script>
		<script src="Detector.js"></script>
		<script src="stats.min.js"></script>
		
		<script src="loaders/MTLLoader.js"></script>
		<script src="loaders/OBJLoader.js"></script>	
		<script type='text/javascript' src='DAT.GUI.min.js'></script>

		<script>

			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

			var container, stats;

			var camera, controls, scene, renderer,effectController;
			
			var raycaster;
		
			var objects = [];
			
			var selectedObject,selectedPos;
			
			var rotation;
			
			var pos,quat;
			
			var INTERSECTED;
			
			var guiColor;
			
			
			init();
			animate();
			
			function init() {
				
				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
				camera.position.z = 15;
				

				controls = new THREE.OrbitControls( camera );

				scene = new THREE.Scene();
				scene.background = new THREE.Color( 0x555000 );
				scene.add( camera );
				
				// light
			
				var dirLight = new THREE.DirectionalLight( 0xffffff );
				dirLight.position.set( 200, 200, 1000 ).normalize();

				camera.add( dirLight );
				camera.add( dirLight.target );
				
        var mtlLoader = new THREE.MTLLoader(); mtlLoader.setBaseUrl('assets/'); mtlLoader.setPath('assets/'); mtlLoader.load('anno.mtl', function (materials) {

             materials.preload();

         var objLoader = new THREE.OBJLoader();
             objLoader.setMaterials(materials);
             objLoader.setPath('assets/');
             objLoader.load('anno.obj', function (object) {
             scene.add( object );
             objects.push( object );
    });
 });

				// renderer

				renderer = new THREE.WebGLRenderer();
				renderer.setPixelRatio( window.devicePixelRatio );
				renderer.setSize( window.innerWidth, window.innerHeight );
				
				/* Controls */

				controls = new THREE.OrbitControls(camera, renderer.domElement);
				controls.enableDamping = true;
				controls.dampingFactor = 0.25;
				controls.enableZoom = false;
				
				raycaster = new THREE.Raycaster();
				
				gui = new dat.GUI();
	
				parameters = 
				{

					color: "#ff0000",
				
				};
				
				
				gui.add( parameters, 'reset' ).name("Reset");
				guiColor = gui.addColor( parameters, 'color' ).name('Color');
				
				container = document.createElement( 'div' );
				document.body.appendChild( container );
				container.appendChild( renderer.domElement );

				stats = new Stats();
				container.appendChild( stats.dom );

				window.addEventListener( 'resize', onWindowResize, false );
				renderer.domElement.addEventListener("click", onclick, false);
				
			}

			var mouse = new THREE.Vector2();
			
			

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

				raycaster.setFromCamera(mouse, camera);
				var intersects = raycaster.intersectObjects(objects, true);
				
				
				if (intersects.length > 0) {
				
						INTERSECTED = intersects[0].object;
						if ( INTERSECTED && INTERSECTED.material.emissive != null ){
								guiColor.onChange(function(){
							INTERSECTED.material.emissive.setHex(parameters.color)
							});
							
				}
			
			

			function onWindowResize() {

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

				renderer.setSize( window.innerWidth, window.innerHeight );

			}

			function animate() {

				requestAnimationFrame( animate );

				renderer.render( scene, camera );

				stats.update();
			}
		
		</script>

	</body>
</html>


Solution

  • I've create a little live demo with your code and a basic working solution. I'd like to highlight three important changes:

    • You can use the onChange() event handler in order to know when a certain dat.gui property has changed. The demo uses this feature to update the color of a selected object.
    • I have refactored your raycasting logic into something more simple. I've seen you've copied some code from the official three.js examples but the new code should be sufficient for your case. Besides, it's also better to update Material.color instead of Material.emissive.
    • If you set OrbitControls.enableDamping to true, you have to update the controls in your animation loop.

    https://jsfiddle.net/btuzd23o/2/

    three.js R103