Three.js ThreeJS-具有不同旋转中心和观察点的轨道控制

Three.js ThreeJS-具有不同旋转中心和观察点的轨道控制,three.js,Three.js,我一直在我的应用程序中使用OrbitControl来允许摄像机在世界各地旋转。最近,我试图增强控制,使相机能够围绕任意点旋转,而不仅仅是相机注视点。我还没有取得多少成功 在代码中,如果我删除这个:this.object.lookAt(this.target)它工作得不好。有什么想法吗 一些图片需要澄清: 我围绕对象的中心(轴)旋转了摄影机,但摄影机没有注视中心。只需更新controls.target属性,例如: controls.target.set(1, 5, 7); 或以网格为目标: c

我一直在我的应用程序中使用OrbitControl来允许摄像机在世界各地旋转。最近,我试图增强控制,使相机能够围绕任意点旋转,而不仅仅是相机注视点。我还没有取得多少成功

在代码中,如果我删除这个:
this.object.lookAt(this.target)它工作得不好。有什么想法吗

一些图片需要澄清:


我围绕对象的中心(轴)旋转了摄影机,但摄影机没有注视中心。

只需更新controls.target属性,例如:

controls.target.set(1, 5, 7);
或以网格为目标:

controls.target.copy(mesh.position)

OrbitControls设计用于环绕场景,摄影机视口直接看着控件旋转目标。它们的设计并不是为了单独处理对象旋转和相机,它们有变形控制,但不支持阻尼

使用动态观察控件旋转,将摄影机视口锁定为查看中心(虚线),并围绕中心(红线)旋转:

如果移动/平移目标,则摄影机目标和旋转中心将一起移动,如下所示:

您需要的是旋转中心和摄影机目标是独立的,因此摄影机围绕对象旋转,同时观察以下某个点:

创建自定义摄影机/旋转功能似乎有两种方法:

1)修改轨道控制 将camera.lookAt更改为从controls.target偏移

查看控制所需的更改:

自定义动态观察控件演示:

2)修改转换控件 更改变换控件以允许阻尼、自由旋转和隐藏gizmo覆盖

自定义转换控件的演示

3)创建自己的对象旋转控件

import * as THREE from "https://threejs.org/build/three.module.js";

var mesh, renderer, scene, camera, controls;
var radius = 5;
var group;
var targetRotationX = 0;
var targetRotationOnMouseDownX = 0;
var targetRotationY = 0;
var targetRotationOnMouseDownY = 0;
var mouseX = 0;
var mouseXOnMouseDown = 0;
var mouseY = 0;
var mouseYOnMouseDown = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var finalRotationY

init();
animate();

function init() {

  // renderer
  renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.setPixelRatio(window.devicePixelRatio);
  document.body.appendChild(renderer.domElement);

  // scene
  scene = new THREE.Scene();

  // camera
  camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 10000);
  camera.position.set(0, radius * 2, radius * 2);
  camera.lookAt(0, radius, 0)

  // controls
  /*     controls = new OrbitControls( camera, renderer.domElement ); */
  document.addEventListener('mousedown', onDocumentMouseDown, false);
  document.addEventListener('touchstart', onDocumentTouchStart, false);
  document.addEventListener('touchmove', onDocumentTouchMove, false);

  // ambient
  scene.add(new THREE.AmbientLight(0x222222));

  // light
  var light = new THREE.DirectionalLight(0xffffff, 1);
  light.position.set(20, 20, 0);
  scene.add(light);

  // geometry
  var geometry = new THREE.SphereGeometry(radius, 12, 8);

  // material
  var material = new THREE.MeshPhongMaterial({
    color: 0x00ffff,
    flatShading: true,
    transparent: true,
    opacity: 0.7,
  });

  // mesh
  group = new THREE.Object3D();
  mesh = new THREE.Mesh(geometry, material);
  group.add(mesh);
  scene.add(group);
}

function onDocumentMouseDown(event) {
  event.preventDefault();
  document.addEventListener('mousemove', onDocumentMouseMove, false);
  document.addEventListener('mouseup', onDocumentMouseUp, false);
  document.addEventListener('mouseout', onDocumentMouseOut, false);
  mouseXOnMouseDown = event.clientX - windowHalfX;
  targetRotationOnMouseDownX = targetRotationX;
  mouseYOnMouseDown = event.clientY - windowHalfY;
  targetRotationOnMouseDownY = targetRotationY;
}

function onDocumentMouseMove(event) {
  mouseX = event.clientX - windowHalfX;
  mouseY = event.clientY - windowHalfY;
  targetRotationY = targetRotationOnMouseDownY + (mouseY - mouseYOnMouseDown) * 0.02;
  targetRotationX = targetRotationOnMouseDownX + (mouseX - mouseXOnMouseDown) * 0.02;
}

function onDocumentMouseUp(event) {
  document.removeEventListener('mousemove', onDocumentMouseMove, false);
  document.removeEventListener('mouseup', onDocumentMouseUp, false);
  document.removeEventListener('mouseout', onDocumentMouseOut, false);
}

function onDocumentMouseOut(event) {
  document.removeEventListener('mousemove', onDocumentMouseMove, false);
  document.removeEventListener('mouseup', onDocumentMouseUp, false);
  document.removeEventListener('mouseout', onDocumentMouseOut, false);
}

function onDocumentTouchStart(event) {
  if (event.touches.length == 1) {
    event.preventDefault();
    mouseXOnMouseDown = event.touches[0].pageX - windowHalfX;
    targetRotationOnMouseDownX = targetRotationX;
    mouseYOnMouseDown = event.touches[0].pageY - windowHalfY;
    targetRotationOnMouseDownY = targetRotationY;
  }
}

function onDocumentTouchMove(event) {
  if (event.touches.length == 1) {
    event.preventDefault();
    mouseX = event.touches[0].pageX - windowHalfX;
    targetRotationX = targetRotationOnMouseDownX + (mouseX - mouseXOnMouseDown) * 0.05;
    mouseY = event.touches[0].pageY - windowHalfY;
    targetRotationY = targetRotationOnMouseDownY + (mouseY - mouseYOnMouseDown) * 0.05;
  }
}

function animate() {
  requestAnimationFrame(animate);
  rotate();
  renderer.render(scene, camera);
}

function rotate() {
  group.rotation.y += (targetRotationX - group.rotation.y) * 0.1;
  finalRotationY = (targetRotationY - group.rotation.x);
  if (group.rotation.x <= 1 && group.rotation.x >= -1) {
    group.rotation.x += finalRotationY * 0.1;
  }
  if (group.rotation.x > 1) {
    group.rotation.x = 1
  }
  if (group.rotation.x < -1) {
    group.rotation.x = -1
  }
}
import*作为三个源”https://threejs.org/build/three.module.js";
var网格、渲染器、场景、摄影机、控件;
var半径=5;
var组;
var targetRotationX=0;
var TargetRotationNoMouseDownx=0;
var targetRotationY=0;
var TargetRotationNoMousedowny=0;
var-mouseX=0;
var mouseXOnMouseDown=0;
var-mouseY=0;
var mouseYOnMouseDown=0;
var windowHalfX=window.innerWidth/2;
var windowHalfY=window.innerHeight/2;
var金融旋转
init();
制作动画();
函数init(){
//渲染器
renderer=new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth、window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.doElement);
//场面
场景=新的三个。场景();
//摄像机
摄像头=新的三个透视摄像头(40,window.innerWidth/window.innerHeight,11000);
摄像机位置设置(0,半径*2,半径*2);
摄影机。注视(0,半径,0)
//控制
/*控件=新的轨道控件(摄影机、渲染器.doElement)*/
文件。添加的文件列表(“mousedown”,onDocumentMouseDown,false);
document.addEventListener(“touchstart”,onDocumentTouchStart,false);
文档。addEventListener('touchmove',onDocumentTouchMove,false);
//环境的
添加(新的3.AmbientLight(0x22222));
//轻的
var灯=新的三方向灯(0xffffff,1);
光。位置。设置(20,20,0);
场景。添加(灯光);
//几何学
var几何=新的三个。球度法(半径,12,8);
//材料
var材质=新的3.0网格材质({
颜色:0x00ffff,
对,,
透明:是的,
不透明度:0.7,
});
//网孔
group=new THREE.Object3D();
网格=新的三个网格(几何体、材质);
组。添加(网格);
场景。添加(组);
}
函数onDocumentMouseDown(事件){
event.preventDefault();
document.addEventListener('mousemove',onDocumentMouseMove,false);
文件。添加的列表器(“鼠标”,onDocumentMouseUp,false);
文件。添加的监听器('mouseout',onDocumentMouseOut,false);
mouseXOnMouseDown=event.clientX-windowHalfX;
targetRotationNoMouseDownX=targetRotationX;
mouseYOnMouseDown=event.clientY-windowHalfY;
targetRotationNoMousedowny=targetRotationY;
}
onDocumentMouseMove函数(事件){
mouseX=event.clientX-windowHalfX;
mouseY=event.clientY-windowHalfY;
targetRotationY=TARGETROTATIONNMOUSEDOWNY+(mouseY-mouseYOnMouseDown)*0.02;
targetRotationX=targetRotationNoMouseDownX+(mouseX-mouseXOnMouseDown)*0.02;
}
onDocumentMouseUp函数(事件){
document.removeEventListener('mousemove',onDocumentMouseMove,false);
删除文档监听器('mouseup',onDocumentMouseUp,false);
文件。删除文件监听器('mouseout',onDocumentMouseOut,false);
}
onDocumentMouseOut函数(事件){
document.removeEventListener('mousemove',onDocumentMouseMove,false);
删除文档监听器('mouseup',onDocumentMouseUp,false);
文件。删除文件监听器('mouseout',onDocumentMouseOut,false);
}
函数onDocumentTouchStart(事件){
if(event.touchs.length==1){
event.preventDefault();
mouseXOnMouseDown=event.touchs[0].pageX-windowHalfX;
targetRotationNoMouseDownX=targetRotationX;
mouseYOnMouseDown=event.touchs[0].pageY-windowHalfY;
targetRotationNoMousedowny=targetRotationY;
}
}
函数onDocumentTouchMove(事件){
if(event.touchs.length==1){
event.preventDefault();
mouseX=event.touchs[0].pageX-windowHalfX;
targetRotationX=targetRotationNoMouseDownX+(mouseX-mouseXOnMouseDown)*0.05;
mouseY=event.touchs[0].pageY-windowHalfY;
targetRotationY=TARGETROTATIONNMOUSEDOWNY+(mouseY-mouseYOnMouseDown)*0.05;
}
}
函数animate(){
请求动画帧(动画);
旋转();
渲染器。渲染(场景、摄影机);
}
函数rotate(){
group.rotation.y+=(targetRotationX-group.rotation.y)*0.1;
最终旋转=(targetRotationY-group.rotation.x);
if(group.rotation.x=-1){
group.rotation.x+=最终旋转Y*0.1;
}
如果