Измените цвет 3D-модели с помощью ColorPicker three.js

#three.js #color-picker

#three.js #средство выбора цвета

Вопрос:

Я пытаюсь изменить цвет 3D-объекта, где он пересекается, с помощью средства выбора цвета.Я пытаюсь с помощью dat.gui.Я хочу изменить цвет 3D-детали, на которую нажимается, и изменить выбранный из палитры цветов.Я попробовал несколько возможных способов, но это не сработало.Пожалуйста, обратитесь к коду, который я опробовал. Помогите мне с каким-нибудь решением и обратите мое внимание на то, где я ошибаюсь. Спасибо.

 <!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 amp;amp; 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>  

Ответ №1:

Я создал небольшую демонстрационную версию с вашим кодом и базовым рабочим решением. Я хотел бы выделить три важных изменения:

  • Вы можете использовать onChange() обработчик событий, чтобы узнать, когда изменилось определенное dat.gui свойство. Демонстрационная версия использует эту функцию для обновления цвета выбранного объекта.
  • Я переработал вашу логику raycasting во что-то более простое. Я видел, что вы скопировали некоторый код из официальных three.js примеров, но нового кода должно быть достаточно для вашего случая. Кроме того, также лучше обновить Material.color вместо Material.emissive .
  • Если вы установили OrbitControls.enableDamping значение true , вам необходимо обновить элементы управления в цикле анимации.

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

three.js R103