2014-10-03 14 views
5

Sto lavorando a una semplice demo Three.js che utilizza OrbitControls.js.Three.js e OrbitControls.js - panoramica della telecamera parallela al piano terra (come Google Earth)

Mi piacerebbe cambiare il comportamento del panning in OrbitControls. Attualmente, quando si esegue la panoramica della telecamera, la fotocamera viene spostata su un piano perpendicolare alla direzione di visualizzazione. Mi piacerebbe cambiarlo in modo che la fotocamera rimanga una distanza costante dal piano di terra e si muova parallelamente ad essa. Google Earth utilizza un'impostazione di controllo simile.

Modifica: avrei dovuto menzionare questo dettaglio in primo luogo, ma mi piacerebbe anche il punto in cui si fa clic e si inizia a trascinare per rimanere direttamente sotto il cursore durante l'intero trascinamento. Deve esserci quella solida connessione tra il movimento del mouse e ciò che l'utente si aspetta che accada sullo schermo. Altrimenti, mi sento come se stessi "scivolando" quando provo a muovermi intorno alla scena.

Qualcuno può darmi una spiegazione di alto livello su come ciò potrebbe essere fatto (con o senza OrbitControls.js)?

+0

Il vostro "piano di massa" è in realtà un piano (ad esempio piatto o altezza variabile)? – caseygrun

+0

In realtà è piatto. È solo un piano infinito situato a (0,0,0) con un vettore in alto di (0,1,0). – Justin

+0

Oh, quindi vuoi solo eseguire una panoramica delle direzioni X/Z del mondo, mantenendo la fotocamera in una posizione Y fissa? – caseygrun

risposta

1

L'ho capito. Ecco la panoramica:

  1. Memorizza l'evento Mousedown da qualche parte.
  2. Quando il mouse si muove, ottieni il nuovo evento mouse.
  3. Per ciascuno di questi punti, trova i punti sull'aereo in cui si trovano quei clic (dovrai inserire i punti nello spazio della fotocamera, trasformarli nello spazio del mondo, quindi sparare un raggio dalla telecamera attraverso ogni punto per trovare le loro intersezioni con il piano. This page spiega il test di intersezione del piano di raggio).
  4. Sottrarre il punto di intersezione iniziale dello spazio del mondo dal punto di intersezione della fine dello spazio del mondo per ottenere l'offset.
  5. Sottrai quell'offset dal punto di mira della videocamera e il gioco è fatto!

Nel caso di OrbitControl.js, la fotocamera guarda sempre il punto di destinazione e la sua posizione è relativa a quel punto. Quindi quando cambi il bersaglio, la telecamera si muove con esso. Poiché l'obiettivo si trova sempre sul piano, la telecamera si sposta parallelamente a tale piano (purché si effettui la panoramica).

4

Qualche tempo fa stavo lavorando esattamente su questo problema, ad esempio l'adattamento di OrbitControls.js per mappare la navigazione.

+0

Questo mi ha aiutato molto, grazie. –

+1

sembra perfetto, ma non funziona più con la versione 75. Le proiezioni sono state deprecate e stanno causando un errore. –

4

Questo sembra come se fosse una bella funzionalità, e sembra essere una facile modifica allo OrbitControls.js esistente. Sostituire i seguenti due metodi.

var panLeft = function() { 

    var v = new THREE.Vector3(); 

    return function panLeft(distance, objectMatrix) { 

     var te = objectMatrix.elements; 

     // get elements from the X-column of matrix 
     v.set(te[ 0 ], 0, te[ 2 ]).normalize(); 
     v.multiplyScalar(- distance); 

     panOffset.add(v); 

    }; 

}(); 

var panUp = function() { 

    var v = new THREE.Vector3(); 

    return function panUp(distance, objectMatrix) { 

     var te = objectMatrix.elements; 

     // get elements from the Z-column of matrix 
     v.set(te[ 8 ], 0, te[ 10 ]).normalize(); 
     v.multiplyScalar(- distance); 

     panOffset.add(v); 

    }; 

}(); 

Capovolgere i segni se si desidera che il panning abbia il comportamento contrario.

I tasti freccia dovrebbero funzionare anche. Modificare handleKeyDown() se lo si desidera.

three.js r.75

+1

Ho provato questo. È vicino, ma sembra che il panUp sia indietro. Inoltre, avrei dovuto dirlo, ma volevo che il punto in cui si fa clic e si trascini per rimanere sotto il cursore durante l'intero trascinamento. Rende l'esperienza più naturale e tattile per l'utente. In realtà ho trovato una soluzione funzionante dopo aver postato questa domanda. Dovrei aggiungerlo alla mia risposta? – Justin

+0

1. Il cosiddetto panning "all'indietro" può essere risolto con un segno di capovolgimento, ma è necessario verificare il comportamento in una varietà di sistemi operativi, in particolare OSX. 2. Questo approccio mantiene il punto approssimativamente sotto il cursore quando la vista è diretta dall'alto. Quando l'angolo di visuale è acuto, la regolazione della distanza di pan di un fattore di cos (angolo di visuale) può dare il risultato desiderato. – WestLangley

0

Si dovrebbe impostare la fotocamera 'fino' a z ax:

camera.up.set(0,0,1)

E poi, il problema principale con OrbitControl è la sua funzione panUp(). Dovrebbe essere risolto.

La mia richiesta di pull: https://github.com/mrdoob/three.js/pull/12727

y ax è relativo agli assi della macchina fotografica e deve essere relativo ad un piano fisso in tutto il mondo. Per definire l'asse y previsto, effettuare una rotazione di 90 ° della telecamera x ax, in base all'asse z mondiale.

v.setFromMatrixColumn(objectMatrix, 0); // get X column of objectMatrix 
v.applyAxisAngle(new THREE.Vector3(0, 0, 1), Math.PI/2); 
v.multiplyScalar(distance); 
panOffset.add(v) 

Divertiti!

Problemi correlati