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

}

Siddharth-Verma
fonte
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

Marco Martinelli
fonte
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.

Dirk
fonte
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.

bobobobo
fonte
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.

Md Mahbubur Rahman
fonte
a detecção de colisão já foi alcançada. Meu objetivo é criar uma animação de sprite.
Siddharth-Verma