mini-skamja/utils/calculateScaleToFit.ts

57 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Box3, PerspectiveCamera, Vector3 } from 'three'
import { degToRad } from 'three/src/math/MathUtils.js';
/**
* Вычисляет масштаб объекта и позицию камеры, чтобы объект полностью помещался в видимой области.
* @param object - Объект Three.js (например, загруженная модель).
* @param camera - Экземпляр камеры.
* @param controls - Экземпляр OrbitControls.
* @param distance - Расстояние от камеры до объекта.
* @param cameraOffset - Коэффициенты смещения камеры (x, y, z).
*/
export default function (
object: any,
camera: PerspectiveCamera,
controls: any,
distance: number,
cameraOffset: { x: number; y: number; z: number }
) {
// Обновляем мировую матрицу объекта
object.updateWorldMatrix(true, true)
const fov = camera.fov // Угол обзора камеры
const aspect = camera.aspect // Соотношение сторон
const bbox = new Box3().setFromObject(object) // Вычисляем bounding box
const center = new Vector3()
bbox.getCenter(center) // Центр объекта
const size = new Vector3()
bbox.getSize(size) // Размеры объекта
// Рассчитываем масштаб, чтобы объект полностью помещался в видимой области
const vFOV = degToRad(fov) // Угол обзора в радианах
const visibleHeight = 2 * Math.tan(vFOV / 2) * distance // Видимая высота
const visibleWidth = visibleHeight * aspect // Видимая ширина
const scaleX = visibleWidth / size.x
const scaleY = visibleHeight / size.y
const scaleZ = visibleWidth / size.z
const scale = Math.min(scaleX, scaleY, scaleZ)
// Позиционируем камеру с учетом смещения
camera.position.set(
center.x + distance * cameraOffset.x,
center.y + distance * cameraOffset.y,
center.z + distance * cameraOffset.z
)
// Устанавливаем цель для OrbitControls
if (controls) {
controls.target.set(center.x, center.y, center.z)
controls.update() // Обновляем контроллы
}
return { scale, center }
}