Domanda

Sto costruendo un gioco da tavolo in WebGL. La scheda può essere ruotata/ingrandita. Ho bisogno di un modo per tradurre un clic sull'elemento di tela (x, y) nel punto rilevante nello spazio 3D (x, y, z). Il risultato finale è che voglio conoscere la coordinata (x, y, z) che contiene il punto che tocca l'oggetto più vicino all'utente. Ad esempio, l'utente fa clic su un pezzo e immagini un raggio che viaggia attraverso lo spazio 3D che attraversa sia il pezzo che il tabellone, ma voglio la coord (x, y, z) del pezzo nel punto in cui si trovava toccato.

Sento che questo deve essere un problema molto comune, ma non riesco a trovare una soluzione nei miei googles. Ci deve essere un modo per proiettare la vista corrente dello spazio 3D in 2D in modo da poter mappare ogni punto nello spazio 2D al punto rilevante nello spazio 3D. Voglio che l'utente sia in grado di mouse su uno spazio sulla scheda e avere il colore di cambio spot.

È stato utile?

Soluzione

Stai cercando una funzione non professionista, che converte le coordinate dello schermo in un cast di raggi dalla posizione della telecamera nel mondo 3D. È quindi necessario eseguire test di intersezione Ray/Triangolo per trovare il triangolo più vicino alla fotocamera che interseca anche il raggio.

Ho un esempio di non proietto disponibile su jax/fotocamera.js#l568 - ma dovrai comunque implementare l'intersezione Ray/Triangle. Ne ho un'implementazione a jax/triangle.js#l113.

C'è un'alternativa più semplice e (di solito) più veloce, tuttavia, chiamata "picking". Usalo se si desidera selezionare un intero oggetto (ad esempio, un pezzo di scacchi) e se non ti interessa il fatto che il mouse abbia effettivamente fatto clic. Il WebGL Way per farlo è rendere l'intera scena in varie sfumature di blu (il blu è una chiave, mentre il rosso e il verde vengono utilizzati per ID univoci degli oggetti nella scena) per una trama, quindi leggi un pixel da quella trama. La decodifica dell'RGB nell'ID dell'oggetto ti darà l'oggetto che è stato fatto clic. Ancora una volta, l'ho implementato ed è disponibile a Jax/World.js#L82. (Vedi anche linee 146, 162, 175.)

Entrambi gli approcci hanno pro e contro (discusso qui E in alcuni dei commenti dopo) e dovrai capire quale approccio serve al meglio le tue esigenze. La raccolta è più lenta di scene enormi, ma non proietta in JS puro è estremamente lento (dal momento che JS stesso non è poi così veloce), quindi la mia migliore raccomandazione sarebbe quella di sperimentare entrambi.

Cordiali saluti, potresti anche guardare il progetto Glu e il codice non proietta, su cui ho basato il mio codice in modo libera: http://www.opengl.org/wiki/gluproject_and_gluunproject_code

Altri suggerimenti

Sto lavorando a questo problema al momento: l'approccio che sto adottando è

  1. Render gli oggetti per scegliere il buffer ciascuno con un colore unico
  2. Leggi il buffer pixel, mappa su oggetto scelto
  3. Render Oggetto scelto su un tampone con ogni pixel Colore una funzione di Z-Depth
  4. Leggi il buffer pixel, mappa su Z-Depth
  5. Abbiamo scelto oggetto e z approssimativo per le coord

Questa è la demo di lavoro

function onMouseUp(event) {

    event.preventDefault();        
    x_pos = (event.clientX / window.innerWidth) * 2 - 1;
    y_pos = -(event.clientY / window.innerHeight) * 2 + 1;
    z_pos = 0.5;

    var vector = new THREE.Vector3( x_pos , y_pos , z_pos );

    var projector = new THREE.Projector();
    projector.unprojectVector(vector, camera);
    var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
    var intersects = raycaster.intersectObjects(intersectObjects);

    if (intersects.length > 0) {

        xp = intersects[0].point.x.toFixed(2);
        yp = intersects[0].point.y.toFixed(2);
        zp = intersects[0].point.z.toFixed(2);  
        destination = new THREE.Vector3( xp , yp , zp );

        radians =  Math.atan2( ( driller.position.x - xp) , (driller.position.z - zp));
        radians += 90 * (Math.PI / 180);
        console.log(radians);

        var tween = new TWEEN.Tween(driller.rotation).to({ y : radians },200).easing(TWEEN.Easing.Linear.None).start();

    }

weissner-doors.de/drone/

coltivato da uno dei thread. non sono sicuro di (x, y, z) ma puoi ottenere il canvas(x,y) usando

getBoundingClientRect ()

function getCanvasCoord(){
  var mx = event.clientX;
  var my = event.clientY;
  var canvas = document.getElementById('canvasId');
  var rect = canvas.getBoundingClientRect();// check if your browser supports this
  mx = mx - rect.left;
  my = my - rect.top;
  return {x: mx , y: my};
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top