Three.js Orbit Controls

강정우·2025년 1월 9일
0

three.js

목록 보기
14/24
post-thumbnail

Orbit Controls

우선 Orbit Controls 은 three.js core 의 일부가 아니고 add-on 이다.

또한 three.js 에는 여러 컨트롤러들이 존재한다.

camera, control

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100)
camera.position.z = 2
camera.lookAt(0.5, 0.5, 0.5)

const controls = new OrbitControls(camera, renderer.domElement)
// controls.target.set(.5, .5, .5)

카메라 객체에는 lookAt() 메서드가, 컨트롤 객체에는 .set() 이 존재한다.
이때, 컨트롤의 기본 값은 (0, 0, 0) 이다. 따라서 만약 카메라 초기값만 세팅해주고 컨트롤의 초기값을 카메라 초기값과 다르게 설정하면 의도한 바와는 다르게 동작된다.
하지만 lootAt() 메서드를 사용하여 세팅하기보단 더 간단하게 컨트롤 객체의 update() 함수를 사용하는 것이 더 좋다.
왜냐하면 lookAt() 은 control 을 위해 나온 함수가 아니기 때문에 더 콘크리트한 코드를 작성하고 싶다면 컨트롤 함수를 사용하여 Control 객체를 조절하는 것이 좋다.

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100)
camera.position.z = 2
// camera.lookAt(0.5, 0.5, 0.5)

const controls = new OrbitControls(camera, renderer.domElement)
controls.target.set(.5, .5, .5)
// animation 함수에서 실행해줘야함.
controls.update()

event

const controls = new OrbitControls(camera, renderer.domElement)

controls.addEventListener('start', () => console.log("Controls Start Event"))
controls.addEventListener('change', () => console.log("Controls Change"))
controls.addEventListener('end', () => console.log("Controls End Event"))

start: 마우스, 터치를 누를 때
change: 마우스, 터치를 하여 욺직일 때
end: 마우스, 터치를 땔 때

autoRotate

controls.autoRotate = true
controls.autoRotateSpeed = 10

자동으로 돌아가도록 하는 속성 값이며 반드시 animate 함수안에 controls.update() 가 있어야 매 프레임 마다 적용되어 동작한다.

Damping

controls.enableDamping = true
controls.dampingFactor = .01

사용자가 회전 후 관성으로 조금 더 나아가도록 부드럽게 설정하는 설정 값이다.

키보드 컨트롤

controls.listenToKeyEvents(window)
controls.keys = {
    LEFT: 'KeyA', // default 'ArrowLeft'
    UP: 'KeyW', // default 'ArrowUp'
    RIGHT: 'KeyD', // default 'ArrowRight'
    BOTTOM: 'KeyS' // default 'ArrowDown'
}
controls.mouseButtons = {
    LEFT: THREE.MOUSE.ROTATE,
    MIDDLE: THREE.MOUSE.DOLLY,
    RIGHT: THREE.MOUSE.PAN
}
controls.touches = {
    ONE: THREE.TOUCH.ROTATE,
    TWO: THREE.TOUCH.DOLLY_PAN
}

키보드를 사용하여 카메라 위치를 옮길 수 있다. 또한 화살표로 되어있는 키를 다른 키로 매핑할 수 있다.
또한 마우스, 터치를 고려하려 키와 해당 이벤트를 매핑할 수 있다.

screenSpacePanning

controls.screenSpacePanning = false 마우스 오른쪽 클릭 즉, pan 이벤트가 마우스 휠 이벤트 즉, zoom in, out 이벤트로 바뀐다.

contorl 제한하기

// 상하
controls.minPolarAngle = 0
controls.maxPolarAngle = Math.PI
// 좌우
controls.minAzimuthAngle = 0
controls.maxAzimuthAngle = Math.PI / 2
// 줌 in, out 의 최대, 최소 거리
controls.maxDistance = 4
controls.minDistance = 1.5

controls.enabled = false
controls.enablePan = false
controls.enableRotate = false
controls.enableZoom = false

💻 전체 코드

import './style.css'
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import Stats from 'three/addons/libs/stats.module.js'

const scene = new THREE.Scene()

const gridHelper = new THREE.GridHelper()
gridHelper.position.y = -0.5
scene.add(gridHelper)

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100)
camera.position.z = 2

const renderer = new THREE.WebGLRenderer({antialias: true})
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)

window.addEventListener('resize', () => {
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    renderer.setSize(window.innerWidth, window.innerHeight)
})

const info = document.createElement('div')
info.style.cssText = 'position:absolute;bottom:10px;left:10px;color:white;font-family:monospace;font-size: 17px;filter: drop-shadow(1px 1px 1px #000000);'
document.body.appendChild(info)

const controls = new OrbitControls(camera, renderer.domElement)

// camera.lookAt(0.5, 0.5, 0.5)
// controls.target.set(.5, .5, .5)
// controls.update()

controls.addEventListener('change', () => {
    info.innerText =
        'Polar Angle : ' +
        ((controls.getPolarAngle() / -Math.PI) * 180 + 90).toFixed(2) +
        '°\nAzimuth Angle : ' +
        ((controls.getAzimuthalAngle() / Math.PI) * 180).toFixed(2) +
        '°'
})
// controls.addEventListener('start', () => console.log("Controls Start Event"))
// controls.addEventListener('end', () => console.log("Controls End Event"))
// controls.autoRotate = true
// controls.autoRotateSpeed = 10
// controls.enableDamping = true
// controls.dampingFactor = .01
// controls.listenToKeyEvents(window)
// controls.keys = {
//     LEFT: 'KeyA', // default 'ArrowLeft'
//     UP: 'KeyW', // default 'ArrowUp'
//     RIGHT: 'KeyD', // default 'ArrowRight'
//     BOTTOM: 'KeyS' // default 'ArrowDown'
// }
// controls.mouseButtons = {
//     LEFT: THREE.MOUSE.ROTATE,
//     MIDDLE: THREE.MOUSE.DOLLY,
//     RIGHT: THREE.MOUSE.PAN
// }
// controls.touches = {
//     ONE: THREE.TOUCH.ROTATE,
//     TWO: THREE.TOUCH.DOLLY_PAN
// }
// controls.screenSpacePanning = false
// controls.minAzimuthAngle = 0
// controls.maxAzimuthAngle = Math.PI / 2
// controls.minPolarAngle = 0
// controls.maxPolarAngle = Math.PI
// controls.maxDistance = 4
// controls.minDistance = 1.5
// controls.enabled = false
// controls.enablePan = false
// controls.enableRotate = false
// controls.enableZoom = false

const geometry = new THREE.BoxGeometry()
const material = new THREE.MeshNormalMaterial({ wireframe: true })

const cube = new THREE.Mesh(geometry, material)
scene.add(cube)

const stats = new Stats()
document.body.appendChild(stats.dom)

function animate() {
    requestAnimationFrame(animate)

    controls.update()

    renderer.render(scene, camera)

    stats.update()
}

animate()
profile
智(지)! 德(덕)! 體(체)!

0개의 댓글