ThreeJS управления орбитой установить цель без lookAt
Я пытаюсь сделать 3D-просмотрщик для построения моделей. У нас загружена модель, и мы пытаемся взаимодействовать с ней. Для этого мы используем OrbiControls для вращения, панорамирования и масштабирования модели.
Мы хотим иметь такое поведение в средстве просмотра, что, когда пользователь щелкает и перетаскивает (таким образом вращая), центр вращения находится в точке здания, где пользователь щелкает.
Я думал, что был мудрым, изменив цель OrbitControl как так:
control.target.set(newX, newY, newZ);
Однако в источнике файла OrbitControl.js я обнаружил, что при обновлении элемента управления
camera.lookAt()
вызывается функция, которая приводит камеру к прыжку на новую позицию.
Есть ли способ обойти это? Я пытался в течение нескольких часов, и ничего не получалось.
Попытался изменить target0, затем вызвать reset() для элемента управления. Также попытался изменить камеру обратно в старое положение (это может быть, как это было сделано, но я мог бы попробовать это плохо.
3 ответа
Есть ли способ обойти это?
Короткий ответ: "Да, но он не использует стандартную версию OrbitControls.js".
Читайте дальше для моих подробных рассуждений....
Я только что провел некоторое время, глядя на исходный код OrbitControls.js
(r87) рассматривает идею реализации расширения, которое позволит вам предоставить дополнительную 2-ую точку, которую она будет использовать в качестве цели камеры.
Однако после изучения кода я думаю, что это было бы плохой функцией для добавления в стандартную публичную версию. В OrbitControls есть много функций, таких как возможность ограничения угла обзора, минимального и максимального поворота и расстояния тележки, которые предполагают, что камера и центр орбиты совпадают. Если бы была опция второй камеры tagret, все они должны были бы быть изменены, чтобы использовать либо центр орбиты, либо цель камеры, либо иметь настраиваемый параметр, который переключает тот, который он использует. Это добавило бы сотни дополнительных строк кода, усложнило бы его понимание и все для очень нишевой функции.
Итак... Решение:
Поскольку вы создаете технический инструмент, я подозреваю, что вас не волнует ограниченный угол обзора, расстояние или поворот, поэтому на вашем месте я бы скопировал OrbitControls.js
в свой проект, переименуйте его в OrbitControls_customised.js
и внесите необходимые изменения:
Добавьте 2 новых параметра ниже this.target
называется this.cameraTarget
а также this.coupleCenters
// "target" sets the location of focus, where the object orbits around
this.target = new THREE.Vector3();
// "cameraTarget" is where the camera is looking (by default the same as target
this.cameraTarget = new THREE.Vector3();
// Whether the camera should be locked to the orbit center
this.coupleCenters = true;
И на линии, где он инструктирует камеру смотреть в центр...
scope.object.lookAt( scope.target );
... измените его так, чтобы он обновлял камеру только тогда, когда coupleCenters имеет значение true...
if( scope.coupleCenters ){
scope.cameraTarget = scope.target;
}
scope.object.lookAt( scope.cameraTarget );
Теперь, с этими изменениями, вы можете положить onMouseDown
событие, которое использует RayCasting, чтобы найти точку на вашем объекте, устанавливает controls.decoupleCenters
в false
и устанавливает controls.target
до точки пересечения / пересечения raycast. Тогда onMouseUp
событие, которое устанавливает controls.target
назад к controls.cameraTarget
чтобы позволить ему вести себя как обычно.
Я надеюсь, что это ответит на ваш вопрос и даст вам приблизительный план работы.
Попробуй это:
Сначала установите положение элемента управления на:
control.center.set(0, 0, 0);
Затем сделайте это:
camera.position.copy(control.center).add(new THREE.Vector3(x, y, z+10));
где x, y и z - позиция вашей модели здания.
Обратите внимание, что я добавил +10 к z, чтобы камера находилась перед моделью. Измените +10 на другое значение, чтобы приблизиться / отойти к модели.
Ниже приведено решение Martin Joiner (СПАСИБО!!!), реализованное в этом коде:
Измените строку 45 с этого:
controls.coupleCenters = false;
к этому:
controls.coupleCenters = true;
а затем нажмите любую клавишу (или щелкните левой кнопкой мыши), чтобы увидеть исходное поведение, описанное Wouter Coebergh, до того, как рекомендованная логика Мартина будет добавлена в настраиваемые элементы управления орбитой.