使用OpenGL在iPad上绘制应用程序

时间:2011-01-05 16:43:02

标签: iphone xcode ipad opengl-es drawing

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

好吧,我的App有效,我可以写一些文字。但写作并不是很好,写作并不好玩。绘制路径不是平滑的,它是有角度的,因为我从一个点到另一个点绘制一条线。并且路径到处都有相同的宽度。我的想法是:当你快速写作时,线条比你写作慢的时候要薄。它应该像用真笔写作一样。

如何让路径看起来更顺畅?如何根据书写速度改变线条的宽度?

在这里你可以看到我的意思:

example

2 个答案:

答案 0 :(得分: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,那么您已经在使用此系统构建的点精灵。

答案 1 :(得分:4)

关于你问题的第二部分(如何根据写作速度改变线条的宽度),你应该能够利用UITouch的{​​{1}来实现这一点。您的timestamptouchesBegan:withEvent:方法中的属性。

您可以通过存储最新touchesMoved:withEvent:对象的时间戳并将其与新对象进行比较来计算两个后续触摸事件之间的时差。将滑动运动的距离除以时差应该可以测量移动速度。

现在您需要做的就是想出一种方法将写入速度转换为线宽,这可能会归结为选择任意值并进行调整直到您对结果感到满意为止。