Parliamo di 3D

Qui si parla di sprites, backgrounds, effetti speciali, programmi di disegno, ecc.
Avatar utente
Sla
GMI VIP
Messaggi: 3618
Iscritto il: 21/07/2008, 10:11
Specialità: Titanismo
Località: (gm) Italia
Contatta:

Parliamo di 3D

Messaggio da Sla »

Passando il tempo su GMI, leggendo le domande e i topic in generale, mi sono reso conto che l'argomento che va per la maggiore è il 3D. La grafica 3D sembra proprio una destinazione finale, il motivo per cui si cerca di imparare velocemente il 2D visto che spesso viene consigliato di prendere la mano con quello prima di incrementare il numero delle dimensioni. Eppure, spesso e volentieri non si sa come e perché, si ignora totalmente il meraviglioso processo matematico che il rendering in real time cela ai nostri occhi, e non può essere altro che così vista anche la generale carenza di conoscenze matematiche qui sul forum. Non voglio incolpare nessuno, se non è un interesse non è colpa vostra, e anche se lo fosse quasi sempre siete troppo giovani per pretendere che l'istruzione pubblica vi abbia dato ciò che serve, e di certo non cercate di procurarvelo da soli. Le cause? Forse pigrizia, forse la penuria di informazioni in lingua non vi consola, anche se l'inglese sarebbe da conoscere a prescindere.
Non importa. Il mio intento adesso è di fornirvi quell'infarinatura generale di concetti matematici (tra i quali elementi di algebra lineare e trigonometria) che servono per entrare un po' nel dettaglio nella spiegazione del funzionamento di un motore di rendering 3D.
Ho visto che diversi si sono cimentati nella programmazione di un sistema di fake 3d (3d via software invece che hardware, come sarebbe giusto), ma nessuno si è mai preoccupato troppo di fare qualcosa di valido.
Il mio obiettivo è di creare passo-passo un engine di rendering via software, magari sia game maker che in C++, giusto per apprezzare la differenza tra due linguaggi di diverso livello di astrazione nel modello delle virtual machine.
Conto di farlo in più "episodi", non penso di riuscire a scrivere tutto oggi.
Non aspettatevi un rendering in real time, immaginatevi piuttosto qualcosa come potrebbe essere il rendering prodotto dal vostro programma di modeling preferito, lento ma completo. Si tratta solo di un esempio per illustrare le vere tecniche per renderizzare grafica 3D, senza supporto gpu non andrà mai tanto veloce.
Propedeuticità per la guida: nessuna. Quanto scrivo vuole anche essere un buon riferimento matematico per il forum.
Non darò niente per scontato: ogni volta che mi servirà qualche nozione importante la spiegherò in spoiler, in modo da permettere a quelli che già sanno di saltarlo. Naturalmente non mi considero un essere superiore, i più esperti sono caldamente invitati a leggere comunque tutto e a controllare per bene che non abbia lasciato qua e la qualche errore.


EDIT: Lascio l'introduzione precedente per correttezza, ma nel corso della realizzazione di questa guida ho dovuto ridimensionare
il mio obiettivo. Non posso assolutamente lavorare con GM, è troppo, troppo lento. Ero preparato ad affrontare un problema del genere, ma non pensavo fosse così grave. Impiegare dei minuti per vedere qualcosa allunga troppo anche i tempi di debugging, oltre ogni limite imposto dalla mia pazienza.
Lavorerò pertanto solo con qualche linguaggio di più basso livello come il C++. Questo significa che oltre a un piccolo exe dimostrativo, in questo tutorial non vedrete codice, visto che non tutti potrebbero comprenderlo.

Utilizzerò diverse volte l'espressione di sommatoria, pertanto se non sapete cos'è cominciate espandendo lo spoiler.
Spoiler
Una sommatoria è un po' come un for in game maker.
Prendiamo tre numeri interi i,n,m tali che n <= m. In questo paragone, i è la variabile che fa da indice del for.
Scrivere
Immagine
è un po' come scrivere

Codice: Seleziona tutto

risultato = 0;
for(i=n;i<=m;i+=1)
    risultato += f(i);
In altre parole quella sommatoria si espande in una somma dei (m-n)+1 valori:
f(n) + f(n+1) + f(n+2) + ... + f(m-1) + f(m).
Notate come la i in f(i) nell'immagine venga sostituita ogni volta con il suo valore attuale, che viene incrementato dopo ogni espressione.
È praticamente sicuro che prima o poi salterà fuori nella guida qualche riferimento a funzioni trigonometriche quali seno e coseno, pertanto togliamoci adesso il dente e vediamo subito di cosa si tratta.
:cursor: Nello spoiler seguente:
- definizione di funzione reale per valori reali, di Dominio e Codominio
- cenni di notazione insiemistica
- gli angoli e i radianti
- esempio di funzione: degtorad
- la funzione seno
- la funzione coseno
- esempi: lengthdir_x,y,z
Spoiler
Prima di tutto la definizione di funzione. Cercherò di esprimermi in termini più familiari per voi programmatori di gml.
Una funzione matematica ha lo stesso significato logico di uno script nel GML. Immaginatevela come una scatola magica che trasforma univocamente l'input che gli viene dato in un determinato output, secondo alcune regole ben specifiche. In particolare utilizzeremo funzioni ad una sola variabile reale (un solo parametro per input, che generalmente viene chiamato x).
Funzioni di questo tipo si indicano in questo modo:
Immagine
dove f è il nome della funzione. Dopo : viene specificato l'insieme Dominio -> Codominio della funzione. L'insieme Dominio è il raggruppamento di tutti i numeri che la funzione può accettare come input. Se diamo in pasto alla funzione un valore non incluso nel suo dominio in matematica si dice che la funzione non è definita. In programmazione una cosa del genere potrebbe condurre ad un comportamento inaspettato della funzione.
Similmente, il Codominio di una funzione è l'insieme dei valori che la funzione può restituire.
Nel nostro caso sia Dominio che Codominio sono Immagine, a significare che input e output possono essere un qualunque numero reale.
Facciamo subito un esempio per chiarire le idee: definiamo lo script divide(a)

Codice: Seleziona tutto

return(100/argument1);
che divide 100 per l'argomento passato. Il dominio di "divide" non ammette lo 0 perché l'operazione 100/0 è indefinita.
In termini matematici possiamo scrivere:
Immagine
In insiemistica si possono formare insiemi discreti specificando gli elementi che appartengono all'insieme tra parentesi graffe, separati da virgole. l'insieme {0} comprende quindi solo elemento 0.
Immagine / {0} è identico a Immagine - {0}, ovvero togliamo da Immagine l'insieme {0}, per i quali valori la funzione risulta indefinita.
Con questa operazione abbiamo determinato il campo di esistenza della funzione "divide".

È importante sottolineare che le funzioni collegano univocamente un output ad ogni input. Questo significa che per ogni valore di input la funzione restituisce uno ed un solo valore in output.
Pensateci un attimo, se alla domanda "Dimmi quanto fa 100 diviso questo valore qui, 10" seguissero due o più risposte distinte tra loro ci sarebbe qualcosa che non va.

Generalmente ci si riferisce al singolo elemento del Dominio e del Codominio rispettivamente con x e y con questa notazione
y = f(x). Nel nostro esempio, y = divide(x). Potremmmo scrivere una "tabella di verità" della funzione divide di questo tipo:
se x è 4, y = 25 (infatti 100/4 = 25)
x -> y
4 -> 25 (=100/4)
10 -> 10 (=100/10)
2 -> 50
1 -> 100

x è anche chiamata variabile indipendente perché può essere scelta arbitrariamente, mentre y è variabile dipende, perché è conseguenza logica (dipende da..) della scelta fatta per x.

Per le funzioni del tipo
Immagine
possiamo disegnare una rappresentazione grafica sul piano cartesiano in due dimensioni. Tipicamente si assegna l'asse X al Dominio (infatti il singolo elemento è x), e l'asse Y al Codominio.
Il grafico sarà un insieme (infinito, se la funzione è continua) di punti del tipo P(x,y) dove x,y rispettano la tavola di verità scritta prima.
Il grafico di y = 100/x = 1/x * 100 è simile a y = 1/x, perché, come vedremo più avanti, moltiplicare tutto per un numero equivale alla trasformazione per "scaling". Si ingrandisce tutto, ma si mantengono le stesse proporzioni.
Immagine
Una curva di questo tipo viene chiamata iperbole equilatera.

Funzioni trigonometriche
Dovete prima di tutto avere bene in mente il contesto in cui ci muoviamo, ovvero quello di circonferenza goniometrica. Immaginatevi dunque in un piano cartesiano 2D come quello precedente il grafico di una circonferenza che ha per centro l'origine O(0,0) e per raggio la lunghezza 1.
Possiamo subito affermare che tale curva interseca gli assi nei punti (1,0), (0,1), (-1,0) e (0,-1).
Come prima cosa, per lavorare con questa curva ne definiamo la lunghezza.
Immaginate di tagliare la circonferenza e di stenderla sull'asse delle X. Quello che viene fuori è un segmento della lunghezza che convenzionalmente viene considerata come due volte la costante Immagine.
Quindi:
circonferenza unitaria =(è lunga) 2Immagine
semicirconferenza unitaria =(è lunga) Immagine
3/4 di circonferenza unitaria =(è lunga) 3/4 * 2Immagine = 3/2Immagine
Consideriamo adesso un angolo alfa e notiamo che ad ogni angolo possiamo associare univocamente una lunghezza l nella circonferenza unitaria secondo questa regola:
Immagine
Il linguaggio che ho utilizzato dovrebbe ricordarvi la definizione di funzione. Ad ogni angolo espresso in gradi possiamo attribuire univocamente la lunghezza l indicata nel disegno. Ma sì! Anche questa è una funzione, e ce la offre direttamente game maker con degtorad(x), ponendo x = alfa. La lunghezza l si chiama angolo radiante corrispondente all'angolo alfa espresso in gradi.
Proviamo a scrivere una piccola tabella di verità per questa funzione:
x (gradi) -> y (radianti)
0 -> 0
180 -> Immagine
360 -> 2Immagine
Osserviamo che 360 = 2*(180) e che degtorad(360) è ovviamente 2*degtorad(180). Tutto questo può farci
pensare che la relazione di conversione sia lineare. Possiamo quindi rappresentare in un grafico i tre punti della tabella di verità e congiungerli con un segmento, e avremo la nostra funzione.
Immagine
Ed ecco la formulazione matematica con annesso campo d'esistenza.
Immagine
(In realtà degtorad funziona comunque da Immagine in Immagine. Più avanti si capirà come interpretare angoli negativi o più grandi di 2Immagine. Un grazie a BaronVsCorsar per la segnalazione)
Nell'ultima espressione compaiono due intervalli.
Gli intervalli che prenderemo in considerazione saranno sempre intervalli reali, ovvero sottoinsiemi limitati di Immagine. La notazione per scrivere un intervallo è la seguente: [a,b], dove a e b sono rispettivamente il limite inferiore e superiore dell'intervallo. Gli elementi dell'intervallo sono tutti i numeri reali compresi tra a e b.
Possiamo includere/escludere nell'intervallo l'estremo inferiore utilizzando rispettivamente [a,b], ]a,b].
Analogamente per l'estremo superiore: [a,b], [a,b[

Finalmente parliamo di seno e coseno.
Sono entrambe funzioni reali di variabile reale (dello stesso tipo di quelle affrontate fin'ora) che attribuiscono una lunghezza particolare ad ogni angolo. Sempre in riferimento alla circonferenza unitaria, valgono le segueneti regole:
Immagine
Il dominio di entrambe è tutto Immagine. Infatti, un angolo maggiore di 2Immagine può essere scomposto in elementi più semplici.
Immagine
con n = massimo numero intero possibile.
Visto che l'angolo 2Immagine corrisponde all'angolo 0, i valori alfa e beta, pur diversi numericamente, hanno la stessa valenza se considerati come angoli.
Per esempio, a = (13/3)Immagine può essere considerato come (4 + 1/3)Immagine. Scelto n=2, a = 2nImmagine + Immagine/3.
a ha la stessa valenza di Immagine/3
Un angolo negativo si comporta come un angolo positivo:
l'unica differenza è che, per convenzione, invece di crescere a partire dall'asse X in senso antiorario, lo fa in senso orario.


Se fate girare mentalmente l'angolo alfa nel disegno tra 0 e 2Immagine vedrete che seno e coseno oscillano sempre tra 1 e -1, non vanno mai oltre. Ne segue:
Immagine
Per il grafico di seno e coseno vi invito a guardare su internet, non sarei mai in grado di disegnarvelo preciso.

Ora consideriamo questa immagine
Immagine
che rappresenta il problema che ci troviamo davanti quando (succede spesso) dobbiamo utilizzare le funzioni lengthdir_x (che restituirebbe il lato OB) e lengthdir_y (che restituirebbe il lato AB).
Sul triangolo rettangolo di partenza (OAB) sono segnati i parametri che avremmo passato alle funzioni lengthdir_*.
Costruiamo un nuovo triangolo (OCD) simile ad (OAB) ma con ipotenusa (OC) lunga 1. Questo nuovo triangolo (disegnato in bianco) è inscrivibile in una circonferenza di raggio 1 con centro nell'origine del sistema cartesiano. Questo significa che i lati OD e DC equivalgono rispettivamente a cos(alfa) e sin(alfa). Visto che i due triangoli sono simili , le proporzioni tra i lati corrispondenti sono mantenute. length/OC = AB/CD = OB/OD.
Sostituendo con i valori che conosciamo:
length = AB/sin(alfa)
length = OB/cos(alfa)
da cui si ricava:
AB = length*sin(alfa)
OB = length*cos(alfa)

Consideriamo infine un problema che spesso viene affrontato dai programmatori 3D alle prime armi. Sono già uscite diverse domande su lenghtdir_z, ma sostanzialmente questa funzione non può essere simile alle altre due. Il problema di fondo è che per descrivere un punto nel piano bastano due informazioni (nel nostro caso le due coordinate polari lunghezza e "direzione" vengono convertite da lengthdir_x,y nelle corrispondenti cartesiane), mentre nel 3D, tre sono le dimensioni e tre sono le informazioni che servono per determinare un punto nello spazio. Per effettuare la conversione coordinate polari->cartesiane bisognerebbe creare nuove funzioni, diverse da quelle per il piano, che accettino tre argomenti: due angoli e una lunghezza (quelli rappresentati nel disegno seguente)
Immagine
le nuove funzioni lengthdir2_x,y,z ritornano le coordinate del punto P(OB,OA,PH) individuato da alfa,beta e length.
Per quanto riguarda le prime due ce la possiamo cavare con le vecchie lengthdir_x,y considerando l'angolo alfa e la lunghezza OH.
Con un ragionamento analogo all'esempio precedente, ma riadattato al nostro caso,
possiamo calcolare:
OH = length*cos(beta)
PH = length*sin(beta)
In conclusione solo sfruttando anche la terza informazione (beta) siamo in grado di trovare tutto, la domanda su lengthdir_z(length,dir) era insensata, e, per motivi di consistenza, è anche un bene che non esista in game maker.
Passiamo adesso a qualche nozione basilare sui vettori, un argomento fondamentale per la grafica 3D.
:cursor: (1) Lo spoiler seguente contiene:
- definizione e rappresentazione di vettori
- operazioni di somma, prodotto tra vettori
- rappresentazione per combinazione lineare di una base
Spoiler
Un vettore è una collezione più o meno grande di elementi omogenei matematici. Con elementi matematici intendo veramente una qualunque classe di elementi, a patto che per questa siano definiti operatori di somma e moltiplicazione (tra poco vedremo questa particolarità più nello specifico).
Nel corso di questa guida tratteremo soltanto vettori di numeri reali,quindi d'ora in poi quando parlerò di vettori mi riferirò sempre e soltanto a questo tipo di collezione.
I vettori canonici sono formati da tre numeri reali. Ognuno dei tre numeri è anche chiamato "componente" del vettore. Si è soliti riferirsi alle tre componenti dei vettori con il nome x,y,z, oppure, molto più spesso, se il vettore si chiama "v", le tre componenti si chiamano Immagine, Immagine, Immagine.
Fondamentalmente le informazioni (le componenti) di un vettore "codificano" solamente una direzione nello spazio e, in essa, un verso di percorrenza. Questi vettori vengono anche chiamati liberi e sono rappresentati con un trattino inferiore (come una sottolineatura). Quando questi vettori vengono applicati ad un certo punto nello spazio vengono detti appunto vettori applicati. Spesso i vettori liberi vengono applicati all'origine (0,0,0) e, quindi, le tre componenti possono essere considerate come il punto (0+Immagine, 0+Immagine, 0+Immagine) = (Immagine, Immagine, Immagine).
I vettori applicati si rappresentano con la famosa freccina sopra il nome, nel nostro caso Immagine.
Per semplicità userò quest'ultima notazione per riferirmi a qualunque vettore, sia esso applicato o libero.
La figura seguente mostra la rappresentazione grafica di un vettore dalle componenti 4,4 applicato all'origine in un piano cartesiano 2D. Esso può anche essere considerato come il punto P a cui "punta" (perdonate la sprecisione del disegno, ho fatto a mano..)
Immagine

Si definisce modulo di un vettore la sua intensità o lunghezza. Per chiarire le idee, consideriamo un vettore applicato all'origine. Il modulo di questo vettore Immagine è la sua distanza dall'origine. Si scrive:
Immagine , formula che si può ricavare dal teorema di pitagora.
Presi due vettori Immagine e Immagine, per poter essere chiamati tali, e, quindi, essere elementi di Immagine (l'insieme dei vettori con 3 numeri reali), devono soddisfare le seguenti condizioni:

(1.1) ( Immagine + Immagine ) Immagine Immagine Immagine Immagine, Immagine Immagine Immagine
"il vettore risultante dalla somma di due vettori u,v appartiene a V3, per ogni coppia u,v appartenente a V3 scelta"
(1.2) cImmagine Immagine Immagine Immagine Immagine Immagine Immagine, c Immagine Immagine
"il vettore risultante dal prodotto di un vettore u per un numero reale c appartiene a V3 per ogni coppia <vettore v di V3, numero c reale> scelta "
(1.3) ( Immagine x Immagine ) Immagine Immagine Immagine Immagine, Immagine Immagine Immagine
"il vettore risultante dal prodotto vettoriale uxv appartiene a V3, per ogni coppia u,v appartenente a V3 scelta"


La prima espressione mostra la somma tra due vettori, che produce un nuovo vettore che ha per componenti la somma membro a membro dei componenti dei due vettori iniziali.
Immagine
per rappresentare il vettore w è stata usata la notazione per parentesi quadre che racchiude le componenti di w separate dalle virgole.

Nell'espressione (1.2) compare il prodotto tra un vettore ed un numero reale.Questo prodotto restituisce un vettore le cui componenti sono quelle del vettore di partenza, ciascuna moltiplicata per il numero reale.
Immagine
Com'è facile intuire, moltiplicare un vettore per uno scalare (un numero reale) equivale alla nota trasformazione per scaling o stretching. Moltiplicando un vettore per 2 otterremo un vettore orientato allo stesso modo ma lungo il doppio; possiamo dimezzarlo moltiplicandolo per 0.5, e così via.

La terza espressione mostra, infine, il prodotto vettoriale tra due vettori, che restituisce ancora un vettore secondo questa regola: (sia alfa l'angolo compreso tra i due vettori)
(1.4) Immagine
Questa formula introduce un nuovo vettore Immagine.
I vettori scritti in questa notazione sono detti vettori normali e hanno modulo pari a 1.
Questa peculiarità li rende particolarmente comodi, vedremo perché.
In questo caso Immagine è da considerare perpendicolare a entrambi i vettori di partenza u e v. L'espressione a destra di Immagine è chiaramente una quantità scalare.
Si tratta quindi di un'espressione analoga alla (1.2). Essendo il modulo di Immagine pari a 1, il prodotto Immaginea (con a scalare) non farà altro che cambiare il modulo di Immagine in a.
Immagine è dunque semplicemente un manichino, un vettore facilmente modellabile che quindi torna comodo nelle definizioni.

È facile dimostrare che le tre condizioni (1.1),(1.2),(1.3) sono sempre soddisfatte finché si tratta di vettori a numeri reali.

Consideriamo adesso un famoso insieme costituito da tre vettori normali, tutti perpendicolari tra loro:
{ Immagine,Immagine,Immagine }
Immagine = [1,0,0]
Immagine = [0,1,0]
Immagine = [0,0,1]
Questi tre costituiscono una base che genera Immagine. Un insieme di vettori costituisce una base per uno spazio vettoriale (in questo caso Immagine) quando qualunque vettore Immagine di Immagine può essere espresso come un'unica combinazione lineare dei vettori della base
Immagine
Per esempio il vettore Immagine = [4,5,2] si può scrivere come:
4Immagine + 5Immagine + 2Immagine .
Un'altro modo molto usato per scrivere la stessa cosa è:
Immagine

Ancora una cosa: anche se avete letto tutta questa sezione potrebbe essere consigliabile fare un po' di esercizio su carta per prenderci la mano. Inventate qualche vettore e giù di somme/differenze/prodotti per allenare la vostra mente a visualizzare il rapidamente il risultato delle operazioni più comuni. La differenza tra due vettori può essere scritta a partire dalla somma (es: Immagine + (-Immagine ), essendo -Immagine un'espressione del tipo (1.2))

Il prossimo piccolo, grande passo: le matrici.
Lo prometto: da qui in avanti gli argomenti si faranno sempre più interessanti e vicini al 3D.
:cursor: (2) Nello spoiler seguente parleremo di:
- sistemi lineari
- matrice associata ad un sistema
- operazioni tra matrici
- matrice inversa
- compatibilità di un sistema
- determinante di una matrice quadrata di terzo ordine
Spoiler
Sistemi lineari in Immagine

Un sistema di equazioni raccoglie diverse uguaglianze che hanno in comune una stessa n-upla di variabili (insieme di n variabili).
Ogni sistema può avere una,diverse,infinite o nessuna soluzione. Ogni soluzione è una n-upla di variabili che soddisfa contemporaneamente tutte le uguaglianze del sistema. Per quanto richiede la guida possiamo limitarci a trattare sistemi di tre variabili (x,y,z).
Identificheremo con Immagine = [ Immagine , Immagine , Immagine ] Immagine Immagine la soluzione particolare di un sistema a tre variabili reali.
Per esempio, supponiamo di voler traslare il punto P di coordinate ( Immagine , Immagine , Immagine ) in una nuova posizione P'. Sia Immagine il vettore che collega P a P'.
Possiamo servirci del seguente sistema:
Immagine
essendo ( Immagine , Immagine , Immagine ) le nuove coordinate di P (traslato in P').
Si noti che solo le coordinate di P' sono variabili, tutto il resto (le coordinate di P e le componenti del vettore Immagine) sono espressioni costanti.
Potreste storcere il naso all'idea che le coordinate di P' siano variabili. Lo sono fintanto che non le inseriamo dentro quel sistema. È proprio il sistema, infatti, a dire che le ( Immagine , Immagine , Immagine )
devono essere tali da soddisfare contemporaneamente le tre condizioni affinché P' si trovi in (P + Immagine).
In particolare il sistema analizzato ha un'unica soluzione, pertanto le coordinate di P' sono costanti e corrispondono alla soluzione del sistema.

Il sistema analizzato è estremamente semplice: la sua soluzione è immediata.
Prima di passare oltre vorrei fare notare che un sistema a tre variabili, per ammettere un'unica soluzione, deve avere almeno tre equazioni, non di meno. Più avanti analizzeremo più nel dettaglio questo discorso, per adesso limitiamoci a ricordare l'esempio della sezione precedente del lengthdir_z (se non lo avete visto si trova alla fine di trigonometria, il primo spoiler).
Il discorso era simile, per lavorare in 3D servono sempre almeno 3 informazioni, poi se ne vengono date altre ridondanti poco ci importa, sarà più facile trovare la soluzione.
Voglio far notare anche che attraverso questo sistema abbiamo applicato una trasformazione di coordinate per traslazione, il che potrebbe farci pensare (correttamente) di riuscire a tirar fuori dal cilindro anche rotazioni e ridimensionamenti (perdonate la parola, non so come chiamare lo scaling) con sistemi simili. Sono sicuro che cominciate già a sentire il potenziale nascosto di quanto stiamo vedendo, ma mettete le fantasie da parte, andiamo avanti analizzando il caso generico in cui non troviamo soltanto espressioni costanti (sarebbe bello!).

Immagine

un sistema di questo tipo si chiama anche lineare perché le variabili che compaiono sono sempre di primo grado.
Come vedete adesso ogni equazione contiene tutte e tre le variabili (x1,x2,x3 non sono più le coordiante di P ma le variabili del sistema), ciascuna moltiplicata per una costante reale. In ogni uguaglianza a destra dell'uguale c'è ancora una costante reale (ho usato gli indici per non dover inventare troppi nomi). La dove vedete delle lettere che non siano x, quindi, dovete immaginarvi al loro posto semplicemente un numero.
Si può notare che si tratta veramente del caso generale, qualunque sistema compatibile (che ammette una soluzione) in tre variabili può essere espresso a partire da questa bestia attribuendo i giusti valori a ogni costante.
Quello precedente, per esempio, si ottiene con: a1 = 1, b1 = 0, c1 = 0, d1 = x1 + v1 e così via per le altre righe.
Per studiare al meglio questo sistema devo introdurre il concetto di matrice.
Attraverso le matrici potremo studiare esattamente come, quando e quante soluzioni ammette un sistema del genere, e perfino trovare un modo automatico per risolverli, senza doverci ragionare troppo.

Matrici

Rispondo subito alla prima e ovvia domanda: cos'è una matrice?
Osserviamo subito un esempio
Immagine
come vedete, una matrice è semplicemente una griglia di valori reali.
Una matrice può avere un qualunque m >= 1 numero di righe e un qualunque n >= 1 numero di colonne.
Generalmente il nome delle matrici è una lettera maiuscola.
La notazione completa per riferirsi ad una matrice con m righe ed n colonne è Immagine, che nel nostro esempio diventa Immagine. Una matrice con n=m (come A) è detta quadrata.
Un'altra matrice particolare è quella che viene definita vettore colonna, che ha m > 1 righe ed una sola colonna.
Una matrice di questo tipo sostanzialmente non è diversa da un vettore di Immagine.
Per riferirsi allo specifico elemento di A nella i-esima riga e j-esima colonna si scrive Immagine. La matrice precedente può quindi essere riscritta come segue:
Immagine.

Tra le matrici sono definite le operazioni di:
- somma / differenza
- prodotto
Inoltre abbiamo anche l'operazione di:
- prodotto / divisione per uno scalare.

Partiamo dalla terza operazione. Moltiplicare (dividere) una matrice A per un numero k significa moltiplicare (dividere) ogni suo elemento per k... abbastanza intuibile, no?
(2.1) Immagine
Se volessi dividere A per h potrei semplicemente moltiplicarla per 1/h.
La somma tra due matrici, rigorosamente della stessa dimensione, segue la seguente regola:
(2.2) Immagine
La differenza tra due matrici segue dalla somma moltiplicando B per (-1)
(2.3) Immagine

Infine il prodotto tra due matrici, l'operazione che sicuramente ora come ora considererete la più difficile e/o astrusa, ma vi assicuro che se avete pazienza e andate avanti a leggere capirete perché è stato definito così.
Il prodotto tra due matrici viene chiamato prodotto righe per colonne , fondamentalmente perché da luogo ad una nuova matrice le cui componenti sono una somma di prodotto tra gli elementi di una riga di una matrice e di una colonna dell'altra.
Vale la seguente regola:
(2.4) Immagine
Posso spenderci qualche parola, ma comunque la cosa migliore è che proviate a inventare due matrici e a calcolarne la matrice prodotto per allenarvi a capire il meccanismo.
In pratica l'elemento i-j esimo di C si ottiene sommando i contributi di coppie di numeri moltiplicati tra loro.
Le coppie si scelgono muovendosi lungo la i-esima riga della matrice A (da sinistra verso destra) e lungo la j-esima colonna di B (dall'alto verso il basso). Questa definizione implica che non tutte le matrici possono essere moltiplicate tra loro, e che il prodotto tra due matrici cambia a seconda dell'ordine (A*B != B*A).
In particolare, affinché non restino valori scoppiati nella sommatoria precedente, è necessario che il numero di colonne di A (matrice a sinistra del prodotto) sia uguale al numero di righe di B (matrice a destra).
Consideriamo A(2,3) e B(3,1). Notiamo che il prodotto A*B è definito (si noti che B è una matrice "vettore colonna"),
e non solo B*A potrebbe essere diverso, ma in questo caso è addirittura indefinito, in quanto B ha 1 colonna mentre A ha 2 righe.
Non posso davvero rendervi le cose più semplici, è necessario che fate pratica voi.
Forza, prendete carta e matita e calcolatevi ogni singolo elemento di una matrice prodotto tra due matrici quadrate di terzo grado. Se non ci prendete la mano non possiamo andare avanti.

Riprendiamo in mano il sistema lineare precedente e costruiamone la matrice associata
Immagine
Immagine
Come vedete le componenti della matrice associata A sono ordinatamente i coefficienti delle variabili del sistema lineare.
Costruiamo il vettore colonna D
Immagine.
Chiamiamo X il vettore colonna che ha ordinatamente come componenti x1,x2,x3 (le variabili del sistema).
Adesso vi chiedo di espandere su carta, per esercizio, l'espressione matriciale
Immagine
Per espandere intendo scrivere tutte le matrici in nella forma che mostra tutte le loro componenti. Ovviamente prima dovete calcolare la matrice risultate da A*X.
Fate un favore a voi stessi: impeditevi di leggere oltre finché non avete finito l'esercizio.



Se è andato tutto bene dovreste aver capito che
Immagine è un'altro modo di scrivere lo stesso sistema, ma molto più sintetico.
Se dovessimo imparare a maneggiare espressioni matriciali di questo tipo trovare la soluzione (le componenti della matrice vettore colonna X) potrebbe diventare una passeggiata.
Intanto proviamo a comportarci come se fosse un'espressione lineare. La soluzione si troverebbe moltiplicando ambo i membri per Immagine (ricordo che elevare un valore a (-1) equivale a farne il reciproco, Immagine) . Otterremmo X = D/A.
In altre parole se riuscissimo a definire l'operatore di divisione tra matrici avremmo fatto il nostro lavoro.
Piccola nota: d'ora in poi considereremo matrici quadrate di ordine 3, che sono le più comuni per questi calcoli.
Introduciamo allora la matrice Identità, chiamata spesso I (Identity Matrix).
Questa è una matrice quadrata che ha tutti gli elementi della diagonale principale pari a 1, gli altri sono 0.
Immagine
Inventate una qualunque matrice A3,3 e noterete che IA = AI = A.
Dimostriamolo:
Immagine
notiamo che tutte le espressioni in cui si espande la sommatoria sono 0 eccetto quella in cui Immagine = 1, ovvero nell'unico caso in cui k=i.
La sommatoria si traduce quindi in:
Immagine
concludiamo che B = A.

Potremmo considerare la matrice Identità in analogia con il numero reale 1 per le equazioni lineari:
1*a = a*1 = a;

Chiamiamo ora Immagine quella matrice che moltiplicata per A restituisce I.
Immagine
Vorrei specificare bene che Immagine non è elevazione di A a (-1), è pura notazione, esattamente come Immagine non è Immagine ma la funzione inversa di f. Di fatto non esiste l'operazione di dividere qualcosa per una matrice, però per le sue caratteristiche possiamo immaginare (per capire meglio) che Immagine sia 1/A
(1/A * A farebbe, infatti, 1, che come ho detto prima può essere associato alla matrice identità I, ma di fatto 1 != I).
Osserviamo che per come la ho definita, Immagine deve avere dimensione 3,3. Infatti, essendo definiti entrambi i prodotti destro e sinistro di Immagine con A, Immagine deve avere lo stesso numero di colonne e di righe di A.
Sempre in analogia con i numeri reali possiamo notare che:
Immagine
infatti a^(-1) = 1/a.
Moltiplicare una matrice per Immagine non significa proprio "dividerla" per A , ma è la cosa più vicina alla divisione che siamo riusciti a fare.

Riconsideriamo il sistema lineare precedente,
Immagine
Moltiplicando sia a sinistra che a destra dell'uguale per una stessa matrice, l'uguaglianza rimane intatta:
Immagine
Si noti che l'ordine dei prodotto nella prima espressione è stato mantenuto: Immagine è stata posizionata a sinistra di entrambe le parti.

L'ultima espressione mostra che per risolvere un sistema è sufficiente invertirne la matrice associata.
Trovare le componenti della matrice Immagine è un lavoro lungo e faticoso, adatto più ad un processore che all'uomo per la sua mole computazionale, ma una volta fatto consente di risolvere velocemente sistemi anche molto complessi e per questo è diventato il metodo più utilizzato per portare a termine le trasformazioni nei vertici in 3D.
Immagine è chiamata matrice inversa di A.

Cominciamo dicendo che non tutte le matrici sono invertibili, ovvero non tutte le matrici A ammettono Immagine tale che:
Immagine
Per esempio, se il sistema Immagine cui la matrice A è associata fosse incompatibile, dovremmo pensare a
ImmagineD come una matrice indefinita.
Visto che D è un vettore colonna costante, è proprio Immagine ad essere indefinita: si tratta di un caso in cui A non ammette inversa. Viceversa, se A ammette inversa, necessariamente ImmagineD è soluzione del sistema Immagine.
Possiamo dire con certezza, quindi, che un sistema è compatibile se la sua matrice associata A ammette inversa.

Come ho già detto, invertire una matrice è un processo lungo e faticoso, e tale è anche la sua spiegazione.
A meno che non siate voi a chiedermi di farla, in questa sede non vi spiegherò come si invertono le matrici.
Tuttavia capisco che il discorso della compatibilità e delle dimensioni di un sistema possa comunque essere interessante, perciò possiamo focalizzarci su quello.

Consideriamo dunque , sempre in riferimento al sistema Immagine, la matrice
Immagine
Essendo tale matrice uguale a D vale, per ogni riga i, la seguente uguaglianza:
Immagine
Un sistema compatibile ammette la soluzione particolare [x1,x2,x3] che soddisfa le tre espressioni ottenute al variare di i da quella precedente.
Riscriviamo il sistema in una nuova forma
Immagine
Potete verificare che si tratta della stessa cosa facendo uso delle proprietà 2.1 e 2.2 delle matrici (prodotto per numero reale e somma).
In questa forma però alcuni vettori chiave (che chiameremo A', B' ,C', e D' con ovvio significato dei nomi) sono stati isolati, inoltre appare chiaro che D' non è altro che una combinazione lineare dei vettori A' , B' , C'.
Una combinazione lineare di tre vettori restituisce un nuovo vettore che, in parole povere, "eredita" un tot dal primo, un tot dal secondo e un tot dal terzo.
Per spiegarmi meglio faccio un esempio. In precedenza abbiamo visto che un vettore può essere rappresentato come combinazione lineare dei vettori di una base
in Immagine
Immagine si ottiene prendendo Immagine volte Immagine, Immagine volte Immagine e Immagine volte Immagine.
In questo caso D' si ottiene prendendo x1 volte A', x2 volte B' e x3 volte C'.

Adesso, visto che D' potrebbe rappresentare un qualunque punto nello spazio, condizione sufficiente affinché un sistema sia compatibile è che i vettori colonna della sua matrice associata (ovvero A', B', C') non siano complanari.
Se lo fossero, infatti, non c'è santo che tenga: qualunque combinazione lineare di tre vettori complanari non potrà fare altro che originare un vettore che porta ad un punto ancora sullo stesso piano a cui appartengono i primi. Questo significa che se D' non appartiene anch'esso allo stesso piano, non esistono tre valori x1,x2,x3 che risolvano il sistema.

Ci resta ancora un problema, come verifichiamo che i vettori non siano complanari?
La risposta è semplice. Proviamo a costruire un parallelepipedo con i tre vettori che ci interessano, come quello in figura (ringrazio Wikipedia)
Immagine
Si può dimostrare che il volume di questo solido equivale a fare il prodotto misto tra i tre vettori, indifferentemente dall'ordine con cui li moltiplichiamo, purché si tenga presente che il prodotto vettoriale è definito solo tra due matrici (non potete svolgere prima quello scalare, che restituisce un numero).
Immagine
Quando il volume di questo solido è 0 significa che i vettori sono complanari.

Ad ogni matrice quadrata di terzo ordine possiamo attribuire un valore numerico che corrisponde al prodotto misto calcolato tra i suoi tre vettori colonna. Questo numero si chiama determinante della matrice considerata.
Se il determinante della matrice A associata ad un sistema è nullo, il sistema risulta incompatibile.
Peraltro per calcolare la matrice inversa Immagine, tra le altre operazioni, la matrice A viene divisa per il suo determinante, e sappiamo che dividere per 0 è indefinito.


[/color]
Ultima modifica di Sla il 14/09/2013, 16:16, modificato 79 volte in totale.
eppure mi sembra tutto giusto...

Avatar utente
Xxshark888xX
Membro d'elite
Messaggi: 1497
Iscritto il: 30/05/2012, 19:17
Specialità: Un poco di tutto
Uso: GM:Studio 1.4 Pro
Località: Earth
Contatta:

Re: Tecniche 3D - la realtà

Messaggio da Xxshark888xX »

Sla ha scritto:Passando il tempo su GMI, leggendo le domande e i topic in generale, mi sono reso conto che l'argomento che va per la maggiore è il 3D. La grafica 3D sembra proprio una destinazione finale, il motivo per cui si cerca di imparare velocemente il 2D visto che spesso viene consigliato di prendere la mano con quello prima di incrementare il numero delle dimensioni. Eppure, spesso e volentieri non si sa come e perché, si ignora totalmente il meraviglioso processo matematico che il rendering in real time cela ai nostri occhi, e non può essere altro che così vista anche la generale carenza di conoscenze matematiche qui sul forum. Non voglio incolpare nessuno, se non è un interesse non è colpa vostra, e anche se lo fosse quasi sempre siete troppo giovani per pretendere che l'istruzione pubblica vi abbia dato ciò che serve, e di certo non cercate di procurarvelo da soli. Le cause? Forse pigrizia, forse la penuria di informazioni in lingua non vi consola, anche se l'inglese sarebbe da conoscere a prescindere.
Non importa. Il mio intento adesso è di fornirvi quell'infarinatura generale di concetti matematici (tra i quali elementi di algebra lineare e trigonometria) che servono per entrare un po' nel dettaglio nella spiegazione del funzionamento di un motore di rendering 3D.
Ho visto che diversi si sono cimentati nella programmazione di un sistema di fake 3d (3d via software invece che hardware, come sarebbe giusto), ma nessuno si è mai preoccupato troppo di fare qualcosa di valido.
Il mio obiettivo è di creare passo-passo un engine di rendering via software, magari sia game maker che in C++, giusto per apprezzare la differenza tra due linguaggi di diverso livello di astrazione nel modello delle virtual machine.
Conto di farlo in più "episodi", non penso di riuscire a scrivere tutto oggi.
Non aspettatevi un rendering in real time, immaginatevi piuttosto qualcosa come potrebbe essere il rendering prodotto dal vostro programma di modeling preferito, lento ma completo. Si tratta solo di un esempio per illustrare le vere tecniche per renderizzare grafica 3D, senza supporto gpu non andrà mai tanto veloce.
Propedeuticità per la guida: nessuna. Quanto scrivo vuole anche essere un buon riferimento matematico per il forum.
Non darò niente per scontato: ogni volta che mi servirà qualche nozione importante la spiegherò in spoiler, in modo da permettere a quelli che già sanno di saltarlo. Naturalmente non mi considero un essere superiore, i più esperti sono caldamente invitati a leggere comunque tutto e a controllare per bene che non abbia lasciato qua e la qualche errore.

Cominciamo con qualche nozione basilare che ci tornerà utile: cos'è un vettore e il prodotto scalare e vettoriale tra due vettori.
Spoiler
Un vettore è una collezione più o meno grande di elementi omogenei matematici. Con elementi matematici intendo veramente una qualunque classe di elementi, a patto che per questa siano definiti operatori di somma e moltiplicazione (tra poco vedremo questa particolarità più nello specifico).
Nel corso di questa guida tratteremo soltanto vettori di numeri reali,quindi d'ora in poi quando parlerò di vettori mi riferirò sempre e soltanto a questo tipo di collezione.
I vettori canonici sono formati da tre numeri reali. Ognuno dei tre numeri è anche chiamato "componente" del vettore. Si è soliti riferirsi alle tre componenti dei vettori con il nome x,y,z, oppure, molto più spesso, se il vettore si chiama "v", le tre componenti si chiamano Immagine, Immagine, Immagine.
Fondamentalmente le informazioni (le componenti) di un vettore "codificano" solamente una direzione nello spazio e, in essa, un verso di percorrenza. Questi vettori vengono anche chiamati liberi e sono rappresentati con un trattino inferiore (come una sottolineatura). Quando questi vettori vengono applicati ad un certo punto nello spazio vengono detti appunto vettori applicati. Spesso i vettori liberi vengono applicati all'origine (0,0,0) e, quindi, le tre componenti possono essere considerate come il punto (0+Immagine, 0+Immagine, 0+Immagine) = (Immagine, Immagine, Immagine).
I vettori applicati si rappresentano con la famosa freccina sopra il nome, nel nostro caso Immagine.
Per semplicità userò quest'ultima notazione per riferirmi a qualunque vettore, sia esso applicato o libero.
La figura seguente mostra la rappresentazione grafica di un vettore dalle componenti 4,4 applicato all'origine in un piano cartesiano 2D. Esso può anche essere considerato come il punto P a cui "punta" (perdonate la sprecisione del disegno, ho fatto a mano..)
Immagine

Si definisce modulo di un vettore la sua intensità o lunghezza. Per chiarire le idee, consideriamo un vettore applicato all'origine. Il modulo di questo vettore Immagine è la sua distanza dall'origine. Si scrive:
Immagine , formula che si può ricavare dal teorema di pitagora.
Presi due vettori Immagine e Immagine, per poter essere chiamati tali, e, quindi, essere elementi di Immagine (l'insieme dei vettori con 3 numeri reali), devono soddisfare le seguenti condizioni:

(1.1) ( Immagine + Immagine ) Immagine Immagine Immagine Immagine, Immagine Immagine Immagine
"il vettore risultante dalla somma di due vettori u,v appartiene a V3, per ogni coppia u,v appartenente a V3 scelta"
(1.2) cImmagine Immagine Immagine Immagine Immagine Immagine Immagine, c Immagine Immagine
"il vettore risultante dal prodotto di un vettore u per un numero reale c appartiene a V3 per ogni coppia <vettore v di V3, numero c reale> scelta "
(1.3) ( Immagine x Immagine ) Immagine Immagine Immagine Immagine, Immagine Immagine Immagine
"il vettore risultante dal prodotto vettoriale uxv appartiene a V3, per ogni coppia u,v appartenente a V3 scelta"


La prima espressione mostra la somma tra due vettori, che produce un nuovo vettore che ha per componenti la somma membro a membro dei componenti dei due vettori iniziali.
Immagine
per rappresentare il vettore w è stata usata la notazione per parentesi quadre che racchiude le componenti di w separate dalle virgole.

La seconda espressione compare il prodotto tra un vettore ed un numero reale.Questo prodotto restituisce un vettore le cui componenti sono quelle del vettore di partenza, ciascuna moltiplicata per il numero reale.
Immagine
Com'è facile intuire, moltiplicare un vettore per uno scalare (un numero reale) equivale alla nota trasformazione per scaling o stretching. Moltiplicando un vettore per 2 otterremo un vettore orientato allo stesso modo ma lungo il doppio; possiamo dimezzarlo moltiplicandolo per 0.5, e così via.

La terza espressione mostra, infine, il prodotto vettoriale tra due vettori, che restituisce ancora un vettore secondo questa regola: (sia alfa l'angolo compreso tra i due vettori)
(1.3) Immagine
Questa formula introduce un nuovo vettore Immagine.
I vettori scritti in questa notazione sono detti vettori normali e hanno modulo pari a 1.
Questa peculiarità li rende particolarmente comodi, vedremo perché.
In questo caso Immagine è da considerare perpendicolare a entrambi i vettori di partenza u e v. L'espressione a destra di Immagine è chiaramente una quantità scalare.
Si tratta quindi di un'espressione analoga alla (1.2). Essendo il modulo di Immagine pari a 1, il prodotto Immaginea (con a scalare) non farà altro che cambiare il modulo di Immagine in a.
Immagine è dunque semplicemente un manichino, un vettore facilmente modellabile che quindi torna comodo nelle definizioni.

È facile dimostrare che le tre condizioni sono sempre soddisfatte finché si tratta di vettori a numeri reali.



- sono già stanco di scrivere :lol: . magari sul piu tardi inserisco prima dei vettori qualche nozione di trigonometria, dato che serve già per il prodotto scalare e vettoriale, e completo per bene la sezione sui vettori. Domani potrei già iniziare a parlare delle matrici.
Tu sei pazzo :lol:
Contatti
Steam
Facebook

Gif
Spoiler
Immagine
Immagine
Immagine
Immagine

Avatar utente
Sla
GMI VIP
Messaggi: 3618
Iscritto il: 21/07/2008, 10:11
Specialità: Titanismo
Località: (gm) Italia
Contatta:

Re: Tecniche 3D - la realtà

Messaggio da Sla »

Parliamo adesso di trasformazioni nello spazio, ovvero le operazioni che capitano più spesso nella grafica 3D.
:cursor: Nello spoiler:
- introduzione e applicazione di matrici
- ridimensionamenti
- rotazioni
- traslazioni
- trasformazioni consecutive
Spoiler
Dato un punto nello spazio espresso come vettore colonna
Immagine
, il nostro scopo è quello di costruire una matrice che applicata al punto P trasformi le sue coordinate secondo regole specifiche di traslazione (translation), ridimensionamento (scale) o rotazione attorno all'origine (rotation).
Applicare una matrice T ad un punto P significa calcolare il prodotto TP, per questo il punto P deve essere anch'esso una matrice.
Una matrice T con le proprietà discusse si chiama matrice di trasformazione (transformation matrix).
Quello che ci apprestiamo a fare è una ricerca euristica delle proprietà che deve avere una matrice siffatta.
Per quanto riguarda rotazioni e ridimensionamenti possiamo limitarci a considerare matrici 3x3, ma per annoverare anche le traslazioni saremo costretti ad aggiungere una dimensione (4x4), in seguito vedremo perché.

Scaling
Cominciamo a pensare a come potrebbe essere una matrice di ridimensionamento.
Supponiamo di avere una serie di vertici del tipo di P dell'immagine precedente riferiti ad un origine di un sistema cartesiano 3D. Vogliamo applicare ad ogni vertice un fattore di ridimensionamento che li renda più vicini o più lontani dall'origine, ma che non cambi la loro angolazione riespetto a quest'ultima. In pratica vogliamo solo cambiare il modulo del vettore associato ad ogni vertice. Abbiamo già visto che questo tipo di operazione si ottiene moltiplicando ogni componente del singolo vertice P per il fattore k.
Per questo tipo di operazione andrebbe benissimo anche kImmagine , senza bisogno di fare ricorso alle matrici.
Notiamo tuttavia che in questo modo possiamo solo compiere ridimensionamenti omogenei.
Se il nostro personaggio fosse troppo grasso e volessimo restringerlo solo lungo l'asse X e Y, un prodotto scalare * vettore non sarebbe più sufficiente, perché ne modificherebbe anche l'altezza (Z), senza il minimo beneficio per i suoi problemi di obesità.
Pensiamo allora a come potrebbe essere definita una matrice S che ridimensiona con un valore arbitrario lungo ogni asse.
Un buon punto di partenza è definire S = I, perché in questo modo IP resta P.
Chiamiamo P' il punto P trasformato da S, P' = SP.
Per le proprietà della matrice identità possiamo scrivere
Immagine
con s1,1 , s2,2 , s3,3 tutti 1, essendo S = I.
Ci accorgiamo però che abbiamo ottenuto quello che volevamo moltiplicando ogni componente del vettore P per un fattore che possiamo assegnare arbitrariamente.
Chiamiamo Sx, Sy, Sz i fattori di ridimensionamento lungo uno specifico asse, la matrice S diventa:
Immagine
e concludiamo che dalla sua applicazione su un punto ne risulta il ridimensionamento del punto.


Rotating
"Ruotare un punto di un angolo alfa" non significa niente. Come al solito servono altre informazioni, in questo caso ci mancano i riferimenti.
Possiamo ricavare qualunque orientamento nello spazio ruotando attorno agli assi cartesiani X,Y,Z.
Definiremo allora tre matrici diverse per:
-> ruotare di angolo alfa attorno a X
-> ruotare di un angolo beta attorno a Y
-> ruotare di un angolo gamma attorno a Z
Nota: questo tipo di rotazioni mantiene intatta la distanza di un punto dall'origine del sistema di riferimento cartesiano in cui si trova.

Consideriamo un punto P in un sistema cartesiano R centrato in O(0,0,0) in tre dimensioni, siano Immagine i versori corrispondenti agli assi {X,Y,Z}.
Consideriamo anche un secondo sistema cartesiano R' centrato nello stesso punto di R, con gli assi sempre perpendicolari tra loro ma orientati in modo diverso da quelli di R, e siano Immagine i versori relativi agli assi di R'.
Possiamo dire che R' è ruotato in maniera indefinita rispetto ad ogni asse di R.
Chiamiamo P' il vettore colonna con le componenti di P rispetto a R'.
Se riferissimo queste nuove componenti al sistema iniziale R invece di R', avremmo ruotato P in senso opposto rispetto all'orientamento di R'.

Vediamo dove ci porta la matematica (attenzione: la sintassi è rigorosa, se vedete un puntino non è un prodotto normale ma un prodotto scalare tra due vettori)
Immagine
Immagine

L'ultima relazione ottenuta si presta molto bene a esprimere un prodotto tra matrici. Infatti, se poniamo:
Immagine
l'ultima espressione diventa
Immagine.
insomma, P' = RP, e abbiamo trovato la nostra matrice di rotazione R, il cui i,k-esimo elemento (i=riga,k=colonna)
Immagine
non è altro che la lunghezza dell'i-esimo versore del nuovo sistema di riferimento rispetto al k-esimo versore del vecchio.
In altre parole la matrice di rotazione R ha come componenti ordinatamente le componenti dei nuovi versori rispetto al riferimento iniziale.

Sappiamo però che con questo tipo di matrice effettuiamo una rotazione in senso opposto rispetto a quello della rotazione degli assi. Se gli assi del nuovo sistema di riferimento sono ruotati di un angolo alfa rispetto a quelli iniziali, la rotazione del punto cui è applicata la matrice è di -alfa.
Notiamo però che fare la rotazione opposta a quella imposta dalla matrice R equivale a invertire R.
Per aggiustare la nostra matrice dovremi quindi invertirla.
Per brevità non voglio dimostrarvelo, ma se si tratta di una matrice di rotazione, l'inversa corrisponde alla trasposta. In una matrice trasposta quelli che sarebbero i vettori riga diventano colonna e viceversa.
Faccio un esempio di rotazione attorno all'asse Z dell'angolo alfa.
Immagine

Translating
Le traslazioni sono un caso eccezionale perché non riusciamo a inserirle nelle matrici 3x3 viste fin'ora senza andare.
Intendiamoci: l'obiettivo è di avere un'unica matrice di trasformazione che applicata una sola volta applichi tutte le trasformazioni che ci abbiamo salvato dentro (in seguito vedremo come fare).
Questo per ottimizzare le prestazioni nella trasformazione di vertici, operazione che viene fatta davvero un numero elevatissimo di volte per ogni renderizzazione di frame.

Con matrici di trasformazione 3x3 non riusciamo a implementare le traslazioni senza intaccare le informazioni di ridimensionamenti e rotazioni, questo per la natura diversa di queste operazioni:
mentre per ruotare o ridimensionare ci servono dei prodotti, per traslare dobbiamo solo sommare ai vertici dei valori nelle direzioni X,Y,Z.
La soluzione è passare a matrici 4x4.

Come al solito, per non far danni, partiamo dalla matrice identità 4x4. È semplice notare che, per le proprietà della matrice identità, la quarta riga e quarta colonna appena aggiunte non producono cambiamenti durante l'applicazione della matrice su un punto. Possiamo estendere le matrici di rotazione e ridimensionamento aggiungendo questa quarta colonna e quarta riga e avremo una matrice di trasformazione che si comporta nello stesso modo di quella ridotta.
Faccio un esempio con la matrice di rotazione attorno all'asse Z calcolata in precedenza:
Immagine

Per compatibilità con il prodotto tra matrici dobbiamo aggiungere un campo anche ai vettori colonna (che prenderà nome di W), che diventano quindi composti da 4 righe e 1 colonna.
Osserviamo che:
Immagine
(potete verificarlo applicando le proprietà del prodotto tra matrici)
Ponento Pw = 1 avremo ottenuto la nostra traslazione del vettore T = {tx,ty,tz}.
Inoltre il punto risultante avrà in automatico di nuovo w = 1.

La matrice di traslazione è dunque:
Immagine

Vorrei farvi notare che possiamo disabilitare le traslazioni in uno specifico vettore colonna 4x1 lasciando W = 0, in questo caso solo rotazioni e ridimensionamenti avranno effetto. Se anche dovessimo traslare tale vettore, il vettore di traslazione diventerebbe {0,0,0}.
Questo può essere utile quando vogliamo tener traccia di una direzione che cambia nello stesso modo in cui vengono trasformate le mesh (i modelli). Un vettore direzione non deve essere traslato, altrimenti si perde l'informazione utile.

Trasformazioni successive
L'ultima cosa che vediamo in questa sezione: come riunire più trasformazioni in una sola così da velocizzare i calcoli?
Consideriamo la matrice di trasformazione T 4x4, a prescindere dal tipo di trasformazione che contiene, vale:
X' = T X, in cui X' è il vettore delle coordinate del punto X trasformato da T.
Supponiamo di voler effettuare una nuova trasformazione T'. Scriveremo ovviamente X'' = T'X'.
Procediamo con X'' = T' ( T X). Per la proprietà associativa del prodotto tra matrici, X'' = (T' T) X.
Possiamo andare avanti con altre trasformazioni:
X''' = (T'' T' T) X. Chiamiamo W (=World, più avanti si capirà il perché di questo nome) la matrice di trasformazione.
Inizialmente, quando ancora nessuna trasformazione è stata applicata, essa sarà la matrice identità I 4x4.
Volendo aggiungere una trasformazione T a W faremo W = TW, che è esattamente il funzionamento di
d3d_transform_add* (rotation_x,y,z, translation, scaling)



Ci avviciniamo sempre di più al disegno dei nostri primi triangoli.
:cursor: In questo paragrafo:
- mesh
- World Matrix
- View Matrix
- Projection Matrix

Spoiler
Nel corso della guida ci troveremo a disegnare dei modelli.
Un modello è semplicemente un insieme di triangoli, generalmente adiacenti, che formano un solido poligonale nello spazio.
Perché proprio triangoli? Si da il caso che qualunque superficie possa essere approssimata utilizzando dei triangoli. Immaginatevi una superficie curva ideale. Sappiamo che se fosse un oggetto reale sarebbe composto da un elevato numero di atomi e avrebbe un certo spessore, io vorrei invece parlare di superfici che hanno uno spessore nullo. Spessore nullo equivale a non esistente nella realtà, per questo dobbiamo parlare di superficie "ideale". Una superficie ideale è composta da infiniti punti e non ha spessore. Renderizzare infiniti punti è ovviamente un'operazione infinitamente lunga. Nella computer grafica dobbiamo comunque rappresentare qualcosa, e lo facciamo a scapito della qualità della rappresentazione. Infatti, invece di considerare infiniti punti, ne considereremo un numero finito N. Una superficie composta da N degli infiniti punti della corrispondente superficie ideale potrebbe essere una buona approssimazione della superficie ideale. Localmente (nei singoli N punti) si tratta di un'approssimazione perfetta per quanto consentito dal mezzo fisico (precisione di un float o double, a seconda del tipo utilizzato), ma se consideriamo tutti i punti che stanno tra i nostri N, questi saranno ottenuti per interpolazione lineare dei punti noti e avranno un certo errore intrinseco, per questo parliamo di un'approssimazione della superficie ideale, tanto migliore quanti più punti utilizziamo (quanto aumentiamo N).
Inoltre, per dare un'approssimazione globale della superficie ideale, dovremo prendere gli N punti omogeneamente lungo tutta la superficie. Non possiamo certo considerare prendere tutti gli N punti da un angolino della superficie da renderizzare, altrimenti sullo schermo comparirà solo quell'angolino.

Per renderizzare gli N punti ci rendiamo velocemente conto del perché sia importante utilizzare i triangoli.
Potremmo disegnare solamente i punti scelti, ma avremmo una pessima rappresentazione della superficie.
Potremmo disegnare le varie linee che congiungono i punti (e quindi prenderli a gruppi di 2), ma di nuovo, la rappresentazione non sarebbe verosimile (vedi wireframe). Il prossimo passo logico è considerare i punti non singolarmente, non a coppie ma a gruppi di tre.
Ogni gruppo verrà rappresentato come un triangolo. Si noti che attraverso i triangoli raggiungiamo il massimo livello di precisione consentito dalla partizione scelta della superficie ideale in N punti. Se aumentassimo il numero di vertici per gruppo dovremmo interpolare qualche informazione e finiremmo per peggiorare la qualità della rappresentazione, mentre abbiamo visto che diminuendo il numero di vertici rispetto a 3, aumenteremmo sicuramente la precisione (se disegnamo punto per punto caspita, tutto quello che è stato disegnato è un'approssimazione perfetta della superficie ideale, visto che ogni punto appartiene a quest'ultima), ma la rappresentazione non sarebbe soddisfacente.

La geometria si esprime in nostro favore: 3 è il numero minimo di punti per avere una superficie, 3 punti formano sempre un triangolo.

È bene, allora, che il nostro engine abbia delle classi per gestire le mesh,e,quindi, rasterizzare triangoli.
È anche imporante che abbiate ben chiaro che d'ora in poi in questa guida, parlando di mesh, si intenderà collezione di facce (triangoli).

Le mesh vengono salvate in memoria in un sistema di riferimento che viene chiamato Model Space. Si tratta di uno spazio tridimensionale riferito
all'origine O(0,0,0) riservato ad ogni singola mesh. Per fare un esempio, la mesh di un cubo centrato all'origine potrebbe avere vertici che vanno da (1,1,1) a (-1,-1,-1).
Quando renderizzate una mesh in una determinata posizione e orientazione nello spazio, il motore grafico (sia che usiate DirectX che OpenGL) prende
le coordinate dal model space e le trasforma. Il risultato di questa trasformazione
sono coordinate che appartengono al World Space, che è lo spazio del "mondo reale" dell'ambientazione del vostro gioco.
Potremmo immaginare che la mesh di cubo debba rappresentare un dado nel gioco. Questo verrà lanciato e, urtando un tavolino diverse volte, rotolerà
fino a fermarsi su una faccia. Un buon motore fisico ci fornirà ogni istante dei valori di traslazione e rotazione che, se applicati ai vertici del model space, restituiranno nuovi valori appartenenti al mondo reale.
Si noti che le coordinate locali (del model space) di una mesh non vengono alterate dopo ogni trasformazione: quelle coordinate da li non le tocca nessuno, altrimenti non avrebbe senso parlare di spazi locali riservati.
Potremmo anche lavorare senza uno spazio riservato per i vertici del modello, ma così facendo, trasformazione dopo trasformazione, le sue coordinate verrebbero sempre di più "corrotte". Per quanto i dati possano esser precisi c'è quasi sempre un certo margine di approssimazione nei calcoli in virgola mobile, che produrrebbe un errore via via più grande con l'aumentare dei calcoli sui vertici.
Con il metodo del model space invece, a costo della memoria, le coordinate rimangono intatte per tutta la durata del programma.

Un motore di rendering usa una matrice apposita per le trasformazioni viste chiamata World Matrix. La World Matrix può includere una qualunque combinazione di trasformazioni secondo la regola W' = TW già vista (ovvero: se vogliamo combinare una nuova trasformazione T di qualunque tipo {translation,scale,rotation} ad una matice W possiamo moltiplicarla a sinistra per T).
all'inizio W viene settata ad una matrice identità 4x4 (il perché di questa dimensione si è già visto in precedenza), e viene via via modificata.
Per fare un esmepio, d3d_transform_add_rotation_* non fa che costruire una matrice di rotazione e moltiplicarla alla World Matrix corrente.
Il risultato viene salvato in una matrice temporanea e poi copiato nella World Matrix, liberandola dal contenuto precedente.
Le funzioni di tipo d3d_transform_set* si comportano nello stesso modo, solo che prima di applicare la trasformazione alla World Matrix, la rendono
matrice identità 4x4.

Immagine

In quella che viene chiamata rendering pipeline, ogni vertice del model space viene convertito in coordinate schermo (x,y) a seconda:
- della posizione effettiva nel mondo reale (si calcola con la World Matrix)
- della posizione effettiva rispetto alla telecamera (si calcola con la View Matrix, come vedremo)
- delle proprietà della proiezione (fov,aspect,near,far, che metteremo nella Projection Matrix).

Le tre matrici evidenziate sono decisamente utili perché si comportano in modo da fornire velocemente le coordinate a schermo (x,y) partendo dal vertice V nel model space:
V' = World V
V'' = View V'
V''' = Projection V''
dove V''' contiene le (x,y) cercate.
Per renderizzare una mesh passeremo in rassegna tutte le sue facce, una alla volta.
Sappiamo che una faccia è un triangolo, dovremo pertanto analizzare tre vertici alla volta.
Attraverso le WVP convertiremo ogni vertice in coordinate schermo (x,y). In altre parole le WVP ci dicono dove si trova sullo schermo un punto nello spazio guardato dalla telecamera da noi impostata.
Dovremo poi renderizzare il triangolo che unisce le tree coppie di coordinate a schermo (esattamente come farebbe un draw_triangle(x1,y1, x2,y2, x3,y3) ).
Quest'ultima operazione è detta di rasterizing (rasterizzazione).
Visto che un engine 3d deve effettuare dei controlli su ogni pixel disegnato (siano di luce, di z buffering o qualunque altra cosa), non potremo servirci di un banale draw_triangle e dovremo costruirci una nostra funzione per determinare quali punti colorare.

Passiamo ad analizzare la View Matrix.

La matrice View sposta semplicemente i vertici dal world space al View Space. Quest'ultimo è uno spazio in cui l'origine coincide con la posizione della telecamera, ed
è orientato in modo da avvere l'asse Z parallelo al vettore che descrive la direzione in cui è rivolta la telecamera.
Questa trasformazione è molto comoda perché sposta la geometria del mondo in modo da renderla relativa alla telecamera, si può capire quanto ci semplifichi la ricerca delle coordinate a schermo.
Per poter procedere abbiamo bisogno di conoscere esattamente com'è posizionata la telecamera. Ci servono tre vettori:
FROM = [xfrom,yfrom,zfrom], TO = [xto,yto,zto], UP = [xup,yup,zup] (si noti la corrispondenza di argomenti con la funzione di Game Maker per gestire la telecamera)
FROM è il vettore posizionale che indica la locazione della telecamera nello spazio, TO indica invece il punto che la telecamera sta guardando.
Se un vertice si dovesse trovare in quel punto verrebbe disegnato al centro esatto dello schermo.
Conoscendo FROM e TO possiamo determinare un asse (parallelo al vettore TO-FROM) che sarà l'asse Z del sistema di riferimento del View Space.
sappiamo quindi dove si trova la telecamera e dove guarda, ma ancora non sappiamo in che modo lo fa. Infatti, non abbiamo imposto restrizioni sulla rotazione
che la telecamera può avere attorno all'asse prima considerato.
Mi sipego meglio: dovete puntare una telecamera ad un bel gruppetto di turisti giapponesi che vi ha chiesto di scattargli una foto davanti al colosseo, però scattando una foto "in verticale" non riuscite a includerli tutti.
Mantenendo costanti il punto in cui si trova la telecamera e il punto in cui guardate, ruotate allora la telecamera fino ad avere una foto orizzontale, più adatta alla situazione.
Avete portato a termine una rotazione di 90° attorno all'asse Z del View Space. Nel caso della telecamera serve qualche informazione che specifichi in che modo è orientata rispetto a Z.
Questo è esattamente il lavoro del vettore UP, un vettore direzionale che, se applicato nel punto FROM, indica che direzione ha lo zenith della telecamera.
Per chi non lo sapesse, lo zenith è considerato generalmente quell'asse perpendicolare alla Terra che passa per la nostra testa. Guardare in alto significa
guardare verso lo zenith.
A partire da questi tre vettori possiamo determinare una base ortonormale per il View Space:
Z_axis = normalize(TO-FROM)
X_axis = Z x normalize(UP)
Y_axis = Z x X

La view applica le seguenti trasformazioni ai vertici nel World Space:
traslazione di -FROM
rotazione di inversa di R (quindi R^-1), essendo R la matrice di rotazione che porta gli assi a coincidere con quelli dell'orientazione della telecamera.
Con (View * World) * Vertex abbiamo calcolato la posizione di Vertex relativa alla telecamera.

Immagine

Infine la matrice più complicata, la Projection Matrix.
Questa proietta i vertici nel View Space sul piano di proiezione, che corrisponde alla finesta del gioco.
Per fare questo abbiamo bisogno di alcuni parametri circa il tipo di proiezione che faremo.
In questa guida tratterò solo la rappresentazione per proiezione prospettica, quindi quello che ci serve è:
(horizontal) fov, aspect, nearclip, farclip.
Per capire meglio si immagini una piramide infinita, con vertice corrispondente alla posizione della telecamera, e con altezza parallela all'asse Z del View Space.
Ogni vertice posizionato all'interno di questa piramide può essere visto dalla telecamera.
Per descrivere la piramide servono i parametri già evidenziati:
hfov: l'angolo orizzontale di apertura della piramide, segnato nell'immagine come "fov".
aspect: è il ratio (una divisione) di height/width della schermata del rendering (probabilmente coincide con room_height/room_width)
near: è una distanza dalla telecamera. I punti con tale distanza inferiore a near saranno considerati troppo vicini per essere visti e non verranno disegnati.
Per quanto possa sembrare strano senza un near non si potrebbe fare una proiezione prospettica: tutti i punti andrebbero proiettati direttamente sulla telecamera
e non si capirebbe un bel niente!
far: similmente a near, i punti più lontani di far non verranno disegnati perché troppo lontani per essere visti.

Immagine

Il trapezio nero è in realtà quello che si vede sul piano XY della sezione di piramide che rappresenta il frustum di visualizzazione. Dall'origine (posizione della telecamera) parte una piramide che si prolunga all'inifnito di apertura fov.
L'asse di questa piramide coincide con l'asse Z del View Space (disegnato in nero). I valori near e far sono lunghezze misurate sull'asse della piramide
Immaginate un piano perpendicolare a questo asse, passante il punto appartenente all'asse e distante near dall'origine. La porzione di piano delimitata dalle intersezioni con i quattro lati laterali della frustum di visualizzazione viene chiamata Projection Plane, ed è un rettangolo avente come proporzioni l'aspect ratio specificato in precedenza.

Ora si immagini una nuova porzione di piano con le medesime caratteristiche del precedente, però passante per il punto
a distanza far dalla telecamera (e origine del View Space). Questa viene denominata Far Plane.

La frustum di visualizzazione non è altro che una sezione della piramide infinita di partenza, ovvero tutto quello che sta tra il near ed il far plane. Tutti i vertici che cadono dentro questo spazio vengono proiettati sul near plane.
Se prendessimo un nuovo sistema di riferimento con:
-> origine coincidente con il vertice in alto a sinistra del projection plane
-> asse X parallelo al lato più lungo (se esiste, ovvero se aspect ratio != 1) del projection plane
-> asse Y parallelo al lato più corto del projection plane e orientato verso il basso
avremo che le coordinate dell'intersezione del raggio che congiunge il vertice nel frustum di visualizzazione con la telecamera e il projection plane sono proporzionali alle coordinate finali del vertice rappresentato sullo schermo.

In altre parole: prendiamo tutti i vertici della scena, li trasportiamo lungo un percorso retillineo verso la telecamera. Quando questi vertici intercettano il projection plane, li fermiamo.
L'immagine che compare sul projection plane è esattamente l'immagine che volevamo ottenere, dobbiamo solo ridimensionarla in modo da farla combaciare con la finestra di gioco.

La projection matrix si occupa di questo, di ricavare le coordinate dei punti riportati sul projection plane, e come si può desumere dall'immagine si tratta di semplici conversioni lineari. Con un po di trigonometria potremmo arrivare a tradurre una cosa del genere in due trasformazioni per scale e translation.

Ringraziando di nuovo wikipedia, posto un'immagine che dovrebbe spiegare meglio
Immagine
Image courtesy of Wikipedia


Questa immagine mette meglio in evidenza la piramide infinita, il near e far plane, e il solido al loro interno(colorato di verde): il frustum di visualizzazione.
La pallina A è completamente interna al frustum, pertanto verrà disegnata a schermo.
La pallina B, sebbene dentro alla piramide, non si trova all'interno del frustum e non verrà disegnata. Potremmo però aumentare il parametro far e arrivare a includere anche lei.
Per la pallina sigma (arancio) invece, non c'è santo che tenga. La telecamera non è orientata in modo da riuscire a vederla.
Ultima modifica di Sla il 03/04/2013, 17:23, modificato 10 volte in totale.
eppure mi sembra tutto giusto...

Avatar utente
Xxshark888xX
Membro d'elite
Messaggi: 1497
Iscritto il: 30/05/2012, 19:17
Specialità: Un poco di tutto
Uso: GM:Studio 1.4 Pro
Località: Earth
Contatta:

Re: Tecniche 3D - la realtà

Messaggio da Xxshark888xX »

Sla ha scritto:hai ragione, la trigonometria la metto domani, delle matrici parlerò dopodomani.
Da li il passo è veloce fino alle World View Projection
Si, ho capito tutto, si... sisi... :lol: :lol:
Contatti
Steam
Facebook

Gif
Spoiler
Immagine
Immagine
Immagine
Immagine

Avatar utente
Sla
GMI VIP
Messaggi: 3618
Iscritto il: 21/07/2008, 10:11
Specialità: Titanismo
Località: (gm) Italia
Contatta:

Re: Tecniche 3D - la realtà

Messaggio da Sla »

Capirai quando ne parlerò. Se invece ti riferisci a qualcosa nell'op provo a spiegarlo meglio..
eppure mi sembra tutto giusto...

Solid Snake
GMI Advanced
Messaggi: 2093
Iscritto il: 19/12/2010, 16:17
Specialità: Programmazione
Uso: GM:Studio 1.4 Standard
Contatta:

Re: Tecniche 3D - la realtà

Messaggio da Solid Snake »

Parlerai anche di collisioni in 3d?
♥♥♥♥♥♥
Immagine
♥♥♥♥♥♥
Spoiler
Immagine

Avatar utente
Sla
GMI VIP
Messaggi: 3618
Iscritto il: 21/07/2008, 10:11
Specialità: Titanismo
Località: (gm) Italia
Contatta:

Re: Tecniche 3D - la realtà

Messaggio da Sla »

Non credo. Potrei farlo ma sarebbe puramente speculativo, nel senso che non si potrebbe apprezzare il collision checking in tempo reale visto che lato software non riuscirò a produrre nemmeno il rendering in tempo reale.
Il traguardo sarà riuscire a produrre un'immagine più o meno statica, ma di una scena poligonalmente complessa facendo tutto a mano.
Se avrò voglia di portare avanti il tutorial anche dopo questo primo traguardo credo riterrò più opportuno concentrarmi su aspetti grafici come effetti shader e simili.
eppure mi sembra tutto giusto...

Avatar utente
Sla
GMI VIP
Messaggi: 3618
Iscritto il: 21/07/2008, 10:11
Specialità: Titanismo
Località: (gm) Italia
Contatta:

Re: Parliamo di 3D

Messaggio da Sla »

:cursor: Sezione trigonometria completata
eppure mi sembra tutto giusto...

Avatar utente
BaronVsCorsar
GMI VIP
Messaggi: 4699
Iscritto il: 14/02/2004, 12:05
Specialità: Saccenza
Uso: GameMaker 8.1
Località: Ferrara
Contatta:

Re: Parliamo di 3D

Messaggio da BaronVsCorsar »

una piccola precisazione sulla trigonomotria.
a rigore (e se ben ricordo è anche il comportamento in pratica del gml) la funzione degtorad
dovrebbe essere definita da R a R, e non nei due intervalli [0;360[ e [0;2pi[
(ma sicuramente non andrebbe definita con l'estremo superiore incluso nel caso lo si facesse limitatamente al primo periodo)

PS1: se non sbaglio non hai definito la simbologia dell'intervallo.

PS2: come hai realizzato le figure allegate in due colori? una tavoletta grafica?

PS3: sigillo del "baron approved" sul topic. non per mio interesse sul 3d, ma approcciare l'argomento matematicamente è lodevole! (e molto molto oneroso...)
ImmagineSchiva questo - http:\\baronvscorsar.altervista.org
by Lego: Vado in un bar e faccio "votiamo che quel tizio la in fondo venga buttato fuori", ma perché?

Avatar utente
Sla
GMI VIP
Messaggi: 3618
Iscritto il: 21/07/2008, 10:11
Specialità: Titanismo
Località: (gm) Italia
Contatta:

Re: Parliamo di 3D

Messaggio da Sla »

BaronVsCorsar ha scritto:la funzione degtorad
dovrebbe essere definita da R a R, e non nei due intervalli [0;360[ e [0;2pi[
Hai ragione, ma ho preferito lasciare così per consistenza con quanto disegnato prima (segmento e non retta), in modo da non confondere chi ancora deve imparare.
Inoltre non avevo ancora introdotto il concetto di "auto aggiustamento" degli angoli degeneri. Aggiungo comunque una nota a riguardo.
BaronVsCorsar ha scritto:PS1: se non sbaglio non hai definito la simbologia dell'intervallo.
provvedo, grazie per la segnalazione.
BaronVsCorsar ha scritto:PS2: come hai realizzato le figure allegate in due colori? una tavoletta grafica?
Precisamente. Forse un giorno la userò anche per far grafica, come pensavo quando l'ho presa :lol:
eppure mi sembra tutto giusto...

Avatar utente
CaMpIoN
Membro super
Messaggi: 684
Iscritto il: 17/11/2009, 16:20
Specialità: Programmatore
Uso: GM:Studio 1.4 Master
Contatta:

Re: Parliamo di 3D

Messaggio da CaMpIoN »

Ottima idea Sla, in questo modo approfondisco anche un po di cose ;)
Giochi da me creati:
Spoiler
Immagine

Avatar utente
Prometeo
Membro d'elite
Messaggi: 1258
Iscritto il: 15/09/2010, 12:36
Specialità: Grafico Progammatore
Uso: GameMaker 8.1
Località: Italia
Contatta:

Re: Parliamo di 3D

Messaggio da Prometeo »

Sla, ti voglio bene... per gente come me, con un livello di matematica mooooolto imbarazzante, questi tutorial sono manna dal cielo... infinitamente grazie e chapeau :cappa:
Il dolore che i limiti delle cose c'impongono, cioè a dire il mal essere del desiderio non soddisfatto, il senso del non potere tutto, ci dà il sentimento e l'idea del tutto. Il limite diventa indizio. E la più larga via verso l'infinito è il dolore. [Niccolò Tommaseo]

Avatar utente
Sla
GMI VIP
Messaggi: 3618
Iscritto il: 21/07/2008, 10:11
Specialità: Titanismo
Località: (gm) Italia
Contatta:

Re: Parliamo di 3D

Messaggio da Sla »

Grazie per il vostro supporto, mi date la grinta per continuare :D
Pian piano sto portando avanti il lavoro
eppure mi sembra tutto giusto...

Avatar utente
jumoonp
GMI VIP
Messaggi: 3292
Iscritto il: 13/01/2008, 20:59
Contatta:

Re: Parliamo di 3D

Messaggio da jumoonp »

Sla ha scritto:Grazie per il vostro supporto, mi date la grinta per continuare :D
Pian piano sto portando avanti il lavoro
Io ancora non riesco a capire come si fa a calcolare 2 lati di un triangolo scaleno, avendo come dati tutti e tre gli angoli ed un lato....

le formule che conosco vanno bene solo per il triangolo rettangolo... a causa di questo ho quasi rinuciato ad un progettino interessante :cry:
Spoiler
Gabriele Dell'Otto e Lee bermejo

Immagine

Avatar utente
Sla
GMI VIP
Messaggi: 3618
Iscritto il: 21/07/2008, 10:11
Specialità: Titanismo
Località: (gm) Italia
Contatta:

Re: Parliamo di 3D

Messaggio da Sla »

hai letto la sezione trigonometria?
eppure mi sembra tutto giusto...

Avatar utente
jumoonp
GMI VIP
Messaggi: 3292
Iscritto il: 13/01/2008, 20:59
Contatta:

Re: Parliamo di 3D

Messaggio da jumoonp »

Sla ha scritto:hai letto la sezione trigonometria?
Non ci capisco nulla....le mie basi matematiche sono quello che sono :oops:
Spoiler
Gabriele Dell'Otto e Lee bermejo

Immagine

Avatar utente
CaMpIoN
Membro super
Messaggi: 684
Iscritto il: 17/11/2009, 16:20
Specialità: Programmatore
Uso: GM:Studio 1.4 Master
Contatta:

Re: Parliamo di 3D

Messaggio da CaMpIoN »

jumoonp ha scritto:
Sla ha scritto:Grazie per il vostro supporto, mi date la grinta per continuare :D
Pian piano sto portando avanti il lavoro
Io ancora non riesco a capire come si fa a calcolare 2 lati di un triangolo scaleno, avendo come dati tutti e tre gli angoli ed un lato....

le formule che conosco vanno bene solo per il triangolo rettangolo... a causa di questo ho quasi rinuciato ad un progettino interessante :cry:
Ti avevo spiegato come fare sulla tua domanda in D&R, avendo 3 angoli e 1 lato di un triangolo qualsiasi devi usare il teorema dei seni, leggiti la guida sulla trigonometria sopra di Sla magari ti è più chiaro.
Giochi da me creati:
Spoiler
Immagine

Avatar utente
Sla
GMI VIP
Messaggi: 3618
Iscritto il: 21/07/2008, 10:11
Specialità: Titanismo
Località: (gm) Italia
Contatta:

Re: Parliamo di 3D

Messaggio da Sla »

Se davvero non capisci nulla della parte di trigonometria non so come aiutarti, non ci sono grossi prerequisiti.
Prova ad essere più specifico. Potresti quotarmi la parte che non capisci
eppure mi sembra tutto giusto...

Avatar utente
CaMpIoN
Membro super
Messaggi: 684
Iscritto il: 17/11/2009, 16:20
Specialità: Programmatore
Uso: GM:Studio 1.4 Master
Contatta:

Re: Parliamo di 3D

Messaggio da CaMpIoN »

Anche il resto delle operazioni verranno fatte con GM?
Altrimenti diventa un po' complicato ordinare il tutto se sono cose lunghine, comunque ottimo lavoro :)
Giochi da me creati:
Spoiler
Immagine

Avatar utente
Sla
GMI VIP
Messaggi: 3618
Iscritto il: 21/07/2008, 10:11
Specialità: Titanismo
Località: (gm) Italia
Contatta:

Re: Parliamo di 3D

Messaggio da Sla »

Certo, tutto con game maker. In un secondo momento proverò a rifare lo stesso programma ma ottimizzato e parallelizzato in più core in c++.
Vedremo la differenza
eppure mi sembra tutto giusto...

Rispondi

Chi c’è in linea

Visitano il forum: Nessuno e 57 ospiti