Three.js - обработка повторного события на объекте

#1

Здравствуйте. Подскажите, как сделать в tree.js повторное выполнение события на том же объекте (по click). Первый раз событие выполняется, после нет. Вот код скрипта:

window.onload = function(){
var scene, camera, mesh;
var player = {height:1.7, speed: 0.2, turnSpeed:Math.PI*0.02};       
var raycaster;//
var width = window.innerWidth;
var height = window.innerHeight;
var canvas = document.getElementById('sal');
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);		
var renderer = new THREE.WebGLRenderer({canvas: canvas, antialias: true});
renderer.setPixelRatio(window.devicePixelRatio * 1.5);
renderer.setSize(width, height);
renderer.setClearColor(0xfffeee);             
camera = new THREE.PerspectiveCamera(45, width/height, 0.1, 1000);
camera.position.set(0, player.height, -10);
camera.lookAt(new THREE.Vector3(0,player.height,0));
scene = new THREE.Scene();	
var amLight = new THREE.AmbientLight(0xffffff, 0.2);
scene.add(amLight);		
var meshFloor = new THREE.Mesh(
    new THREE.PlaneGeometry(10,10,10,10),
    new THREE.MeshPhongMaterial({color:0xf0f0f0, wireframe:false})
);
meshFloor.rotation.x -= Math.PI / 2;
meshFloor.receiveShadow = true;
scene.add(meshFloor);						
var cubeGeometry = new THREE.CubeGeometry(1, 1, 1);
var cubeMaterial = new THREE.MeshBasicMaterial({ color: 0xfff000 });
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);    
cube.rotation.y = Math.PI * 30 / 180;
cube.position.y = 0.5; 
scene.add( cube );    
function animate(){
requestAnimationFrame(animate);	
renderer.render(scene, camera);} animate();	
            function onWindowResize() {
		camera.aspect = window.innerWidth / window.innerHeight;
		camera.updateProjectionMatrix();
		renderer.setSize( window.innerWidth, window.innerHeight );
	}				
	var selectedObject = null;
	var open = function onDocumentMouseClick( event ) {
		event.preventDefault();
		var intersects = getIntersects( event.layerX, event.layerY );
		if ( intersects.length > 0 ) {
				selectedObject = intersects[0].object;					
				selectedObject.material.color.set( '#f00' );
				selectedObject.rotation.y = Math.PI * 10 / 180;											 
                    }									
	}		
	var raycaster = new THREE.Raycaster();
	var mouseVector = new THREE.Vector3();
	function getIntersects( x, y ) {
		x = ( x / window.innerWidth ) * 2 - 1;
		y = - ( y  / window.innerHeight ) * 2 + 1;
		z = 0.5;
		mouseVector.set( x, y, z );
		raycaster.setFromCamera( mouseVector, camera );
		return raycaster.intersectObject( cube, true );
	}    		
    canvas.addEventListener( 'resize', onWindowResize, false );
    canvas.addEventListener( "click", onDocumentMouseClick, false );}
#2

Впредь делись кодом так чтобы его можно было взять и запустить. А то сложно переносить все в jsfiddle вручную.

https://jsfiddle.net/n4cjL1xs/

Код выполняется без ошибки. Единственное что я убрал присвоение в переменную open в этой строке
var open = function onDocumentMouseClick

Функция обработки клика выполняется вызови console.log или alert из функции обработчика клика чтобы убедиться. Просто результат ее работы одинаковый при каждом последующем клике.

#3

Уважаемый dmitry. Я знаю, что код выполняется. Но он выполняется только один раз при первом клике на объекте. При втором клике ничего не происходит. В скрипте есть строка для поворота объекта при клике:
selectedObject.rotation.y = Math.PI * 10 / 180;
Поворот происходит при первом клике. Мне нужно чтобы при повторном клике объект также выполнял поворот и при последующих кликах также. (Или выполнял другое действие, которое я пропишу)

#4

Мы тут свободноб общаемся на “ты”. Считай как в компании людей объединенными интересом. Но если тебе удобнее использовать другие формы - без проблем.

Просто я дотошен к формулировке:

код выполняется повторные разы, просто результат выполнения всегда одинаковый. Код корректен и выполняет именно то что в нем описано. Поймешь эту ситуацию, проще будет добавлять другие действия.

Более точно вопрос был бы сформулирован таким образом “вот код, ожидаю что когда буду кликать несколько раз по объекту, тот будет вращаться, но вращается только при первом клике”.

А теперь по поводу проблемы: чтобы объект вращался, значение поворота должно быть разным при последующих кликах. Значит надо где-то “аккумулировать” знание о текущем повороте.

Я ввел переменную rot, использую ее для вычисления значения поворота и меняю ее значение при каждом клике. Получается новое значение при каждом клике и объект вращается.

https://jsfiddle.net/p09k8hje/

#5

Спасибо за указанный путь к решению задачи. Я неверно истолковывал понятие “rotation”. Я воспринимал это как угол поворота движения (динамика). Но в данном случае это понятие означает не вращение (поворот), а положение объекта в пространстве (статика).
“Правильно заданный вопрос - это на 90% ответ”
Еще раз спасибо.

#6

Добрый день. А где посмотреть (прочитать), как и куда правильно выкладывать код?

#7

Попробуй поиграться с интерфейсом jsfiddle.com. Там должно быть понятно без особой предварительной подготовки

#8
#9

Добрый день. Нужна помощь. Вопрос новый, но тема по факту та же.
Вот здесь выложен код
https://jsfiddle.net/3hd8Lpkz/
В коде реализовано перемещение камеры по событию click, когда указатель мышки над полом.
Медленное движение реализовано при помощи цикла for, функции function(i), и функции setTimeout().
Этот код работает. (В FireFox по крайней мере, у меня работает).
Вопрос следующий: как реализовать блокировку выполнения нового события click, пока не закончено выполнение текущего события click. Чтобы в период перемещения камеры (объекта) нажатие пользователем клавиши мышки не приводило ни к каким последствиям, пока перемещение не закончится.

#10

Добрый день. Спасибо. Я выложил код и задал в той же теме новый вопрос, но пока реакции нет. Или создавать новую тему?

#11

Код не запускается. Суть jsfiddle-а в том чтобы иметь код и мочь редактировать и видеть результаты его работы.

Общая стратегия для таких случаев:

  1. Создать флаг var isAnimating=false
  2. При клике проверять значение флага, если он true, то не начинать новую анимацию. Если он false, то ставить флаг в true и запускать анимацию.
  3. В конце выполнения анимации вернуть значение флага в false.