2011-01-05 21 views
14

iPad için OpenGL kullanarak bir çizim uygulaması (metin) oluşturuyorum. Apple'ın GLPaint örneğine çoktan bir göz attım ve uygulamam şimdi bu koda dayanıyor. Uygulamam resim çizmek için değil, yalnızca metin çizmek için olmalıdır.OpenGL kullanarak iPad'de çizim uygulaması

Eh, benim App çalışır, bazı metin yazabilirim. Ama yazı gerçekten iyi değil, yazmak eğlenceli değil. Çizim yolu pürüzsüz değil, açısaldır çünkü bir noktadan diğerine çizgi çiziyorum. Ve yol her yerde aynı genişliğe sahip. Benim fikrim: hızlı yazarken çizgi yavaş yazdığınızdan daha ince. Gerçek bir kalemle yazmak gibi aynı deneyim olmalı.

Yolu nasıl daha yumuşak gösterebilirim? Yazma hızına bağlı olarak hattın genişliğini nasıl değiştirebilirim? İşte

ne demek istediğimi görebilirsiniz:

Sorunuzun ikinci kısmına ilgili olarak

example

cevap

27

Çizimi düzeltmenin en iyi yolu bezeir eğrisi kullanmaktır. İşte benim kodum. Ben elma dev sitede bulunan değiştirilmiş bir versiyonu, ama orijinal linki hatırlamıyorum:

CGPoint drawBezier(CGPoint origin, CGPoint control, CGPoint destination, int segments) 
{ 
CGPoint vertices[segments/2]; 
CGPoint midPoint; 
glDisable(GL_TEXTURE_2D); 
float x, y; 

float t = 0.0; 
for(int i = 0; i < (segments/2); i++) 
{ 
    x = pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x; 
    y = pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y; 
    vertices[i] = CGPointMake(x, y); 
    t += 1.0/(segments); 

} 
//windowHeight is the height of you drawing canvas. 
midPoint = CGPointMake(x, windowHeight - y); 
glVertexPointer(2, GL_FLOAT, 0, vertices); 
glDrawArrays(GL_POINTS, 0, segments/2); 
return midPoint; 
} 

üç puan dayalı olarak çizilir. Kontrol, geri dönmeniz gereken orta noktadır. Yeni orta nokta öncekilerden farklı olacaktır. Ayrıca, yukarıdaki koddan geçerseniz, sadece çizginin yarısını çizecektir. Bir sonraki vuruş onu doldurur. Bu gereklidir. Bu fonksiyonu çağırmak için benim kodu (yukarıdaki C olduğu, bu Obj C ise):

//Invert the Y axis to conform the iPhone top-down approach 
    invertedYBegCoord = self.bounds.size.height - [[currentStroke objectAtIndex:i] CGPointValue].y; 
    invertedYEndCoord = self.bounds.size.height - [[currentStroke objectAtIndex:i+1] CGPointValue].y; 
    invertedYThirdCoord = self.bounds.size.height - [[currentStroke objectAtIndex:i+2] CGPointValue].y; 
    //Figure our how many dots you need 
    count = MAX(ceilf(sqrtf(([[currentStroke objectAtIndex:i+2] CGPointValue].x - [[currentStroke objectAtIndex:i] CGPointValue].x) 
     * ([[currentStroke objectAtIndex:i+2] CGPointValue].x - [[currentStroke objectAtIndex:i] CGPointValue].x) 
     + ((invertedYThirdCoord - invertedYBegCoord) * (invertedYThirdCoord - invertedYBegCoord)))/pointCount), 1); 

    newMidPoint = drawBezier(CGPointMake([[currentStroke objectAtIndex:i] CGPointValue].x, invertedYBegCoord), CGPointMake([[currentStroke objectAtIndex:i+1] CGPointValue].x, invertedYEndCoord), CGPointMake([[currentStroke objectAtIndex:i+2] CGPointValue].x, invertedYThirdCoord), count); 

    int loc = [currentStroke count]-1; 
    [currentStroke insertObject:[NSValue valueWithCGPoint:newMidPoint] atIndex:loc]; 
    [currentStroke removeObjectAtIndex:loc-1]; 

akım gibi 'kontrol' ters iPad noktaları dayalı orta noktası olsun ve ayarlayacaktır Bu kod puan.

Bu kenarları yumuşatır. Şimdi çizgi genişliği ile ilgili olarak, sadece o çizimin hızını bulmanız gerekiyor. Sadece hattınızın uzunluğunu bulmak en kolay yoldur. Bu bileşen matematiği kullanılarak kolayca yapılır. Bunun için herhangi bir kodum yok, ancak here, bir fizik sitesinden bileşen matematiği için bir astardır. Ya da çizginin ne kadar kalın olması gerektiğine karar vermek için bir sayıya kadar sayma (sayma) yapabilirsiniz (sayı, bileşen matematiğini kullanır).

Durum verileri, açık olmadığı takdirde currentStroke adlı bir dizide saklıyorum.

İhtiyacın olan her şey bu olmalı.

DÜZENLEME:

puan depolamak için, kullanmanız gereken touchesBegin ve touchesEnd:

- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event 
{ 
    self.currentStroke = [NSMutableArray array]; 
    CGPoint point = [ [touches anyObject] locationInView:self]; 
    [currentStroke addObject:[NSValue valueWithCGPoint:point]]; 
    [self draw]; 

} 

- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event 
{ 
    CGPoint point = [ [touches anyObject] locationInView:self]; 
    [currentStroke addObject:[NSValue valueWithCGPoint:point]]; 
    [self draw]; 
} 


- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    CGPoint point = [ [touches anyObject] locationInView:self]; 
    [currentStroke addObject:[NSValue valueWithCGPoint:point]]; 
    [self draw]; 
} 

hemen hemen orada bütün bir çizim uygulamasıdır. GL_Paint kullanıyorsanız, bu sistem üzerinde kurulu olan nokta spritelarını zaten kullanıyorsunuz demektir.

+0

Çok teşekkürler, bu gerçekten yardımcı olur. Ama kodun ikinci bölümünü nerede uygulayacağımı bilmiyorum. GLPaint örneğinde, kullanıcının parmağını hareket ettirdiği her seferinde çağrılan renderLineFromPoint: toPoint: işlevi vardır. Kodunuzun ikinci bölümünü bu işleve eklemem gerekiyor mu? – burki

+0

Veya tüm kodu ekleyebilir misiniz? Bütün yöntemleri kastediyorum. Bu çok nazik olurdu. – burki

+0

EklenenlerBeğen, dokunuşlarKaldırılmış ve dokunuşlarEnd. Bu, yazı içinde hemen hemen tüm bir openGL çizim uygulamasıdır. – Beaker

4

(yazma hızına bağlı olarak hat genişliğini değiştirmek için nasıl), sen olmalı UITouchtimestamp özelliğinden yararlanarak, touchesBegan:withEvent: ve touchesMoved:withEvent: yönteminden yararlanarak bunu gerçekleştirebilirsiniz.

En son UITouch nesnesinin zaman damgasını saklayarak ve yeni olanla karşılaştırarak, sonraki iki dokunma olayı arasındaki zaman farkını hesaplayabilirsiniz. Kayma hareketinin zaman farkına bölünmesi, size hareket hızının bir miktar ölçümünü vermelidir.

Yapmanız gereken tek şey, yazı hızını satır genişliğine dönüştürmenin bir yolunu bulmaktır. Bu, muhtemelen keyfi bir değer seçmek ve sonuçtan memnun kalmayıncaya kadar ayarlamaktır.

+0

Şimdiye kadar teşekkürler. Daha önce böyle bir şey düşündüm. İlk problemimi nasıl çözeceğimi biliyorsan iyi olur. Umarım yeteri kadar mutlu olursun. – burki