Vai al contenuto

Rotate, Scale E Move In Maxscript


Michele71

Recommended Posts

Ciao a tutti :)

Premesso che l'unico linguaggio di Script che conosco appena è MaxScript, volevo togliermi delle spine dal mio fianco che ho da moltissimo tempo.

Ho un serio problema a capire le rotazioni, la scalatura e muovi in MaxScript.

Ovvero, seguendo le normali procedure di Move rotate e scale (trasformazioni Standard) va tutto bene, ma se devo creare uno spinner che mi permette di roteare ecc. un piano ho serie difficoltà nella sua comprenzione.

Esempio:

rollout test "Test Rotazione"

(

Spinner sp "X" range:[-180,180,0]

on sp changed val do

(

rotate $ (angleaxis val [1,0,0])--creato con MacroRecorder

)

)

createdialog test

Perchè si comporta cosi?

Perchè la rotazione è sfasata e sbagliata?

Perchè la rotazione non corrisponde con la trasformazione "Absolute World" in "Trasform Type-In"?

Come realizzare (in termini Teorici e Pratici) una rotazione (scala e muovi) come quella tipica in Max (Select and Move, Select and Rotate e Select and Scale)?

E' da moltissimo tempo che provo e provo ma niente (o meglio) confusione totale...

Sapreste farmi una spiegazione (quasi tutorial) di come creare la sopra citata questione?

Michele

Link al commento
Condividi su altri siti

bn-top

la rotazione non ti torna perchè ogni volta che tu modifichi il valore del tuo spinner tu ruoti l'oggetto, ma la rotazione si somma a quella eseguita nelle tue precedenti modifiche allo spinner.

Esempio:

1°volta: assegni 1 allo spinner -> l'oggetto in totale ha ruotato di 1

2°volta: assegni 2 allo spinner -> l'oggetto in totale ha ruotato di 3(cioè prima 1 e poi 2)

3°volta: assegni 3 allo spinner -> l'oggetto in totale ha ruotato di 6(cioè prima 1, poi 2 ed infine 3)

se guardi questo esempio noterai che la rotazione è corretta:


precRot=0.0


rollout test "Test Rotation"

(

	Spinner sp "X" range: [-180,180,0]


	on test close do

	(

		currentRot = (eulerangles (-precRot) 0 0) as quat


		for obj in selection do rotate obj currentRot

	)	


	on sp changed val do

	(

		currentRot = (eulerangles (val-precRot) 0 0) as quat


		for obj in selection do rotate obj currentRot


		precRot=val

	)


)

CreateDialog test 

perchè ogni volta sottraggo il valore della rotazione precedente a val, che è il valore della nuova rotazione.

Poi ho aggiunto un evento che fa si che la rotazione dell'oggetto una volta che chiudi il rollout venga rimessa a posto.

Te l'ho messa solo per farti capire il concetto.

E' uno script di esempio, per trasformarlo in uno script finale andrebbe sistemato un pò(ad esempio precRot è una variabile globale e bisognerebbe dargli un nome un pò più complicato...)

ciao

Link al commento
Condividi su altri siti

Grazie Coren, ora sono sparite un pò di nubi dalla mia testa :P

Allora ricapitolando:

------------------------------------------------------------------------------------

precRot=0.0 -- variabile globale

rollout test "Test Rotation"(

Spinner sp "X" range: [-180,180,0]

on sp changed val do

(

currentRot = (eulerangles (val-precRot) 0 0) as quat --- creo una funzione di rotazione

eulerangles (rotazione 3d nello spazio usando gli angoli in gradi per ogni asse) mentre l'asse X viene controllato dal valore dello Spinner - il valore precedente stabilita della variabile globale che controlla il valore dello spinner.

for obj in selection do rotate obj currentRot -- per ogni oggetto selezionato applico la rotazione

precRot=val -- variabile è il valore dello spinner

)

)

CreateDialog test

----------------------------------------------------------------------------------

Giusto? Perchè usare il modo Quaternario alla rotazione?

Quello che avevo pensato è di usare la matrice di rotazione (Matrix) che in realtà è abbastanza ostico da capire (dato il mio livello) e ho provato anche con i controller ma, inevitabilmente, mi sono perso nei meandri dell'help di MaxScript...

A proposito di matrici, sono quelle che usa il programma per le rotazioni ecc.?

E per essere più precisi....cosa sono in realtà? :unsure:

Ora se si tratta di creare script complessi, ma di una certa semplicità problemi non ne trovo (relativamente) ma quando si prende questa strada...vado a sbattere!! :wallbash:

Ha, dimenticavo.. "+" per te!

Nuovamente grazie Coren

Link al commento
Condividi su altri siti

uso i quaternioni perchè è così che internamente max lavora.

Avevo messo i quaternioni perchè mi ricordavo che il rotate li richiedeva, ma andando a controllare non è così e quindi puoi evitare la conversione.

Comunque ci sono dei casi in cui i quaternioni sono d'obbligo.

Si, internamente per tenere a mente le trasformazioni di ogni oggetto max usa le matrici.

Le matrici con cui max lavora sono matrici 4*3

Ovvero matrici con 4 righe e 3 colonne.

Quindi possono essere viste anche come quattro vettori di tre elementi ciascuno.

Se un oggetto è posizionato all'origine e non è ruotato o scalato la sua matrice di trasformazione è una matrice di identità:

riga1:[1,0,0]

riga2:[0,1,0]

riga3:[0,0,1]

riga4:[0,0,0]

ogni riga rappresenta un asse cartesiano e la quarta riga rappresenta la traslazione dell'oggetto:

riga1 X:[1,0,0]

riga2 Y:[0,1,0]

riga3 Z:[0,0,1]

traslazione :[0,0,0]

Come puoi vedere ogni riga è sia un vettore che un valore di tipo point3 che può rappresentare anche un vettore.

La scalatura è data dalla lunghezza del vettore.

Mentre la rotazione è data dall'orientamento di questo vettore.

esempio di scalatura(scali del triplo lungo l'asse X):

riga1 X:[3,0,0]

riga2 Y:[0,1,0]

riga3 Z:[0,0,1]

traslazione :[0,0,0]

esempio di rotazione (riotazione di 45° sulla Z):

riga1 X:[0.707107 ,0.707107 , 0]

riga2 Y:[-0.707107 ,0.707107 , 0]

riga3 Z:[0,0,1]

traslazione :[0,0,0]

In questo caso ruotando l'oggetto lungo l'asse Z cambia l'orientamento dei suoi assi X e Y locali ed infatti puoi vedere che solo quelle due righe sono cambiate.

esempio di traslazione(100 lungo l'asse Z);

riga1 X:[1,0,0]

riga2 Y:[0,1,0]

riga3 Z:[0,0,1]

traslazione :[0,0,100]

puoi sempre accedere alle varie parti(cioè ai vari tipi di trasformazione) della matrice scrivendo:


theMat=matrix3 1 --creo una matrice identità

theMat.rotationpart ...

theMat.scalepart ...

theMat.translationpart 

La parte della rotazione la ottieni come un quaternione.

Le altre due come point3.

oppure puoi ruotare, scalare e traslare direttamente le tue matrici.

Trovi tutti i comandi nel topic 'Matrix3 Values'

spero di essere riuscito a spiegare bene come funzionano, se hai altre domande son qua.

ciao

Link al commento
Condividi su altri siti

...spero di essere riuscito a spiegare bene come funzionano...

E si! Chiaro e preciso nella spiegazione. Avevo letto nell'help a riguardo delle matrici, ma i tuoi esempi sono stati chirificatori. Ora dovrò applicarmi a riguardo, ma mi sei stato VERAMENTE di aiuto.

Rinnovo i miei ringraziamenti a te Coren, e se ho ancora perplessità, non mancherò a chiederti aiuto! :rolleyes:

Un affettuoso abbraccio MIchele

:hello:

Link al commento
Condividi su altri siti

...e giusto per completare quello che Coren ha scritto puoi fare anche conversioni tra sistemi di coordinate semplicemente moltiplicando una matrice di conversione a tutte le matrice di trasformazione degli oggetti, esempio questa matrice:

ConvMat=

row1:[-1,0,0]

row2:[ 0,0,1]

row3:[ 0,1,0]

row4:[ 0,0,0]

converte un oggetto con un sistema di coordinate diverse cioè con l'X opposto e la Y e Z invertite di posto, basta che ad esempio fai oggetto.transform *= ConvMat

Stessa cosa anche per i punti esempio oggetto.pos *= ConvMat

Se guardi il pivot capirai.

Magari non lo farai mai ma se dovessi incappare in questo problema (e credo che capiti spesso) non ti preoccupare, esistono soluzioni molto semplici

inoltre ci sono operazioni come allineamento a X:

row1:[ 0,0,0]

row2:[ 0,1,0]

row3:[ 0,0,1]

row4:[ 0,0,0]

che schiaccia tutto sull'asse X.

Ci sarebbero anche altre trasformazioni fighissime ma dovrei cercarle su internet che non mi ricordo dove le avevo trovate, forse qua: http://www.flipcode.com/documents/matrfaq.html#Q41

:hello:

Modificato da johnwhile
Link al commento
Condividi su altri siti

Inviata (modificato)

E giusto per completare, un "+" anche per te johnwhile! :Clap03:

Non puoi capire quanto tempo è che cerco di capire questa cosa (sono autoditatta...) e all'improvviso, qui su treddi, ho trovato risposte che non avrei mai immaginato!!!

Grazie per la completezza dell'informazione e la disponibilità ricevuta :)

Ciao Michele

P.S. per oggi ho finito l'azione di votazione, ma come posso ti assegno il mio + :) :)

Modificato da Michele71
Link al commento
Condividi su altri siti

...e giusto per completare quello che Coren ha scritto puoi fare anche conversioni tra sistemi di coordinate semplicemente moltiplicando una matrice di conversione a tutte le matrice di trasformazione degli oggetti, esempio questa matrice:

ConvMat=

row1:[-1,0,0]

row2:[ 0,0,1]

row3:[ 0,1,0]

row4:[ 0,0,0]

converte un oggetto con un sistema di coordinate diverse cioè con l'X opposto e la Y e Z invertite di posto, basta che ad esempio fai oggetto.transform *= ConvMat

Stessa cosa anche per i punti esempio oggetto.pos *= ConvMat

Se guardi il pivot capirai.

Magari non lo farai mai ma se dovessi incappare in questo problema (e credo che capiti spesso) non ti preoccupare, esistono soluzioni molto semplici

inoltre ci sono operazioni come allineamento a X:

row1:[ 0,0,0]

row2:[ 0,1,0]

row3:[ 0,0,1]

row4:[ 0,0,0]

che schiaccia tutto sull'asse X.

Ci sarebbero anche altre trasformazioni fighissime ma dovrei cercarle su internet che non mi ricordo dove le avevo trovate, forse qua: http://www.flipcode.com/documents/matrfaq.html#Q41

:hello:

me e' venuto un dubbio per la conversione.

basta:

tranMat * convMat

o

tranMat * convMat(-1)

cioe' mi spiego meglio non va moltiplicato per l'inversa?

Link al commento
Condividi su altri siti

no, il moltiplicare qualcosa per una matrice dovrebbe fornirti quel qualcosa ma nel sistema di coordinate della matriche per cui lo hai moltiplicato.

l'inversa è per riportarlo da un sistema di coordinate modificato a quello normale.

ciao

Io intendevo dare solo na soluzione sempice quando ad esempio hai dei dati di un oggetto per un sistema di coordinate diverso, questo è il problema delle OpenGL e direct3D che utilizzano un sistema di coordinate diverso

(ZY scambiate e X invertita).

Se ad esempio hai una serie di dati delle faccie e vertici ma in un sistema diverso, tu costruisci in max come se fossero nel sistema di coordinate di max (quindi il risultato sarà un oggetto completamente ruotato, posizionato e riflesso in modo sbagliato) ma se applichi alla matrice di trasformazione dell'oggetto una moltiplicazione con la matrice di conversione ottieni l'oggetto come dovrebbe apparire nella realtà, se moltiplichi invece un la trasformata dell'oggetto fatto in max per l'inversa della matrice di conversione (*=inverse(MatConv)) ottieni invece la conversione opposta.

Purtroppo mi sono reso conto che sarebbe da resettare il pivot dopo la conversione ma Coren mi ha risolto anche questo problema con semplicemente 3 righe di codice :-).

Comunque era solo per aggiungere qualcosina, magari a qualcuno che legge può interessare.

Link al commento
Condividi su altri siti

@johnwhile

non mi riferivo a te, ma a oneman.

Che ipotizzava per la conversione di sistema di coordinate di dover moltiplicare per l'inversa.

Sono d'accordissimo con quello che hai scritto tu, inoltre il link che hai postato è veramente interessante!!

ciao

Link al commento
Condividi su altri siti

... e ancora, io per convertire invece una matrice di rotazione in una matrice di rotazione equivalente ma in un sistema di coordinate diverso ho letto nel reference che max fà questa cosa:

newTransform = inverse(MatConv) * oldTransform * MatConv

non chiedetemi il perchè ma vi assicuro che in realtà è matematicamente corretto e gia testato in un gioco.

Link al commento
Condividi su altri siti

In effetti mi son confuso, la moltiplicazione è quando devi applicare la matrice ad una matrice o un vettore...

Anche perchè non mi ero posto mai il problema del calcolo a mano dato che usavo sempre xformmat.

comunque sono andato a vedere nell'help e il calcolo in realtà è:

newTransform = MatConv * oldTransform * inverse(MatConv)

ciao

Link al commento
Condividi su altri siti

Accedi per commentare

Sarai in grado di lasciare un commento dopo l'accesso



Accedi ora
  • Navigazione recente   0 utenti

    Non ci sono utenti registrati da visualizzare in questa pagina.

×
×
  • Crea nuovo...