2011-01-05 61 views
14

我使用OpenGL为iPad创建绘图应用程序(文本)。我已经看过苹果的例子GLPaint,我的应用程序现在基于该代码。我的应用程序应该只是绘制文本,而不是绘制图片。使用OpenGL在iPad上绘制应用程序

那么,我的应用程序的作品,我可以写一些文字。但写作不是很好,写作也没有乐趣。绘图路径不平滑,这是因为我从一个点绘制一条线到另一个点。路径的宽度都是一样的。我的想法是:当你写得很快时,线条比写作时慢。它应该与使用真正的笔书写相同的体验。

如何让路径看起来更平滑?我如何根据写作速度改变线条的宽度?

在这里你可以明白我的意思:

example

回答

27

平滑绘图的最佳方法是使用bezeir曲线。这是我的代码。这是一个修改版本我在苹果的开发网站上发现的,但我不记得原文链接:

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

这将利用基于三点。控制是你需要返回的中点。新的中点将与以前不同。另外,如果你通过上面的代码,它只会画出一半的线。下一个笔画将填充它。这是必需的。我调用这个函数代码(上面是在C,这是的OBJ-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的数组中,以防它不明显。

这应该是你所需要的。

编辑:

要存储点,你应该使用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

非常感谢,这真的有帮助。但我不确定在哪里实现代码的第二部分。在GLPaint示例中,有一个函数renderLineFromPoint:toPoint:,每当用户移动他的手指时调用它。我需要将代码的第二部分放入该函数中吗? – burki 2011-01-06 12:03:45

+0

或者你可以添加整个代码?我的意思是完整的方法。那样会很亲切。 – burki 2011-01-06 20:00:53

+0

添加了touchesBegin,touchesMoved和touchesEnd。这几乎是一篇完整的openGL绘图应用程序。 – Beaker 2011-01-07 02:24:43

4

至于你问题的第二部分(如何具体费用取决于写入速度线的宽度),你应该能够通过利用UITouchtimestamp财产在您的touchesBegan:withEvent:touchesMoved:withEvent:方法中实现此目的。

您可以通过存储最近UITouch对象的时间戳和它比较新的一个计算两个连续的触摸事件之间的时间差。划分滑动运动的时间差应该给你一些移动速度的测量值。

现在,所有你需要做的就是拿出一个办法转换速度写入线的宽度,这可能将回落到采摘一个任意值,调整它,直到你满意的结果。

+0

到目前为止感谢。我已经想到了这样的事情。如果你知道如何解决我的第一个问题会很好。希望你用upvote足够快乐。 – burki 2011-01-05 20:00:51