2011-01-05 9 views
14

OpenGLを使用してiPadの描画アプリケーション(テキスト)を作成しています。私は既にAppleの例GLPaintを見てきました。私のアプリはそのコードに基づいています。私のアプリは絵を描くのではなく、絵を描くだけのものでなければなりません。OpenGLを使用したiPadの描画アプリケーション

さて、私のアプリケーションが動作し、テキストを書くことができます。しかし、執筆は実際には良いことではありません。書くのは楽しいものではありません。描画パスは滑らかではなく、ある点から別の点に線を描いているので角度があります。そしてその道はどこでも同じ幅を持っています。私のアイデアは:あなたが速く書くときは、あなたが遅く書いているときよりも細い線です。実際のペンで書くのと同じ経験でなければなりません。

パスをもっとスムーズに見えるようにするにはどうすればよいですか?筆記の速度に応じて、行の幅を変えるにはどうすればよいですか?あなたは私が何を意味するか見ることができます。ここ

example

答えて

27

図を滑らかにする最も良い方法は、ベゼル曲線を使用することです。ここに私のコードです。それは私がリンゴのdevのサイトで見つけ修正したバージョンですが、私は元のリンク覚えていない:

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

3点に基づいて描画されます。コントロールは中点であり、戻す必要があります。新しい中点は以前のものとは異なるでしょう。また、上記のコードを実行すると、行の半分しか描画されません。次のストロークが入力されます。これは必須です。この関数を呼び出すための私のコード(上記はこのがobj-Cであり、Cである):

//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]; 

コードが反転iPadのポイントに基づいて中間点を取得し、現在のように「制御」を設定することポイント。

エッジが滑らかになります。今では線幅については、その図面の速度を見つける必要があります。あなたの行の長さを見つけるのが最も簡単です。これは、コンポーネント数学を使用して簡単に実行できます。私はそれのためのコードを持っていませんが、hereは、物理サイトからコンポーネントマスマチックのための下塗りです。または、単純に数を(上の)数で割って、必要な線の太さを調べることができます(数はコンポーネントの数学を使用します)。

ポイントデータが明白でない場合は、currentStrokeという配列にポイントデータを格納します。

これで十分です。

EDIT:

ポイントを保存するには、使用すべきtouchesBeginと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]; 
} 

ほとんどが全体の描画アプリケーションです。 GL_Paintを使用している場合は、すでにこのシステムが構築されているポイントスプライトを使用しています。

+0

ありがとう、これは本当に役立ちます。しかし、コードの2番目の部分を実装する場所はわかりません。 GLPaintの例では、ユーザーが指を動かすたびに呼び出される関数renderLineFromPoint:toPoint:があります。コードの2番目の部分をその関数に入れる必要がありますか? – burki

+0

または、コード全体を追加できますか?私は完全な方法を意味する。それはとても親切です。 – burki

+0

touchesBegin、touchesMoved、およびtouchesEndが追加されました。それはポストではかなり多くのOpenGL描画アプリケーションです。 – Beaker

4

あなたの質問の後半部分に関しては(書き込みの速度に応じてラインの幅を変化させるためにどのように)、あなたはする必要がありますtouchesBegan:withEvent:touchesMoved:withEvent:メソッドのUITouchtimestampプロパティを利用してこれを達成することができます。

最新のUITouchオブジェクトのタイムスタンプを保存し、それを新しいものと比較することによって、2つの後続のタッチイベントの時間差を計算することができます。スワイプ動作の距離を時間差で割ると、移動速度の測定値が得られます。

あなたがする必要があるのは、書き込み速度を線幅に変換する方法を考え出すことです。これはおそらく結果に満足するまで任意の値を選んで調整することになります。

+0

これまでのところありがとうございます。私はすでにこのようなことを考えました。あなたが私の最初の問題を解決する方法を知っていればいいでしょう。あなたはupvoteで十分幸せだと思います。 – burki