먼저 사용하는 함수는 다음과 같습니다. (에니메이션을 위하 GSAP 라이브러리를 사용하였음)
_zoomFit(object3D, viewMode, bFront, viewAngle) {
const box = new THREE.Box3().setFromObject(object3D);
const sizeBox = box.getSize(new THREE.Vector3()).length();
const centerBox = box.getCenter(new THREE.Vector3());
const offset = new THREE.Vector3(viewMode==="X"?1:0, viewMode==="Y"?1:0, viewMode==="Z"?1:0);
if(!bFront) offset.negate();
offset.applyAxisAngle(new THREE.Vector3(1,0,0), THREE.Math.degToRad(viewAngle));
const newPosition = new THREE.Vector3().copy(centerBox).add(offset);
const halfSizeModel = sizeBox * 0.5;
const halfFov = THREE.Math.degToRad(this._camera.fov * .5);
const distance = halfSizeModel / Math.tan(halfFov);
const direction = (new THREE.Vector3()).subVectors(newPosition, centerBox).normalize();
newPosition.copy(direction.multiplyScalar(distance).add(centerBox));
const oldPosition = this._camera.position.clone();
gsap.to(this._camera.position, { duration: 0.5, x: newPosition.x, y: newPosition.y, z: newPosition.z});
// camera.lookAt(centerBox.x, centerBox.y, centerBox.z); // OrbitControls를 사용하지 않은 경우
// this._controls.target.copy(centerBox); // OrbitControls를 사용하고 있는 경우
gsap.to(this._controls.target, { duration: 0.5,
x: centerBox.x, y: centerBox.y, z: centerBox.z});
}
사용은 줌인 대상을 마우스로 클릭해 선택한다고 할때.. 먼저 RayCaster 객체를 하나 정의하구요.
_setupPicking() {
const raycaster = new THREE.Raycaster();
this._divContainer.addEventListener("click", this._onClick.bind(this));
this._raycaster = raycaster;
}
클릭 이벤트인 _onClick은 다음과 같습니다.
_onClick(event) {
if(!event.ctrlKey) return false;
const width = this._divContainer.clientWidth;
const height = this._divContainer.clientHeight;
const xy = {x: (event.offsetX / width) * 2 - 1, y: -(event.offsetY / height) * 2 + 1};
this._raycaster.setFromCamera(xy, this._camera);
const targets = this._raycaster.intersectObjects(this._scene.children);
if(targets.length > 0) {
const mesh = targets[0].object;
this._zoomFit(mesh, "Y", true, 50);
}
}
이 애니메이션 ZoomIn 기능을 이용해 만든 단위 기능에 대한 예제 영상은 다음과 같습니다.
비디오를 지원하지 않는 웹브라우져입니다.