Подтвердить что ты не робот

Как поместить камеру в объект

Используя three.js у меня есть следующее.

  • Сцена, содержащая несколько экземпляров Object3D
  • Несколько предопределенных позиций камеры Vector3
  • Динамическая ширина/высота холста при изменении размера экрана
  • Пользователь может выбрать объект (сверху)
  • Пользователь может выбрать положение камеры (сверху)

Учитывая выбранный объект и положение камеры, которое они выбрали, как рассчитать конечное положение камеры, чтобы "наилучшим образом подогнать" объект на экране?

Если на некоторых экранах положения камеры используются "как есть", объекты стекают по краю моего окна просмотра, в то время как другие выглядят меньше. Я полагаю, что возможно приспособить объект к усечению камеры, но не смог найти ничего подходящего.

4b9b3361

Ответ 1

Я предполагаю, что вы используете перспективную камеру.

Вы можете установить положение камеры, поле обзора или и то, и другое.

Следующий расчет является точным для объекта, который является кубом, поэтому подумайте в терминах рамки ограничения объекта, выровненной к лицу камеры.

Если камера находится в центре и просматривает куб, определите

dist = distance from the camera to the _closest face_ of the cube

и

height = height of the cube.

Если вы установите поле зрения камеры следующим образом

fov = 2 * Math.atan( height / ( 2 * dist ) ) * ( 180 / Math.PI ); // in degrees

то высота куба будет соответствовать видимой высоте.

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

Если поле обзора фиксировано, воспользуйтесь приведенным выше уравнением для решения.


EDIT: если вы хотите, чтобы куб width соответствовал видимой ширине, пусть aspect - соотношение сторон холста (ширина холста, деленное на высоту холста), и установите поле зрения камеры так же

fov = 2 * Math.atan( ( width / aspect ) / ( 2 * dist ) ) * ( 180 / Math.PI ); // in degrees

three.js r.69

Ответ 2

На основании ответа WestLangleys вот как вы вычисляете расстояние с фиксированным полем зрения камеры:

dist = height / 2 / Math.tan(Math.PI * fov / 360);

Ответ 3

Чтобы рассчитать, как далеко от камеры разместить объект на экране, вы можете использовать эту формулу (в Javascript):

// Convert camera fov degrees to radians
var fov = camera.fov * ( Math.PI / 180 ); 

// Calculate the camera distance
var distance = Math.abs( objectSize / Math.sin( fov / 2 ) );

Где objectSize - высота или ширина объекта. Для объектов куба/сферы вы можете использовать либо высоту, либо ширину. Для объекта без куба/без шара, где длина или ширина больше, используйте var objectSize = Math.max( width, height ), чтобы получить большее значение.

Обратите внимание, что если ваше местоположение объекта не находится в 0, 0, 0, вам нужно настроить положение камеры, чтобы включить смещение.

Здесь CodePen показывает это в действии. Соответствующие строки:

var fov = cameraFov * ( Math.PI / 180 );
var objectSize = 0.6 + ( 0.5 * Math.sin( Date.now() * 0.001 ) );

var cameraPosition = new THREE.Vector3(
    0,
    sphereMesh.position.y + Math.abs( objectSize / Math.sin( fov / 2 ) ),
    0
);

Вы можете видеть, что если вы захватите ручку окна и измените ее размер, сфера по-прежнему занимает 100% высоты экрана. Кроме того, объект масштабируется вверх и вниз с помощью синусоидальной моды (0.6 + ( 0.5 * Math.sin( Date.now() * 0.001 ) )), чтобы показать, что положение камеры учитывает масштаб объекта.

Ответ 4

Из предложения user151496 об использовании соотношения сторон это, похоже, работает, хотя я тестировал только несколько наборов параметров.

var maxDim = Math.max(w, h);
var aspectRatio = w / h;        
var distance = maxDim/ 2 /  aspectRatio / Math.tan(Math.PI * fov / 360);

Ответ 5

попробуйте это для OrbitControls

    let padding = 48;
    let w = Math.max(objectLength, objectWidth) + padding;
    let h = objectHeight + padding;

    let fovX = camera.fov * (aspectX / aspectY);
    let fovY = camera.fov;

    let distanceX = (w / 2) / Math.tan(Math.PI * fovX / 360) + (w / 2);
    let distanceY = (h / 2) / Math.tan(Math.PI * fovY / 360) + (w / 2);

    let distance = Math.max(distanceX, distanceY);