Come implementare gizmos di traduzione, ridimensionamento, rotazione per manipolare le trasformazioni di oggetti 3D?


11

Sto sviluppando un editor 3D di base. Utilizza OpenGL per il rendering di un mondo 3D. In questo momento la mia scena è solo poche scatole di dimensioni diverse e sono sul palco in cui voglio essere in grado di selezionare ogni scatola e quindi spostarla / ridimensionarla / ruotarla per ottenere qualsiasi trasformazione che voglio.

Come posso risolvere il problema dell'implementazione sia del rendering di questi strumenti (o handle, o di come la gente di solito li chiama), sia di selezionarli su ciascun asse per eseguire la modifica della trasformazione con il mio mouse? Per chiarezza: inserisci qui la descrizione dell'immagine

La mia ricerca finora ha suggerito che l'approccio più pulito è quello di avere un riquadro di delimitazione allineato agli assi per freccia nel gizmo e un altro per quadrato (quelli che muovono l'oggetto su un piano anziché un singolo asse) e quindi lanciano un raggio dal mouse posizione e vedere con cosa si scontra. Ma questo è ancora un po 'troppo astratto per me, apprezzerei ulteriori indicazioni su come andrebbe questo algoritmo (lo pseudocodice è più che sufficiente)


1
Di solito, trasmetti un raggio nel mondo con la posizione del mouse e vedi se colpisci un gizmo. Puoi anche trasformare gizmo nello spazio dello schermo per rilevare le collisioni lì. Di solito, però, fai solo una certa distanza dal raggio al tipo di segmento di cose. La rotazione viene generalmente eseguita come una sfera virtuale. Vedi Melax in Gemme di programmazione del gioco 1. La traduzione è praticamente un prodotto a punti, così come la scala.
RandyGaul,

Risposte:


9

Ad un certo punto del mio tempo a e-on ho mantenuto il gizmos della linea di prodotti Vue .
Posso dirti che ci vorranno più giorni, a tempo pieno.
A meno che non trovi una libreria o un modo super intelligente, il modo classico è quello di ottenere le coordinate del mouse nella finestra quando fai clic, se è una coordinata relativa al viewport, puoi semplicemente dividere xey per larghezza e altezza, tu ottiene un vettore (float 2d) nell'intervallo [0,1]. sottrarre (0,5,0,5) per ottenere un intervallo [-0,5, 0,5] sia per x che per y.
Quindi, si crea un raggio da questa coordinata usando semplicemente xey come raggio xey, e si imposta z sulla distanza focale. a volte le proporzioni sono un dolore nel culo in questa operazione. Un po 'di errori di prova e di prova ti riparerà.
Quindi, devi controllare l'intersezione con i tuoi elementi gizmos, o hai una mesh che hai generato, o modellato in blender o altri DCC, o parti mesh che possono articolarsi tra loro ... Basta usare quelle parti mesh come un raggio / query di intersezione triangolare.
O se ce l'hai, raggio / cilindro, raggio / sfera secondo il tuo aspetto e le parti gizmo.
È necessario disporre di routine di intersezione in grado di applicare una matrice di trasformazione sulla primitiva in cui si scontrano . È estremamente importante perché il tuo gizmo si tradurrà con l'oggetto che serve a muoversi, ruoterà e si ridimensionerà con l'inverso della distanza dalla telecamera, in modo da mantenere una dimensione proiettata fissa sullo schermo.
Quindi hai la parte di interazione, il più semplice è prendere il delta del punto in cui il mouse è stato il primo evento "mouse down", e l'attuale posizione di "Spostamento del mouse", in puro 2D, e usare questo delta come movimento dell'asse corrente nello spazio mondiale, moltiplicato per alcuni kche decidi empiricamente. Secondo le tue unità interne rispetto al pixel rispetto all'attuale scala di zoom ecc.
Il passaggio finale è semplicemente quello di applicare la matrice di gizmo all'oggetto manipolato, in modo che lo segua.

Ti dico che è un bel viaggio all'inferno da implementare, e se lo stai facendo nel tuo tempo libero, attendi più di una settimana. Più settimane se stai scoprendo completamente il campo. Più di un mese se i tuoi fine settimana sono impegnati con altre attività :)

Ti suggerisco di scaricare Embree 2.0 da Intel per eseguire la query di intersezione raggio / triangolo per te, quindi non devi preoccuparti di codificarlo. Oppure potresti copiare / incollare senza pietà e adattare il codice dal frullatore ... Penso che siano passati alla licenza Apache? Dovrebbe essere possibile legalmente.


1
Grazie mille per la risposta. È davvero utile. Sapevo di non essere pazzo quando mi sentivo sopraffatto da un compito apparentemente facile. Sottovaluto la sua difficoltà e ho finito per rimanere bloccato sullo stesso problema per giorni .. La prossima volta che vado a gestirlo, sarò sicuro di aver fatto un buon piano. Grazie
Grimshaw,

0

Per manipolatore-traduttore uso il seguente algoritmo:

1) Quando il mouse è abbassato, dobbiamo verificare se il raggio interseca la freccia. Ad esempio consideriamo la freccia X. Costruiamo Ray nello spazio mondiale (basato sulla frustum della fotocamera e sulla posizione del mouse). Costruiamo un piano in cui si trova l'asse x: la sua normale è uguale a V croce X croce V, dove V - vettore dal centro alla telecamera, X - rappresenta l'asse x. Quindi interseciamo il raggio con il piano e quindi troviamo il punto di intersezione nelle coordinate del mondo. Quindi proiettiamo il segmento dell'asse x e il punto risultante sullo schermo, troviamo la distanza tra il segmento proiettato e il punto proiettato sullo schermo. se è inferiore a pochi pixel, il mouse incide sull'asse. Inoltre calcoliamo il vettore delta dello spazio mondiale tra il centro della selezione e la nostra intersezione.

Questa procedura viene eseguita per 3 assi, quindi troviamo le distanze da tutti gli assi. Trova la distanza minima. così abbiamo trovato con quale asse si interseca il mouse.

2) Quando si sposta il mouse. sappiamo da quale asse si muove l'oggetto (da 1). troviamo l'intersezione spaziale mondiale del raggio con il piano (come in 1). inoltre proiettiamo il punto di intersezione sulla linea su cui si muove l'oggetto. posizione manipolatore finale = intersezione + delta.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.