animação de sprite em openGL


9

Estou enfrentando problemas na implementação de animação sprite no openGL ES. Eu pesquisei no Google e a única coisa que estou recebendo é o tutorial implementado via Canvas.

Eu sei o caminho, mas estou tendo problemas para implementá-lo.

O que eu preciso: Uma animação de sprite na detecção de colisão.

O que eu fiz: Função de detecção de colisão funcionando corretamente.

PS: Tudo está funcionando bem, mas quero implementar a animação apenas no OPENGL. Canvas não vai funcionar no meu caso.

------------------------ EDIT -----------------------

Agora eu tenho uma planilha de sprite, digamos que a abaixo tenha algumas coordenadas, mas de onde as coordenadas (u, v) começarão? Devo considerar minhas coordenadas u, v de (0,0) ou de (0,5) e em qual padrão devo armazená-las na minha lista ..? ----> Da esquerda para a direita OU ----> de cima para baixo

Preciso ter uma matriz 2D na minha classe de sprites? aqui está a imagem para uma melhor compreensão.

Folha de sprite Estou assumindo que tenho uma folha de sprite NxN, onde N = 3,4,5,6, .... e assim por diante.

.

.

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

}


11
Animação de sprite e detecção de colisão não têm nada a ver um com o outro.
— API-Beast

Que tipo de animação você está querendo? Esquelético, folha de sprite, algo mais?
— GameDev-er 22/09/12

@ GameDev-er Eu tenho uma folha de sprite.
— Siddharth-Verma

11
@ Mr.Beast Eu sei que eles não têm nada a ver um com o outro. Meu objetivo é obter animação de sprite após colisão. Até agora eu sou capaz de alcançar a detecção de colisão. Mas, no que diz respeito à animação em sprites, não consigo fazer isso. PS: Eu sou um novato no openGL ES e aqui também .. desculpe por qualquer um dos meus comentários, se houver.
— Siddharth-Verma

@Sid Por que você tem x / y misturados? :( X é o eixo horizontal (eu sei que não é inerentemente mas é uma convenção que não se deve ir contra).
— doppelgreener

Respostas:


6

Este é um trecho de código que estou usando no meu aplicativo 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

O truque aqui é usar glMatrixMode seguido por glTranslatef. Isso permitirá que você traduza o espaço uv.

As coordenadas uv variam de (0,0) a (1,1)

Vamos supor que você tenha uma textura quadrada com 4 quadros e queira texturizar um quad. Usarei as seguintes coordenadas para definir quadros no espaço uv (a escolha é sua)

1º (0, 0) (0,5, 0,5)

2º (0,5, 0) (1, 0,5)

3º (0, 0,5) (0,5, 1)

Quarto (0,5, 0,5) (1, 1)

Com glTexCoordPointer, você deve mapear o primeiro quadro no seu quad e, quando quiser mostrar o segundo quadro, chamará glTranslatef (0,5, 0, 0), glTranslatef (0, 0,5, 0) para o terceiro e glTranslatef (0,5, 0,5, 0 ) para o quarto.

O código acima é testado e funciona muito bem, espero que o exemplo seja claro o suficiente.


EDITAR:

no final da sua função de desenho, você deve redefinir sua matriz de textura com esse código.

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

ok, vamos dar 5 linhas e 4 colunas como exemplo. Existem no máximo 20 sprites no seu conjunto de sprites, portanto, use int idx = (int) ((System.currentTimeMillis ()% 200 * number_of_sprites))) / 200);

O idx agora passa de 0 a number_of_sprites-1 (pode ser <20 se você tiver, por exemplo, 5 linhas, 4 colunas, mas apenas 18 sprites) alterando seu valor a cada 200ms. Supondo que você tenha seu sprite da esquerda para a direita e de cima para baixo, você pode encontrar a coordenada do seu quadro no espaço uv fazendo isso.

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 você faz o idx% c, encontra o índice da coluna, os resultados estão sempre entre 0 e c-1

idx% c é um número inteiro, é necessário escalá-lo para um valor entre 0,0 e 1,0, para que você divida por cf, cf é um float, portanto, existe uma conversão implícita aqui

idx / c é a mesma coisa, mas para linhas, idx e c são inteiros, portanto o resultado ainda é inteiro e é o índice da linha, dividindo por rf, você obtém um valor entre 0,0 e 1,0


Estou usando uma faixa triangular aqui. Então, vai funcionar neste caso?
— Siddharth-Verma

Mais uma coisa .. de que maneira devo armazenar as coordenadas? ----> matriz 1D ----> matriz 2D? Se 1D, o que todas as coordenadas devo considerar na matriz?
— Siddharth-Verma

@ Sid Sim, é a mesma coisa, você só precisa usar as coordenadas de mapeamento uv corretas. Tente adaptar meu trecho de código do que se precisar de mais ajuda para postar seu código
— Marco Martinelli

Coordenadas UV @Sid para glTexCoordPointer necessidade de ser armazenada no agrupamento de 1D
— Marco Martinelli

11
para o 1º problema que eu não sei, está funcionando bem aqui, para o segundo, você precisa parar o idx para voltar a 0, então um truque simples é esse. Declare uma variável int oldIdx;antes public FragileSquare()disso no método draw, faça o seguinte: int idx = oldIdx==(numberSprites-1) ? (numberSprites-1) : (int)((System.currentTimeMillis()%(200*numberSprites))/200); oldIdx = idx; a propósito, acho que estamos indo para o AT, a pergunta original foi respondida; talvez você deva fechar essa e abrir uma nova, se necessário.
— Marco Martinelli

1

Minha sugestão: Crie uma textura contendo todos os quadros da animação (lado a lado). Altere as coordenadas da textura de acordo com o quadro que você deseja exibir.


Metade disso já foi feito. Mas como devo obter essa parte ...... "Altere as coordenadas da textura de acordo com o quadro que você deseja exibir." PS: eu sou um novato no openGL ES.
— Siddharth-Verma

1

Você precisa usar algo chamado planilha .

insira a descrição da imagem aqui

Uma planilha é apenas uma imagem com todos os diferentes "quadros" que mostram as poses que o personagem pode fazer. Você seleciona qual "quadro" da folha de sprite a ser exibido com base no tempo (como para uma animação de explosão) ou na entrada do jogador (como ficar de frente para a esquerda, direita ou desenhar uma arma)

A maneira mais fácil de fazer algo assim é fazer com que todos os sprites relacionados tenham o mesmo tamanho (mesma largura e altura), e assim obter a coordenada (u) do quarto sprite da esquerda é apenas (sprite_width*4.0 / sprite_sheet_width).

Se você estiver tentando otimizar e economizar espaço, use uma ferramenta como o TexturePacker para compactar seus sprites em uma única folha. O TexturePacker também emite dados json ou xml que descrevem os locais xy de cada um dos sprites nos quais você carrega.


Eu já tenho uma folha de sprite. Eu conheço o método, é mudando as coordenadas. Mas minha pergunta principal é "Como conseguir isso é o openGL ES?" você tem algum pseudo-código ou um código java para isso? O algoritmo pode funcionar para mim.
— Siddharth-Verma

2
Escreva uma Spriteaula. Dentro do Spriteparque de classe, uma lista de pares (u, v) que descrevem as coordenadas (u, v) de cada "imóvel" na textura. Você precisa de mais 2 variáveis ​​para rastrear o tempo: um flutuador para armazenar "segundos por quadro" (# segundos para gastar em cada quadro de animação) e outro flutuador chamado "relógio", que armazena o "horário atual" no ciclo de animação. Quando você vai desenhar, você deve atualizar o horário atual. Quando "segundos por quadro" é excedido, você passa para o próximo quadro da animação, para que a animação avance.
— precisa saber é o seguinte

Ok, então a lista que contém pares (u, v) será uma matriz 2D?
— Siddharth-Verma

veja a pergunta editada, por favor.
— Siddharth-Verma

1

Você pode usar I_COLLIDE com OpenGL.

Faça de cada entidade do mundo uma caixa e verifique se cada um dos eixos da caixa está colidindo com outras entidades.

Com grandes quantidades de entidades para testar colisões, convém verificar uma octree. Você simplesmente dividiria o mundo em setores e só verificaria a colisão entre objetos nos mesmos setores.

Também utilize o mecanismo de dinâmica Bullet, que é um mecanismo de detecção e colisão de código-fonte aberto.


a detecção de colisão já foi alcançada. Meu objetivo é criar uma animação de sprite.
— Siddharth-Verma
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.