2016-10-06 3 views
14

Я работаю над орфографической камерой для нашего приложения THREE.js. По сути, эта камера представит сцену пользователю в 2D (пользователи могут переключаться между 2D и 3D-камерой). Эта камера позволит панорамировать и масштабировать точку мыши. У меня работает панорамирование, и у меня есть увеличение рабочего времени, но не масштабирование до точки мыши. Вот мой код:3D-камера с трёхмерным увеличением до мыши.

import React from 'react'; 
import T from 'three'; 

let panDamper = 0.15; 

let OrthoCamera = React.createClass({ 
    getInitialState: function() { 
    return { 
     distance: 150, 
     position: { x: 8 * 12, y: 2 * 12, z: 20 * 12 }, 
    }; 
    }, 
    getThreeCameraObject: function() { 
    return this.camera; 
    }, 
    applyPan: function (x, y) { // Apply pan by changing the position of the camera 
    let newPosition = { 
     x: this.state.position.x + x * -1 * panDamper, 
     y: this.state.position.y + y * panDamper, 
     z: this.state.position.z 
    }; 

    this.setState({position: newPosition}); 
    }, 
    applyDirectedZoom: function(x, y, z) { 
    let zoomChange = 10; 
    if(z < 0) zoomChange *= -1; 
    let newDistance = this.state.distance + zoomChange; 

    let mouse3D = { 
     x: (x/window.innerWidth) * 2 - 1, 
     y: -(y/window.innerHeight) * 2 + 1 
    }; 

    let newPositionVector = new T.Vector3(mouse3D.x, mouse3D.y, 0.5); 
    newPositionVector.unproject(this.camera); 
    newPositionVector.sub(this.camera.position); 

    let newPosition = { 
     x: newPositionVector.x, 
     y: newPositionVector.y, 
     z: this.state.position.z 
    }; 

    this.setState({ 
     distance: newDistance, 
     position: newPosition 
    }); 
    }, 
    render: function() { 
    let position = new T.Vector3(this.state.position.x, this.state.position.y, this.state.position.z); 

    let left = (this.state.distance/-2) * this.props.aspect + this.state.position.x; 
    let right = (this.state.distance/2) * this.props.aspect + this.state.position.x; 
    let top = (this.state.distance/2) + this.state.position.y; 
    let bottom = (this.state.distance/-2) + this.state.position.y; 

    // Using react-three-renderer 
    // https://github.com/toxicFork/react-three-renderer 
    return <orthographicCamera 
     {...(_.pick(this.props, ['near', 'far', 'name']))} 
     position={position} 
     left={left} 
     right={right} 
     top={top} 
     bottom={bottom} 
     ref={(camera) => this.camera = camera}/> 
    } 
}); 

module.exports = OrthoCamera; 

Некоторое масштабирование по направлению к точке мыши происходит, но кажется неустойчивым. Я хочу сохранить 2D-представление, так как я увеличиваю масштаб, я также перемещаю камеру (вместо того, чтобы иметь неперпендикулярную цель, которая убивает 2D-эффект).

Я взял реплики от this question. Насколько я могу судить, я успешно конвертируюсь в координаты THREE.js в mouse3D (см. Ответ на вопрос this question).

Итак, учитывая эту настройку, как я могу плавно масштабировать точку мыши (mouse3D), используя орфографическую камеру и поддерживая двумерный вид? Заранее спасибо.

+7

Есть ли у вас скрипка, чтобы опробовать код? – gaitat

+0

Итак, проблема заключается в повороте камеры при масштабировании? – mlkn

+0

Вы нашли решение Scott H –

ответ

2

Предполагая, что у вас есть камера, которая описывается положением и точкой обзора (или поворотным пунктом) в мировых координатах, масштабирование (или от) определенной точки довольно просто по своему ядру.

Ваше представление кажется еще проще: просто пара позиции/расстояния. Я не видел компонент вращения, поэтому я предполагаю, что ваша камера предназначена для орфографии сверху вниз.

В этом случае ваша точка взгляда (которая вам не понадобится) - это просто (position.x, position.y - distance, position.z).

В общем случае все, что вам нужно сделать, - это перемещение как положения камеры, так и точки взгляда в сторону точки масштабирования при сохранении нормальной камеры (т. Е. Направление). Обратите внимание, что это будет работать независимо от типа проекции или вращения камеры.

Если вы думаете об этом, это именно то, что происходит, когда вы увеличиваете масштаб в точке в 3D. Вы продолжаете смотреть в том же направлении, но вы все ближе (без достижения цели) приближаетесь к цели.

Если вы хотите, например, увеличить масштаб в 1,1 раза, вы можете представить, как масштабировать вектор, соединяющий ваше положение камеры с точкой масштабирования, на 1/1.1.

Вы можете сделать это просто интерполирования:

var newPosition = new THREE.Vector3(); 
newPosition.x = (orgPosition.x - zoomAt.x)/zoomFactor + zoomAt.x; 
newPosition.y = (orgPosition.y - zoomAt.y)/zoomFactor + zoomAt.y; 
newPosition.z = (orgPosition.z - zoomAt.z)/zoomFactor + zoomAt.z; 

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

var newDistance = newPosition.y 

Это должно быть сделано.

Если вы хотите установить минимальные и максимальные пределы расстояния между парами позиции/взгляда и положения/масштабирования, это будет немного сложнее (в основном в общем случае).