|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Feb 2002
Messaggi: 906
|
Collisione terreno
Dunque
Sto facendo un tutorial tutto in italiano (per vc6++ in directx 8 con direct3d) implementando un motore grafico per sviluppare videogame. Per ora il motore a queste funzioni: - Schermate iniziali di presentazione - Musica in background (file mid, wav o mp3) - Effetti sonori (sfx) - 2 oggetti, un terreno e un cubo con le proprie texture e effetto luce sui materiali ecc, ecc.) Ogni oggetto ha una propria telecamera (perlomeno ho capito che ogni oggetto è bene che abbia una propria telecamera. Movimenti nel mondo attraverso i tasti freccia e movimenti nell'ambiente tramite mouse (tipo doom unreal o fifa), per intenderci. ------------------------------------- Ora devo capire come fare gli algoritmi di collisione, ovvero riuscirei a farli, infatti sto studiando geomettria 3d (gli assi x,y e z), ma non sono riuscito a capire le variabili da prendere in considerazione per poter sviluppare l'algoritmo di collisione. Dunque, la domanda è questa: Avete presente un terreno montagnoso?, ebbene con il tastofreccia UP mi avvicino alle montagne, ecco..... dovrei fare in modo di non bucare la montagna, ma scalarla oppure scenderla ma non passarci attraverso dunque ragionando insieme, se al mio terreno tolgo le montagne ovvero lo rendo un piano uniforme, riesco a camminare sul piano, correggetemi se sbaglio, il piano dovrebbe avere coordinate +0 se cammino sopra e -0 se cammino sotto. dalla mia vista che è il vettore Z le montagne si avvicinano allo schermo, il vettore Z diminuisce fino ad andare in negativo per i poligoni che io come osservatore non vedo più in quanto sono dietro lo schermo. bene ha questo punto l'algoritmo deve permettermi di salire (spostare la telecamera della visuale sul terreno e scendere quando il vettore Z è positivo. Se qualcuno sà come normalizzare un vettore oppure come calcolare se si è entrati in collisione con i poligoni (che poi sono triangoli) del terreno....... e mi volesse aiutare........... Buon natale a tutti Cionci sei forte......... N.B Questo tutorial lo rendero di pubblico dominio In quanto ho trovato molte difficolta a reperire materiale e info in italiano su direct3d e directx (anzi in pratica non c'è quasi niente) |
|
|
|
|
|
#2 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Re: Collisione terreno
Quote:
Sinceramente non so come potresti fare...pensa che in OpenGL mi sono fermato circa allo stesso punto... Comuqnue qualcosa ho trovato: http://www.mvps.org/directx/articles...ng_spheres.htm Anche se non risolve il problema del terreno, ma solamente il problema della collisione fra oggetti racchiudibili in una sfera... Ultima modifica di cionci : 21-12-2003 alle 12:13. |
|
|
|
|
|
|
#3 |
|
Bannato
Iscritto dal: May 2000
Messaggi: 5
|
brutto non sapere di calcolo vettoriale !
|
|
|
|
|
|
#4 |
|
Bannato
Iscritto dal: Nov 2001
Città: Verona
Messaggi: 1086
|
Io un'idea ce l'avrei anche (tipo mappa delle altezze)
-crei una bitmap che rappresenti il terreno in 2d, "visto dall'alto" -dall'immagine generi il terreno: ogni pixel può rappresentare un quadrilatero di coordinate P0(x,y,z), P1(x+w, y, z), P2(x+w, y, z+w), P3(x, y, z+w) dove p0.x e p0.z sono le coordinate "origine" del terreno sul piano XZ e il valore di y lo ricavi dall'intensità del colore del pixel. Dalla stessa immagine generi un matrice nxm in cui infili i valori di y usati per generare il terreno. A questo punto per stabilire a che altezza si deve trovare un oggetto in un certo punto della mappa è sufficiente ricavare le coordinate x-z della sua posizione: se dividi x e z per il valore w usato nella costruzione del terreno e arrotondi all'intero inferiore ottieni due indici n,m che rappresentano la "cella" in cui si trova l'oggetto la cui "altezza" è quella contenuta nell'elemento n-m della matrice delle altezze. Non è necessario che la matrice delle altezze abbia la stessa risoluzione della mappa (ad esempio potresti creare un quadrilatero per ogni pixel ai fini della creazione del terreno mentre per la matrice suddividi il pixel in 9 parti), quindi potresti risolvere il problema del "movimento a salti" aumentato il campionamento nella matrice (che è un array di [n][m] float o double). Io una cosa del genere l'avevo provata tempo fa e funzionava ma non so se sia il metodo usato "nella realtà". Ciao. |
|
|
|
|
|
#5 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
|
|
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
|
|
|
|
|
|
#7 | |
|
Bannato
Iscritto dal: May 2000
Messaggi: 5
|
Quote:
comunque anche qualche nozione di aritmetica non guasterebbe per esempio: 5 + 10 = 15 e non 5 + 10 = 21 (ad oggi) adesso che ti hanno fatto moderatore modera anche i moderatori smoderati. |
|
|
|
|
|
|
#8 |
|
Senior Member
Iscritto dal: Feb 2002
Messaggi: 906
|
Okay grazie a tutti
ora metto sul terreno un'altro cubo rendolo indipendente dal terreno e cerco di farlo camminare sul terreno controllando le variabili della sua matrice (telecamera, scrivendole in un file testo) nel momento che buca i poligoni del terreno, riportandolo al piano ........ va bè ci siamo capiti vi faccio sapere: x PGI: ci stai vicino ............. questa è l'email di risposta di un mio amico per darmi delle idee sulla questione (potrebbe essere utile anche a voi): x Cioci: Grazie funambolico spirito libero....... ciao amico mio -------------------- buone feste anche a te. Mi mandi il codice sorgente? Così gli do una occhiata perché questa questione di usare due matrici di proiezione differenti non l'ho capita molto :-), cioè la proiezione serve per trasformare le coordinate dal sistema mondo a quello video e quindi è unica per tutta la scena; poi ci sarà una matrice diversa per ogni oggetto presente. La catena è questa: Locale -> Mondo -> Camera -> Base -> Proiezione Locale -> Mondo: Matrice per le trasformazioni applicate all'oggetto (l'unica che deve cambiare all'interno della scena) Mondo -> Camera: Matrice per trasformare le coordinate nel sistema dell'osservatore (unica per ogni frame) Camera -> Base: Matrice per cambiare la base del sistema di riferimento (non è obbligatoria e serve ad esempio per passare da un sist. destrorso ad uno sinistrorso) Base -> Proiezione: La classica matrice che effettua le proporzioni X/Z e Y/Z (circa) Io sto scrivendo un emulatore software delle DirectX e utilizzo questo metodo che è il più lineare e logico. Per quanto riguarda le collisioni ci sono diversi metodi, se hai a disposizione la mappa del terreno puoi tranquillamente prendere l'altezza dello stesso in corrispondenza dell'oggetto che ti interessa e aggiungergli una costante (se vuoi che segua il terreno), come si faceva per il voxel. A proposito se ti interessa sto scrivendo un tutorials su questo vecchio argomento. Se invece vuoi trovare effettivamente la collisione il metodo più semplice è considerare l'oggetto come incluso in una sfera, conoscendo la posizione del suo baricentro, il raggio e la posizione dei triangoli che compongono il terreno si effettua una intersezione fra un raggio uscente dalla sfera e i triangoli; ovviamente solo sui triangoli più vicini. Trovi molti tutorials sulla collisione e intersezione nel sito www.magic-software.com (spero di non essermi sbagliato), prova a fargli una visita; oppure fai una ricerca con i termini "Realtime collision". Ciao! -------------------- Ultima modifica di okay : 22-12-2003 alle 02:28. |
|
|
|
|
|
#9 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
|
|
|
|
|
|
|
#10 | ||||||
|
Senior Member
Iscritto dal: Oct 2002
Città: San Jose, California
Messaggi: 11794
|
Re: Collisione terreno
Quote:
Oppure stai parlando di matrice, ogni oggetto ha una propria matrice di trasformazione. Quote:
Ad ogni frame tiri un "raggio" che parte dalla posizione dell'oggetto in direzione della sua velocita' e intersechi questo raggio con il terreno per capire se e dove "collidono", come dire che stai cercando di capire se durante il tragitto del corpo durante il frame, questo va a collidere in qualche punto col terreno. I dettagli dell'algoritmo di collisione dipendono fortemente da come rappresenti il terreno. Una soluzione veloce ti e' gia' stata descritta in questo thread e funziona bene. Quote:
Una volta che hai la normale, affinche' l'oggetto non penetri il terreno devi assicurarti che la sua velocita' sia correttamente "tagliata" (si dice "chopped" in inglese ma non saprei come tradurlo bene in italiano Per capirci meglio dovrei disegnare una figura, ma immagina di camminare contro un muro, come eviti di andarci contro? Spostandoti solo parallelamente ad esso, quindi "tagliando via" ogni movimento che va verso il muro. In termini matematici, hai il vettore N (la normale al terreno nel punto di collisione), il vettore V (la velocita' del corpo che deriva dagl'input dell'utente nel tuo caso o dai calcoli di un motore di fisica ad esempio) e ti serve calcolare la nuova velocita' V1 affinche' il corpo si muova parallelamente al muro e non verso il muro. V1 = V - dot(V, N)*N Dove dot(V, N) e' il prodotto scalare fra il vettore velocita' V e la normale N e rappresenta l'angolo fra la velocita' e la normale, in altre parole ti da' una valutazione di quanto il corpo si sta muovendo verso il terreno. Se il corpo si sta muovendo direttamente verso il terreno (a 90 gradi) il prodotto scalare avra' valore massimo, per la precisione pari alla lunghezza del vettore V perche' N ha per definizione lunghezza 1 (essendo una normale). Moltiplicando il prodotto scalare per il vettore N, trovi il vettore che rappresenta esattamente di quanto il corpo si sta muovendo verso il terreno. A questo punto ti basta sottrarlo al vettore velocita' iniziale per trovare la velocita' residua parallela al terreno. Sei cosi' garantito che a seguito di una collisione, il corpo non cerchera' di penetrare il terreno perche' tu stai forzando la sua velocita' ad essere parallela al terreno stesso. Quote:
Quote:
Per normalizzare un vettore devi dividerlo per la sua lunghezza. La lunghezza (o norma) di un vettore V e' definita come: V / dot(V, V) Dove dot() e' il prodotto scalare, che per vettori in 3 dimensioni si calcola cosi': dot(V, U) = Vx * Ux + Vy * Uy + Vz * Uz Quote:
__________________
"We in the game industry are lucky enough to be able to create our visions" @ NVIDIA |
||||||
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Feb 2002
Messaggi: 906
|
okay fek...........
Si scusami intendevo una matrice per oggetto! dunque.............. Da buon programmatore autodidatta (asm, c++, vb, web ecc,ecc.) Ho costruito le mie classi in c++, il mio problema ora è la geometria 3d applicata al pc (si era capito eh......!?!?) ..... ora, quello che mi manca è il refiremento alle variabili per poter fare gli algoritmi di collisione al terreno (per adesso): per es. (le mie classi): Terreno.h struct TERRAIN_CUSTOMVERTEX { FLOAT x, y, z; //Posizione dei vertici FLOAT nx, ny, nz; //Luce FLOAT tu, tv; //Coordinate Texture }; WORD m_wRows; //righe WORD m_wCols; //colonne WORD m_wMaxHeight; //massima altezza terreno float m_rTileSize; //ampiezza rettangoli (poligoni) DWORD m_dwNumOfVertices; //n. vertici DWORD m_dwNumOfIndices; //n. indici DWORD m_dwNumOfPolygons; //n. poligoni Terreno.cpp m_dwNumOfVertices = (m_wCols + 1) * (m_wRows + 1); m_dwNumOfPolygons = m_wRows * m_wCols * 2; m_dwNumOfIndices = m_dwNumOfPolygons * 3; D3DXVECTOR3 CTerrain::GetTriangeNormal(D3DXVECTOR3* vVertex1, D3DXVECTOR3* vVertex2, D3DXVECTOR3* vVertex3) { D3DXVECTOR3 vNormal; D3DXVECTOR3 v1; D3DXVECTOR3 v2; D3DXVec3Subtract(&v1, vVertex2, vVertex1); D3DXVec3Subtract(&v2, vVertex3, vVertex1); D3DXVec3Cross(&vNormal, &v1, &v2); D3DXVec3Normalize(&vNormal, &vNormal); return vNormal; } bool CTerrain::SetSize(WORD wRows, WORD wCols, float rTileSize, WORD wMaxHeight) { //Setto grandezze m_wRows = wRows; m_wCols = wCols; //Setto grandezza quadrati dei poligoni m_rTileSize = rTileSize; //Setto la massima altezza dei vertici m_wMaxHeight = wMaxHeight; //Setto i contatori per il terreno m_dwNumOfVertices = (m_wCols + 1) * (m_wRows + 1); m_dwNumOfPolygons = m_wRows * m_wCols * 2; m_dwNumOfIndices = m_dwNumOfPolygons * 3; AggiornoVertici(); return true; } bool CTerrain::AggiornoVertici() { DWORD i = 0; VOID* pVertices; WORD* pBufferIndices; D3DXVECTOR3 vNormal; DWORD dwVertex1; DWORD dwVertex2; DWORD dwVertex3; WORD* pNumOfSharedPolygons = new WORD[m_dwNumOfVertices]; D3DVECTOR* pSumVertexNormal = new D3DVECTOR[m_dwNumOfVertices]; TERRAIN_CUSTOMVERTEX* pcvVertices = new TERRAIN_CUSTOMVERTEX[m_dwNumOfVertices]; float x, z; //Centro il terreno intorno all'origine float zStart = (float)(0.0 - (m_wRows/2.0)); float zEnd = (float)(m_wRows/2.0); float xStart = (float)(0.0 - (m_wCols/2.0)); float xEnd = (float)(m_wCols/2.0); //Initialise the random number generator srand(timeGetTime()); //Cancello memoria e setto i vertici del terreno for(z = zStart; z <= zEnd; z++) { for(x = xStart; x <= xEnd; x++) { pNumOfSharedPolygons[i] = 0; pSumVertexNormal[i] = D3DXVECTOR3(0,0,0); pcvVertices[i].x = x * m_rTileSize; if((z == zStart) || (z == zEnd) || (x == xStart) || (x == xEnd)) { pcvVertices[i].y = 0.0; } else { //Random altezza per y pcvVertices[i].y = (float)(rand() % m_wMaxHeight); } pcvVertices[i].z = -z * m_rTileSize; pcvVertices[i].nx = 0.0; pcvVertices[i].ny = 0.0; pcvVertices[i].nz = 0.0; if(((int)z % 2) == 0) { if(((int)x % 2) == 0) { pcvVertices[i].tu = 0.0; pcvVertices[i].tv = 0.0; } else { pcvVertices[i].tu = 1.0; pcvVertices[i].tv = 0.0; } } else { if(((int)x % 2) == 0) { pcvVertices[i].tu = 0.0; pcvVertices[i].tv = 1.0; } else { pcvVertices[i].tu = 1.0; pcvVertices[i].tv = 1.0; } } i++; } } m_pIndexBuffer->Lock(0, m_dwNumOfIndices * sizeof(WORD), (BYTE**)&pBufferIndices, D3DLOCK_READONLY); //Aggiungo attraverso la normale nei vertici //quale è la normale????????? for(i = 0; i < m_dwNumOfIndices; i += 3) { dwVertex1 = pBufferIndices[i]; dwVertex2 = pBufferIndices[i + 1]; dwVertex3 = pBufferIndices[i + 2]; vNormal = GetTriangeNormal(&D3DXVECTOR3(pcvVertices[dwVertex1].x, pcvVertices[dwVertex1].y, pcvVertices[dwVertex1].z), &D3DXVECTOR3(pcvVertices[dwVertex2].x, pcvVertices[dwVertex2].y, pcvVertices[dwVertex2].z), &D3DXVECTOR3(pcvVertices[dwVertex3].x, pcvVertices[dwVertex3].y, pcvVertices[dwVertex3].z)); pNumOfSharedPolygons[dwVertex1]++; pNumOfSharedPolygons[dwVertex2]++; pNumOfSharedPolygons[dwVertex3]++; pSumVertexNormal[dwVertex1].x += vNormal.x; pSumVertexNormal[dwVertex1].y += vNormal.y; pSumVertexNormal[dwVertex1].z += vNormal.z; pSumVertexNormal[dwVertex2].x += vNormal.x; pSumVertexNormal[dwVertex2].y += vNormal.y; pSumVertexNormal[dwVertex2].z += vNormal.z; pSumVertexNormal[dwVertex3].x += vNormal.x; pSumVertexNormal[dwVertex3].y += vNormal.y; pSumVertexNormal[dwVertex3].z += vNormal.z; } //Quì calcolo la normale????????? for(i = 0; i < m_dwNumOfVertices; i++) { vNormal.x = pSumVertexNormal[i].x / pNumOfSharedPolygons[i]; vNormal.y = pSumVertexNormal[i].y / pNumOfSharedPolygons[i]; vNormal.z = pSumVertexNormal[i].z / pNumOfSharedPolygons[i]; D3DXVec3Normalize(&vNormal, &vNormal); pcvVertices[i].nx = vNormal.x; pcvVertices[i].ny = vNormal.y; pcvVertices[i].nz = vNormal.z; } Quali altre variabili ho biogno per fare l'algoritmo di collisione al terreno????????????????? Queste sono tutte le variabili che ho ha disposizione........ ne devo mettere altre???????? Come faresti tu???????? Cosa prendere in considerazione per i calcoli di collisione al terrenio??????? N.B. Questa è la chiamata in main.cpp per creare il terreno attraverso il device //TERRENO //creo l'oggetto terreno (device, tile rows, tile cols, tile size, max height) //Questo sotto creo montagne (ma è disabilitata dal commento) //m_pTerrain1 = new CTerrain(g_pDevice, 20, 20, 10.0, 15); //questa sotto creo un piano liscio erboso m_pTerrain1 = new CTerrain(g_pDevice, 100, 100, 1.0, 1); //setto la texture m_pTerrain1->SetTexture("Texture//Grass.bmp"); ciao Ultima modifica di okay : 22-12-2003 alle 14:35. |
|
|
|
|
|
#12 | |
|
Senior Member
Iscritto dal: Oct 2002
Città: San Jose, California
Messaggi: 11794
|
Quote:
__________________
"We in the game industry are lucky enough to be able to create our visions" @ NVIDIA |
|
|
|
|
|
|
#13 | |
|
Member
Iscritto dal: Aug 2003
Messaggi: 125
|
Re: Re: Collisione terreno
Quote:
dot(V, N) rappresenta la "lunghezza" (con segno) della proiezione di V su N (dato che N e' unitario), non l'angolo fra V ed N. Chiusa parentesi =) |
|
|
|
|
|
|
#14 | |
|
Senior Member
Iscritto dal: Oct 2002
Città: San Jose, California
Messaggi: 11794
|
Re: Re: Re: Collisione terreno
Quote:
Sono stato indeciso per un po' se scrivergli la formuletta oppure no, ma poi ho optato per una versione "soft". Tagliamo la testa al toro e scriviamola tutta allora: dot(V, N) = |V||N|cos(a) Dove: |V| = lunghezza del vettore V |N| = lunghezza del vettore N a = angolo fra i due vettori In parole, il prodotto scalare rappresenta quanto un vettore si "appoggia" su un altro e dipende dall'angolo fra i due vettori. Tornando all'esempio del muro, se mi dirigo direttamente sul muro il mio vettore velocita' e' parallelo alla normale al muro quindi si "appoggia" interamente su essa. Se cammino parallelamente, allora la velocita' e perpendicolare alla normale e non si "appoggia". Spero sia piu' chiaro cosi'.
__________________
"We in the game industry are lucky enough to be able to create our visions" @ NVIDIA |
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 16:56.



















