openGL'de hareketli grafik animasyonu


9

OpenGL ES'de hareketli grafik animasyonu uygulama konusunda sorunlarla karşılaşıyorum. Ben googled ve ben alıyorum tek şey Tuval üzerinden Tutorial uygulamak olduğunu.

Yolu biliyorum ama uygularken sorun yaşıyorum.

İhtiyacım olan: Çarpışma tespiti üzerine hareketli bir animasyon.

Ne yaptım: Çarpışma Algılama işlevi düzgün çalışıyor.

PS: Her şey iyi çalışıyor ama animasyon SADECE OPENGL uygulamak istiyorum. Tuval benim durumumda çalışmaz.

------------------------ DÜZENLE-----------------------

Şimdi bir sprite sayfam var, diyelim ki aşağıdaki bazı belirli koordinatlara sahip, ama (u, v) koordinatları nereden başlayacak? U, v koordinatlarını (0,0) veya (0,5) 'den mi düşünmeliyim ve bunları hangi modelde listemde saklamalıyım ..? ----> Soldan sağa VEYA ----> yukarıdan aşağıya

Sprite sınıfımda bir 2D diziye sahip olmam gerekir mi? İşte daha iyi bir anlayış için görüntü.

Sprite sayfası Ben bir NxN sprite levha var, burada N = 3,4,5,6, .... ve varsayalım.

.

.

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
Sprite animasyonu ve çarpışma algılamanın birbiriyle hiçbir ilgisi yoktur.
API-Beast

Ne tür bir animasyon istiyorsun? İskelet, hareketli grafik, başka bir şey mi?
GameDev-er

@ GameDev-er Sprite sayfam var.
Siddharth-Verma

1
@ Mr.Beast, birbirleriyle hiçbir ilgileri olmadığını biliyorum. Amacım çarpışmadan sonra hareketli grafiğe ulaşmak. Şimdiye kadar çarpışma algılamayı başarabiliyorum. Ama sprite animasyonu söz konusu olduğunda .. bunu yapamıyorum. PS: i OpenGL ES için bir acemi ve burada da .. varsa herhangi bir yorum için çok üzgünüm.
Siddharth-Verma

@Sid Neden x / y karıştırdınız? . :( X (Ben doğal olarak değil biliyorum ama bir karşı gelmek gerektiğini kongresi) yatay eksendir
doppelgreener

Yanıtlar:


6

Bu, Android uygulamamda kullandığım bir kod pasajı.

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

Buradaki hile, glMatrixMode ve ardından glTranslatef kullanmaktır. Bu uv alanını çevirmenize izin verecektir.

uv koordinatları (0,0) ila (1,1) arasında değişir

Diyelim ki 4 çerçeveli kare bir dokuya sahipsiniz ve dörtlü tekstüre etmek istiyorsunuz. Uv uzayındaki kareleri tanımlamak için aşağıdaki koordinatları kullanacağım (seçim size kalmış)

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)

GlTexCoordPointer ile quad'inizdeki 1. kareyi eşlemelisiniz, ardından 2. kareyi göstermek istediğinizde, 3rd ve glTranslatef (0.5, 0.5, 0) için glTranslatef (0.5, 0, 0), glTranslatef (0, 0.5, 0) dediğinizde ) için.

Yukarıdaki kod test edilmiş ve çok iyi çalışıyor, umarım örnek yeterince açıktır.


DÜZENLE:

çizim fonksiyonunuzun sonunda doku matrisinizi bu kodla sıfırlamanız gerekir.

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

tamam, örnek olarak 5 satır ve 4 sütun alalım. Sprite kümenizde en fazla 20 sprite vardır, bu nedenle int idx = (int) ((System.currentTimeMillis ()% 200 * number_of_sprites))) / 200) kullanın;

idx artık 0'dan number_of_sprites-1'e (örneğin 5 satır, 4 sütun ancak yalnızca 18 sprite varsa <20 olabilir) her 200ms değerini değiştirir. Sprite'ınızın soldan sağa ve yukarıdan aşağıya sahip olduğunu varsayarak, bunu uv uzayında çerçeve koordinatınızı bulabilirsiniz.

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

idx% c yaptığınızda sütun dizininizi bulursunuz, sonuçlar her zaman 0 ile c-1 arasında olur

idx% c bir tamsayıdır, 0,0 ile 1,0 arasında bir değere ölçeklendirmeniz gerekir, böylece cf'ye bölersiniz, cf bir şamandıradır, bu nedenle burada dolaylı bir döküm vardır

idx / c aynı şeydir, ancak satırlar için idx ve c'nin her ikisi de tamsayıdır, bu nedenle sonuç hala tamsayıdır ve satır dizinidir, rf'ye bölünerek 0.0 ile 1.0 arasında bir değer elde edersiniz


Burada bir üçgen şerit kullanıyorum. Peki bu durumda işe yarayacak mı?
Siddharth-Verma

Bir şey daha .. koordinatları ne şekilde saklamalıyım? ----> 1D dizisi ----> 2D dizisi? 1D ise, dizideki tüm koordinatları ne düşünmeliyim?
Siddharth-Verma

@Sid Evet, aynı şey, sadece doğru uv eşleme koordinatlarını kullanmanız gerekir. Kod pasajımı kodunuza daha fazla yardıma ihtiyacınız varsa uyarlamaya çalışın
Marco Martinelli

@ GlTexCoordPointer için UV koordinatları 1D dizisinde saklanmalıdır
Marco Martinelli

1
Bilmiyorum 1. sorun için, burada iyi çalışıyor, ikincisi için, idx 0'a geri dönmek için durdurmanız gerekir, bu yüzden basit bir hile budur. Daha int oldIdx;önce public FragileSquare()draw yönteminde bir değişken bildirin : int idx = oldIdx==(numberSprites-1) ? (numberSprites-1) : (int)((System.currentTimeMillis()%(200*numberSprites))/200); oldIdx = idx; OT'ye gittiğimizi düşünerek, orijinal soru cevaplandı, belki bunu kapatmalı ve gerekirse yeni bir tane açmalısınız.
Marco Martinelli

1

Benim önerim: Animasyonunuzun tüm karelerini içeren doku oluşturun (yan yana). Doku koordinatlarını görüntülemek istediğiniz kareye göre değiştirin.


Yarısı yapıldı. Ama bu bölüme nasıl ulaşmalıyım ...... "Doku koordinatlarını görüntülemek istediğiniz çerçeveye göre değiştirin." PS: OpenGL ES'ye yeni başlayan biriyim.
Siddharth-Verma

1

Sprite sayfası adı verilen bir şey kullanmanız gerekir .

resim açıklamasını buraya girin

Spritesheet, karakterin alabileceği pozları gösteren tüm farklı "çerçevelere" sahip tek bir görüntüdür. Sprite sayfasının hangi "çerçevesini" zamana (bir patlama animasyonu için olduğu gibi) veya oyuncu girişine (sola, sağa veya tabanca çizimi gibi) göre görüntüleneceğini seçersiniz

Bunun gibi bir şey yapmanın en kolay yolu, ilgili tüm spriteların aynı boyutta (aynı genişlik ve yükseklik) olması ve böylece 4. sprite'ın (u) koordinatını soldan elde etmektir (sprite_width*4.0 / sprite_sheet_width).

Optimize etmeye ve alandan tasarruf etmeye çalışıyorsanız, spritelarınızı tek bir sayfaya paketlemek için TexturePacker gibi bir araç kullanabilirsiniz . TexturePacker ayrıca yüklediğiniz spriteların xy konumlarını tanımlayan json veya xml verileri de yayar.


Zaten bir sprite sayfam var. metodu biliyorum, koordinatları değiştirerek. Ama asıl sorum "Bunu başarmak nasıl openGL ES?" bunun için herhangi bir sahte kod veya java kodunuz var mı? Algoritma benim için işe yarayabilir.
Siddharth-Verma

2
Bir Spritesınıf yazın . İçinde Spritesınıfın bir listesini parkı (u, v) doku içinde her bir "hala" nin (u, v) koordinatları tanımlayan çiftleri. Süreyi izlemek için 2 değişken daha gerekir: bir kare "kare başına saniye" depolamak için bir kayan nokta (her animasyon karesinde harcanan # saniye) ve animasyon döngüsünde "geçerli zaman" ı saklayan "saat" adlı başka bir kayan nokta. Çizime gittiğinizde geçerli saati güncellemelisiniz. "Kare başına saniye" aşıldığında, animasyonun devam etmesi için animasyonun bir sonraki karesine geçersiniz.
bobobobo

Peki, (u, v) çiftlerini içeren liste 2d dizisi mi olacak?
Siddharth-Verma

düzenlenen soruya bakınız.
Siddharth-Verma

1

I_COLLIDE'ı OpenGL ile kullanabilirsiniz .

Dünyadaki her varlığı bir kutu haline getirin, ardından kutunun eksenlerinin her birinin diğer varlıklar ile çarpışıp çarpışmadığını kontrol edin.

Çarpışmaları test etmek için büyük miktarlarda varlık ile bir oktree kontrol etmek isteyebilirsiniz. Dünyayı sektörlere ayırırsınız, daha sonra sadece aynı sektörlerdeki nesneler arasındaki çarpışmayı kontrol edersiniz.

Ayrıca açık kaynaklı bir çarpışma algılama ve fizik motoru olan Bullet dinamiği motorunu kullanın.


çarpışma tespiti zaten sağlandı. Amacım bir hareketli grafik animasyonu yaratmak.
Siddharth-Verma
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.