74 votes

Faire tourner la caméra dans Three.js avec la souris

J'ai pas mal d'objets dans ma scène, donc les faire tous pivoter pourrait être un problème. Quel est donc le moyen le plus simple de déplacer la caméra à l'origine par un clic de souris et un glissement ? De cette façon, toutes les lumières et tous les objets de la scène sont au même endroit, et la seule chose qui change est la caméra. Three.js ne permet pas de faire pivoter une caméra autour d'un point, n'est-ce pas ?

Merci.

68voto

Burt Sampson Points 379

Voici un projet avec une caméra rotative . En regardant la source, on a l'impression de déplacer la position de la caméra dans un cercle.

function onDocumentMouseMove( event ) {

    event.preventDefault();

    if ( isMouseDown ) {

        theta = - ( ( event.clientX - onMouseDownPosition.x ) * 0.5 )
                + onMouseDownTheta;
        phi = ( ( event.clientY - onMouseDownPosition.y ) * 0.5 )
              + onMouseDownPhi;

        phi = Math.min( 180, Math.max( 0, phi ) );

        camera.position.x = radious * Math.sin( theta * Math.PI / 360 )
                            * Math.cos( phi * Math.PI / 360 );
        camera.position.y = radious * Math.sin( phi * Math.PI / 360 );
        camera.position.z = radious * Math.cos( theta * Math.PI / 360 )
                            * Math.cos( phi * Math.PI / 360 );
        camera.updateMatrix();

    }

    mouse3D = projector.unprojectVector(
        new THREE.Vector3(
            ( event.clientX / renderer.domElement.width ) * 2 - 1,
            - ( event.clientY / renderer.domElement.height ) * 2 + 1,
            0.5
        ),
        camera
    );
    ray.direction = mouse3D.subSelf( camera.position ).normalize();

    interact();
    render();

}

Voici une autre démo et dans celui-ci je pense que ça crée juste un nouveau THREE.TrackballControls avec la caméra comme paramètre, ce qui est probablement la meilleure façon de procéder.

controls = new THREE.TrackballControls( camera );
controls.target.set( 0, 0, 0 )

9 votes

Assurez-vous d'ajouter les écouteurs d'événements. Dans la source, ils ressemblent à ceci : document.addEventListener( 'mousemove', onDocumentMouseMove, false ) ;

0 votes

Je ne parviens pas à faire la même chose qu'avec les commandes orthographiques par boule de commande, mais je peux vous aider à le faire avec les commandes orthographiques par boule de commande en utilisant la caméra orthographique.

1 votes

Vous avez mentionné le code source mais je n'arrive pas à le trouver. Lorsque je regarde les fichiers JS demandés par l'application dont vous avez donné le lien dans les outils de développement de Chrome, je ne vois pas le code que vous avez publié ci-dessus. Pouvez-vous m'indiquer le lien vers la source ou m'expliquer comment vous l'avez trouvé ? Je suis surtout curieux de savoir où/comment sont définies les variables isMouseDown et projector auxquelles votre extrait de code fait référence. Merci !

56voto

ekcrisp Points 192

Regardez les exemples suivants

http://threejs.org/examples/#misc_controls_orbit

http://threejs.org/examples/#misc_controls_trackball

Il existe d'autres exemples de contrôles de souris différents, mais tous deux permettent à la caméra de tourner autour d'un point et de zoomer et dézoomer avec la molette de la souris, la principale différence étant que OrbitControls impose la direction de la caméra vers le haut, et TrackballControls permet à la caméra de tourner à l'envers.

Tout ce que vous avez à faire est d'inclure les contrôles dans votre document html.

<script src="js/OrbitControls.js"></script>

et inclure cette ligne dans votre source

controls = new THREE.OrbitControls( camera, renderer.domElement );

4 votes

Une seule ligne de controls = new THREE.OrbitControls( camera, renderer.domElement ); Vous devez soit ajouter un gestionnaire de l'événement de changement et, dans ce gestionnaire, appeler la fonction de changement d'adresse. renderer.render(scene, camera) ou ajouter la boucle d'animation et appeler controls.update() dans le animate() .

2 votes

J'ai réussi à faire fonctionner ce système en important simplement le module OrbitControls et en l'instanciant. Aucun gestionnaire ou appel de mise à jour n'est nécessaire. (Il prend une référence à l'élément DOM du moteur de rendu pour attacher les handlers lui-même et au moteur de rendu pour appeler render lui-même).

6voto

Hurden Points 783

Cela pourrait servir de bon point de départ pour déplacer/ rotatif /zoomer une caméra avec la souris/trackpad (en tapuscrit) :

class CameraControl {
    zoomMode: boolean = false
    press: boolean = false
    sensitivity: number = 0.02

    constructor(renderer: Three.Renderer, public camera: Three.PerspectiveCamera, updateCallback:() => void){
        renderer.domElement.addEventListener('mousemove', event => {
            if(!this.press){ return }

            if(event.button == 0){
                camera.position.y -= event.movementY * this.sensitivity
                camera.position.x -= event.movementX * this.sensitivity        
            } else if(event.button == 2){
                camera.quaternion.y -= event.movementX * this.sensitivity/10
                camera.quaternion.x -= event.movementY * this.sensitivity/10
            }

            updateCallback()
        })    

        renderer.domElement.addEventListener('mousedown', () => { this.press = true })
        renderer.domElement.addEventListener('mouseup', () => { this.press = false })
        renderer.domElement.addEventListener('mouseleave', () => { this.press = false })

        document.addEventListener('keydown', event => {
            if(event.key == 'Shift'){
                this.zoomMode = true
            }
        })

        document.addEventListener('keyup', event => {
            if(event.key == 'Shift'){
                this.zoomMode = false
            }
        })

        renderer.domElement.addEventListener('mousewheel', event => {
            if(this.zoomMode){ 
                camera.fov += event.wheelDelta * this.sensitivity
                camera.updateProjectionMatrix()
            } else {
                camera.position.z += event.wheelDelta * this.sensitivity
            }

            updateCallback()
        })
    }
}

le déposer comme :

this.cameraControl = new CameraControl(renderer, camera, () => {
    // you might want to rerender on camera update if you are not rerendering all the time
    window.requestAnimationFrame(() => renderer.render(scene, camera))
})

Contrôles :

  • déplacer pendant [maintenir la souris à gauche / un seul doigt sur le pavé tactile]. pour déplacer la caméra dans le plan x/y
  • déplacer [molette de la souris / deux doigts sur le trackpad] pour se déplacer vers le haut/bas dans la direction z
  • maintenir shift + [molette de la souris / deux doigts sur le trackpad]. pour effectuer un zoom avant/arrière par augmentation/diminution du champ de vision
  • déplacer pendant en maintenant [la souris à droite / deux doigts sur le trackpad]. pour faire tourner la caméra (quaternion)

En outre :

Si vous voulez zoomer en changeant la "distance" (le long de yz) au lieu de changer le champ de vision, vous pouvez augmenter ou diminuer la position y et z de la caméra tout en gardant le rapport de la position y et z inchangé :

// in mousewheel event listener in zoom mode
const ratio = camera.position.y / camera.position.z
camera.position.y += (event.wheelDelta * this.sensitivity * ratio)
camera.position.z += (event.wheelDelta * this.sensitivity)

1 votes

Ça a l'air intéressant ! Auriez-vous une démo en direct à nous montrer ?

0 votes

Je ne le fais pas, mais c'est une bonne idée, je mettrai à jour la réponse avec elle ces jours-ci, je l'espère.

4voto

Pavel Galaton Points 58

Jetez un coup d'oeil à THREE.PointerLockControls

1 votes

3voto

nguyentran Points 353

OrbitControls et TrackballControls semblent convenir à cette fin.

controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;

mise à jour dans le rendu

controls.update();

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X