animazione sprite in openGL


9

Sto riscontrando problemi nell'implementazione dell'animazione sprite in openGL ES. L'ho cercato su Google e l'unica cosa che ottengo è l'implementazione del Tutorial tramite Canvas.

Conosco la strada ma sto riscontrando problemi nella sua attuazione.

Cosa mi serve: un'animazione sprite sul rilevamento delle collisioni.

Cosa ho fatto: la funzione di rilevamento delle collisioni funziona correttamente.

PS: Tutto funziona bene ma voglio implementare l'animazione SOLO in OPENGL. La tela non funzionerà nel mio caso.

------------------------ MODIFICARE-----------------------

Ora ho un foglio sprite, diciamo quello sotto che ha alcune coordinate, ma da dove iniziano le coordinate (u, v)? Devo considerare le mie coordinate u, v da (0,0) o da (0,5) e in quale modello devo memorizzarle nella mia lista ..? ----> Da sinistra a destra OPPURE ----> dall'alto verso il basso

Devo avere un array 2D nella mia classe sprite? ecco l'immagine per una migliore comprensione.

Foglio di Sprite Suppongo di avere un foglio sprite NxN, dove N = 3,4,5,6, .... e così via.

.

.

class FragileSquare{

FloatBuffer fVertexBuffer, mTextureBuffer;

ByteBuffer mColorBuff;

ByteBuffer mIndexBuff;

int[] textures = new int[1];

public boolean beingHitFromBall = false;

int numberSprites = 49;

int columnInt = 7;      //number of columns as int

float columnFloat = 7.0f; //number of columns as float

float rowFloat = 7.0f;


public FragileSquare() {
    // TODO Auto-generated constructor stub

    float vertices [] = {-1.0f,1.0f,            //byte index 0
                         1.0f, 1.0f,            //byte index 1
                                    //byte index 2
                         -1.0f, -1.0f,
                         1.0f,-1.0f};           //byte index 3


    float textureCoord[] = {
                            0.0f,0.0f,
                            0.142f,0.0f,
                            0.0f,0.142f,
                            0.142f,0.142f           


    };


    byte indices[] = {0, 1, 2,
            1, 2, 3 };

    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4*2 * 4); // 4 vertices, 2 co-ordinates(x,y) 4 for converting in float
    byteBuffer.order(ByteOrder.nativeOrder());
    fVertexBuffer = byteBuffer.asFloatBuffer();
    fVertexBuffer.put(vertices);
    fVertexBuffer.position(0);

    ByteBuffer byteBuffer2 = ByteBuffer.allocateDirect(textureCoord.length * 4);
    byteBuffer2.order(ByteOrder.nativeOrder());
    mTextureBuffer =  byteBuffer2.asFloatBuffer();
    mTextureBuffer.put(textureCoord);
    mTextureBuffer.position(0);

}



public void draw(GL10 gl){


    gl.glFrontFace(GL11.GL_CW);

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glVertexPointer(1,GL10.GL_FLOAT, 0, fVertexBuffer);
    gl.glEnable(GL10.GL_TEXTURE_2D);
    int idx = (int) ((System.currentTimeMillis()%(200*4))/200);
    gl.glMatrixMode(GL10.GL_TEXTURE); 
    gl.glTranslatef((idx%columnInt)/columnFloat, (idx/columnInt)/rowFloat, 0);
    gl.glMatrixMode(GL10.GL_MODELVIEW); 
    gl.glEnable(GL10.GL_BLEND);
    gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); //4
    gl.glTexCoordPointer(2, GL10.GL_FLOAT,0, mTextureBuffer); //5
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); //7
    gl.glFrontFace(GL11.GL_CCW);
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glMatrixMode(GL10.GL_TEXTURE);
    gl.glLoadIdentity();
    gl.glMatrixMode(GL10.GL_MODELVIEW);
}

public void loadFragileTexture(GL10 gl, Context context, int resource)
{
    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resource);
    gl.glGenTextures(1, textures, 0);
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
    bitmap.recycle();
}

}


1
L'animazione di Sprite e il rilevamento delle collisioni non hanno nulla a che fare l'uno con l'altro.
API-Beast,

Che tipo di animazione stai cercando? Scheletro, foglio di sprite, qualcos'altro?
GameDev-er,

@ GameDev-er Ho un foglio sprite.
Siddharth-Verma,

1
@ Mr.Beast So che non hanno nulla a che fare l'uno con l'altro. Il mio obiettivo è quello di realizzare l'animazione degli sprite dopo la collisione. Fino ad ora sono in grado di ottenere il rilevamento delle collisioni. Ma per quanto riguarda l'animazione degli sprite ... non sono in grado di farlo. PS: sono un principiante di OpenGL ES e anche qui .. mi dispiace per i miei commenti, se presenti.
Siddharth-Verma,

@Sid Perché hai x / y confuso? :( X è l'asse orizzontale. (So che non è intrinsecamente ma è una convenzione a cui non si dovrebbe andare contro)
doppelgreener,

Risposte:


6

Questo è uno snippet di codice che sto usando nella mia applicazione Android.

gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glMatrixMode(GL10.GL_TEXTURE);    //edit the texture matrix
gl.glTranslatef(u, v, 0);            //translate the uv space (you can also rotate, scale, ...)
gl.glMatrixMode(GL10.GL_MODELVIEW);  //go back to the modelview matrix
gl.glBindTexture(GL10.GL_TEXTURE_2D, getTexture());
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);           //map the texture on the triangles
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, getTextureBuffer()); //load texture coordinates

Il trucco qui è usare glMatrixMode seguito da glTranslatef. Ciò ti consentirà di tradurre lo spazio uv.

le coordinate uv vanno da (0,0) a (1,1)

Supponiamo che tu abbia una trama quadrata con 4 fotogrammi e desideri strutturare un quad. Userò le seguenti coordinate per definire i frame nello spazio uv (a voi la scelta)

1 ° (0, 0) (0,5, 0,5)

2 ° (0,5, 0) (1, 0,5)

3 ° (0, 0,5) (0,5, 1)

4 ° (0,5, 0,5) (1, 1)

Con glTexCoordPointer dovresti mappare il primo fotogramma sul tuo quad, quindi quando vuoi mostrare il secondo fotogramma chiami glTranslatef (0,5, 0, 0), glTranslatef (0, 0,5, 0) per il 3o e glTranslatef (0,5, 0,5, 0 ) per il 4 °.

Il codice sopra è testato e funziona molto bene, spero che l'esempio sia abbastanza chiaro.


MODIFICARE:

al termine della funzione di disegno, è necessario ripristinare la matrice di trama con questo codice.

gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glMatrixMode(GL10.GL_TEXTURE);
gl.glLoadIdentity();
gl.glMatrixMode(GL10.GL_MODELVIEW);

ok, prendiamo 5 righe e 4 colonne come esempio. Ci sono al massimo 20 sprite nel tuo spriteset, quindi usa int idx = (int) ((System.currentTimeMillis ()% 200 * number_of_sprites))) / 200);

idx ora passa da 0 a number_of_sprites-1 (può essere <20 se hai ad esempio 5 righe, 4 colonne ma solo 18 sprite) cambiando il suo valore ogni 200ms. Supponendo che tu abbia il tuo sprite da sinistra a destra e dall'alto verso il basso di quello che puoi trovare le coordinate della cornice nello spazio uv facendo questo.

int c = 4;      //number of columns as int
float cf = 4.f; //number of columns as float
float rf = 5.f; //number of rows as float
gl.glTranslatef((idx%c)/cf, (idx/c)/rf, 0);

quando fai idx% c trovi l'indice di colonna, i risultati sono sempre compresi tra 0 e c-1

idx% c è un numero intero, devi ridimensionarlo su un valore compreso tra 0,0 e 1,0, quindi dividi per cf, cf è un float, quindi c'è un cast implicito qui

idx / c è la stessa cosa ma per righe, idx e c sono entrambi interi quindi il risultato è ancora intero, ed è l'indice di riga, dividendo per rf si ottiene un valore tra 0.0 e 1.0


Sto usando una striscia triangolare qui. Quindi funzionerà in questo caso?
Siddharth-Verma,

Ancora una cosa ... in che modo devo conservare le coordinate? ----> 1D array ----> 2D array? Se 1D, quali sono le coordinate da considerare nell'array?
Siddharth-Verma,

@Sid Sì, è la stessa cosa, devi solo usare le giuste coordinate di mappatura uv. Prova ad adattare il mio frammento di codice che se hai bisogno di più aiuto per pubblicare il tuo codice
Marco Martinelli,

Le coordinate UV @Sid per glTexCoordPointer devono essere memorizzate nell'array 1D
Marco Martinelli,

1
per il 1 ° problema non lo so, qui funziona benissimo, per il secondo, devi fermare idx per tornare a 0 quindi un semplice trucco è questo. Dichiara una variabile int oldIdx;prima di public FragileSquare()allora nel metodo draw: int idx = oldIdx==(numberSprites-1) ? (numberSprites-1) : (int)((System.currentTimeMillis()%(200*numberSprites))/200); oldIdx = idx; In questo modo penso che stiamo andando OT, alla domanda originale è stata data una risposta, forse dovresti chiudere questa e aprirne una nuova se necessario.
Marco Martinelli,

1

Il mio consiglio: crea una trama contenente tutti i fotogrammi dell'animazione (fianco a fianco). Modifica le coordinate della trama in base alla cornice che desideri visualizzare.


La metà è stata fatta. Ma come dovrei ottenere questa parte ... "Modifica le coordinate della trama in base alla cornice che vuoi visualizzare." PS: sono un principiante di openGL ES.
Siddharth-Verma,

1

Devi usare qualcosa chiamato un foglio di calcolo .

inserisci qui la descrizione dell'immagine

Uno spritesheet è solo una singola immagine con tutti i diversi "frame" che mostrano le pose che il personaggio può assumere. Puoi selezionare quale "frame" del foglio sprite visualizzare in base al tempo (come per un'animazione di esplosione) o all'input del giocatore (come affrontare a sinistra, a destra o disegnare una pistola)

Il modo più semplice per fare qualcosa del genere è avere tutti gli sprite correlati della stessa dimensione (stessa larghezza e altezza), e quindi ottenere la coordinata (u) del 4 ° sprite da sinistra è giusto (sprite_width*4.0 / sprite_sheet_width).

Se stai cercando di ottimizzare ed essere efficiente in termini di spazio, puoi utilizzare uno strumento come TexturePacker per impacchettare i tuoi sprite su un singolo foglio. TexturePacker emette anche dati json o xml che descrivono le posizioni xy di ciascuno degli sprite in cui si carica.


Ho già un foglio sprite. Conosco il metodo, è spostando le coordinate. Ma la mia domanda principale è "Come raggiungere questo obiettivo è OpenGL ES?" hai qualche pseudo-codice o un codice java per questo? L'algoritmo potrebbe funzionare per me.
Siddharth-Verma,

2
Scrivi una Spritelezione. All'interno del Spriteparco di classe un elenco di coppie (u, v) che descrivono le coordinate (u, v) di ciascun "fermo" nella trama. Sono necessarie altre 2 variabili per tenere traccia del tempo: un float per memorizzare "secondi per frame" (# secondi da spendere su ciascun frame di animazione) e un altro float chiamato "clock", che memorizza il "tempo corrente" nel ciclo di animazione. Quando vai a disegnare, devi aggiornare l'ora corrente. Quando vengono superati i "secondi per fotogramma", si passa al fotogramma successivo dell'animazione, in modo che l'animazione prosegua.
Bobobobo,

Ok, quindi l'elenco contenente coppie (u, v) sarà un array 2d?
Siddharth-Verma,

vedere la domanda modificata per favore.
Siddharth-Verma,

1

Puoi usare I_COLLIDE con OpenGL.

Trasforma ogni entità nel mondo in una scatola, quindi controlla se ciascuno degli assi della scatola si scontra con altre entità.

Con grandi quantità di entità per verificare le collisioni, potresti voler verificare in un ottavo. Divideresti semplicemente il mondo in settori, quindi verifichi solo la collisione tra oggetti negli stessi settori.

Utilizza anche il motore di dinamica Bullet, che è un motore open source di rilevazione e collisione open source.


il rilevamento delle collisioni è già stato raggiunto. Il mio obiettivo è creare un'animazione sprite.
Siddharth-Verma,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.