animation de sprite dans openGL


9

Je rencontre des problèmes pour implémenter l'animation de sprite dans openGL ES. Je l'ai googlé et la seule chose que je reçois est le tutoriel implémentant via Canvas.

Je connais le chemin mais j'ai du mal à le mettre en œuvre.

Ce dont j'ai besoin: une animation de sprite sur la détection de collision.

Ce que j'ai fait: la fonction de détection de collision fonctionne correctement.

PS: Tout fonctionne bien mais je veux implémenter l'animation dans OPENGL UNIQUEMENT. La toile ne fonctionnera pas dans mon cas.

------------------------ ÉDITER-----------------------

J'ai maintenant une feuille de sprite, disons celle ci-dessous ayant certaines coordonnées, mais d'où commenceront les coordonnées (u, v)? Dois-je considérer mes coordonnées u, v de (0,0) ou de (0,5) et dans quel motif dois-je les stocker dans ma liste ..? ----> De gauche à droite OU ----> de haut en bas

Dois-je avoir un tableau 2D dans ma classe de sprites? voici l'image pour une meilleure compréhension.

Feuille de sprite Je suppose que j'ai une feuille de sprite NxN, où N = 3,4,5,6, .... et ainsi de suite.

.

.

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'animation de sprites et la détection de collision n'ont rien à voir.
API-Beast

Quel genre d'animation voulez-vous? Squelette, feuille de sprite, autre chose?
GameDev-er

@ GameDev-er J'ai une feuille de sprite.
Siddharth-Verma

1
@ Mr.Beast Je sais qu'ils n'ont rien à voir les uns avec les autres. Mon objectif est de réaliser une animation de sprite après une collision. Jusqu'à présent, je suis capable de détecter les collisions. Mais en ce qui concerne l'animation sprite .. je ne suis pas en mesure de le faire. PS: je suis un débutant à openGL ES et ici aussi .. donc désolé pour l'un de mes commentaires, le cas échéant.
Siddharth-Verma

@Sid Pourquoi avez-vous mélangé x / y? :( X est l'axe horizontal. (Je sais que ce n'est pas intrinsèque mais c'est une convention à laquelle il ne faut pas aller)
doppelgreener

Réponses:


6

Il s'agit d'un extrait de code que j'utilise dans mon application 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

L'astuce consiste à utiliser glMatrixMode suivi de glTranslatef. Cela vous permettra de traduire l'espace uv.

les coordonnées uv vont de (0,0) à (1,1)

Supposons que vous ayez une texture carrée avec 4 images et que vous souhaitiez texturer un quad. Je vais utiliser les coordonnées suivantes pour définir des cadres dans l'espace uv (le choix vous appartient)

1er (0, 0) (0,5, 0,5)

2e (0,5, 0) (1, 0,5)

3e (0, 0,5) (0,5, 1)

4e (0,5, 0,5) (1, 1)

Avec glTexCoordPointer, vous devez mapper la 1ère image sur votre quad puis lorsque vous souhaitez afficher la 2ème image que vous appelez glTranslatef (0,5, 0, 0), glTranslatef (0, 0,5, 0) pour la 3ème et glTranslatef (0,5, 0,5, 0 ) pour le 4.

Le code ci-dessus est testé et fonctionne très bien, j'espère que l'exemple est assez clair.


ÉDITER:

à la fin de votre fonction de dessin, vous devez réinitialiser votre matrice de texture avec ce code.

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

ok, prenons 5 lignes et 4 colonnes comme exemple. Il y a au maximum 20 sprites dans votre spriteet, utilisez donc int idx = (int) ((System.currentTimeMillis ()% 200 * number_of_sprites))) / 200);

idx passe maintenant de 0 à number_of_sprites-1 (peut être <20 si vous avez par exemple 5 lignes, 4 colonnes mais seulement 18 sprite) en changeant sa valeur toutes les 200 ms. En supposant que vous avez votre sprite de gauche à droite et de haut en bas, vous pouvez trouver vos coordonnées de cadre dans l'espace uv en faisant cela.

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);

quand vous faites idx% c vous trouvez votre index de colonne, le résultat est toujours entre 0 et c-1

idx% c est un entier, vous devez le mettre à l'échelle à une valeur comprise entre 0,0 et 1,0 pour que vous divisiez par cf, cf est un flottant donc il y a un transtypage implicite ici

idx / c est la même chose mais pour les lignes, idx et c sont tous les deux des nombres entiers donc le résultat est toujours entier, et c'est l'index des lignes, en divisant par rf vous obtenez une valeur entre 0.0 et 1.0


J'utilise ici une bande triangulaire. Alors ça va marcher dans ce cas?
Siddharth-Verma

Encore une chose .. de quelle manière dois-je stocker les coordonnées? ----> tableau 1D ----> tableau 2D? Si 1D, quelles sont les coordonnées à considérer dans le tableau?
Siddharth-Verma

@Sid Oui, c'est la même chose, il vous suffit d'utiliser les bonnes coordonnées de cartographie uv. Essayez d'adapter mon extrait de code que si vous avez besoin de plus d'aide pour publier votre code
Marco Martinelli

Les coordonnées UV @Sid pour glTexCoordPointer doivent être stockées dans un tableau 1D
Marco Martinelli

1
pour le 1er problème, je ne sais pas, ça fonctionne bien ici, pour le second, vous devez arrêter idx pour revenir à 0, donc une astuce simple est la suivante. Déclarez une variable int oldIdx;avant cela public FragileSquare()dans la méthode draw, procédez comme suit: int idx = oldIdx==(numberSprites-1) ? (numberSprites-1) : (int)((System.currentTimeMillis()%(200*numberSprites))/200); oldIdx = idx; À propos, je pense que nous allons OT, la question d'origine a été répondue, vous devriez peut-être fermer celle-ci et en ouvrir une nouvelle si nécessaire.
Marco Martinelli

1

Ma suggestion: créer une texture contenant toutes vos images de votre animation (côte à côte). Modifiez les coordonnées de la texture en fonction du cadre que vous souhaitez afficher.


La moitié a été faite. Mais comment dois-je réaliser cette partie ...... "Modifiez les coordonnées de la texture en fonction du cadre que vous souhaitez afficher." PS: je suis un débutant à openGL ES.
Siddharth-Verma

1

Vous devez utiliser quelque chose appelé une feuille de sprites .

entrez la description de l'image ici

Une feuille de sprites est juste une image unique avec tous les différents "cadres" qui montrent les poses que le personnage peut prendre. Vous sélectionnez le "cadre" de la feuille de sprite à afficher en fonction du temps (comme pour une animation d'explosion) ou de l'entrée du joueur (comme face à gauche, à droite ou dessiner un pistolet)

La façon la plus simple de faire quelque chose comme ça est d'avoir tous les sprites associés de la même taille (même largeur et hauteur), et donc obtenir la coordonnée (u) du 4ème sprite à partir de la gauche est juste (sprite_width*4.0 / sprite_sheet_width).

Si vous essayez d'optimiser et d'être économe en espace, vous pouvez utiliser un outil comme TexturePacker pour emballer vos sprites sur une seule feuille. TexturePacker émet également des données json ou xml qui décrivent les emplacements xy de chacun des sprites dans lesquels vous chargez.


J'ai déjà une feuille de sprite. je connais la méthode, c'est en décalant les coordonnées. Mais ma question principale est "Comment y parvenir est openGL ES?" avez-vous un pseudo-code ou un code java pour cela? L'algorithme pourrait fonctionner pour moi.
Siddharth-Verma

2
Écrivez une Spriteclasse. À l'intérieur du Spriteparc de classe, une liste de paires (u, v) qui décrivent les coordonnées (u, v) de chaque "encore" dans la texture. Vous avez besoin de 2 variables supplémentaires pour suivre le temps: un flottant pour stocker "secondes par image" (# secondes à consacrer à chaque image d'animation), et un autre flottant appelé "horloge", qui stocke "l'heure actuelle" dans le cycle d'animation. Lorsque vous allez dessiner, vous devez mettre à jour l'heure actuelle. Lorsque "secondes par image" est dépassé, vous passez à l'image suivante de l'animation, de sorte que l'animation continue.
bobobobo

D'accord, donc la liste contenant les paires (u, v) sera un tableau 2D?
Siddharth-Verma

voir la question modifiée s'il vous plaît.
Siddharth-Verma

1

Vous pouvez utiliser I_COLLIDE avec OpenGL.

Faites de chaque entité du monde une boîte, puis vérifiez si chacun des axes de la boîte entre en collision avec d'autres entités.

Avec de grandes quantités d'entités pour tester les collisions, vous voudrez peut-être vérifier dans un octree. Vous diviseriez simplement le monde en secteurs, puis vous ne vérifieriez que les collisions entre les objets des mêmes secteurs.

Utilisez également le moteur dynamique Bullet qui est un moteur open source de détection de collision et de physique.


la détection des collisions a déjà été réalisée. Mon objectif est de créer une animation de sprite.
Siddharth-Verma
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.