2011-01-05 4 views
14

OpenGL을 사용하여 iPad 용 그림 응용 프로그램 (텍스트)을 만들고 있습니다. 나는 이미 애플의 GLPaint 예제를 살펴 봤는데, 이제는 내 코드가 그 코드를 기반으로하고있다. 내 응용 프로그램은 그림 그리기가 아닌 텍스트 그리기를위한 것이어야합니다.OpenGL을 사용하여 iPad에서 그림 그리기

글쎄, 내 애플 리케이션, 나는 몇 가지 텍스트를 작성할 수 있습니다. 그러나 글쓰기가 정말 좋지는 않습니다. 글쓰기가 재미 있지 않습니다. 드로잉 경로가 매끄럽지 않고 한 점에서 다른 점으로 선을 그리므로 각도가 있습니다. 그리고 그 길은 어디서나 같은 너비를 가지고 있습니다. 내 생각은 : 당신이 서면으로 글쓰기를 할 때 느린 글씨를 쓰는 것보다 줄이 더 얇습니다. 실제 펜으로 쓰는 것과 같은 경험이어야합니다.

경로를 더 매끄럽게 보이게하려면 어떻게해야합니까? 필기 속도에 따라 줄 너비를 어떻게 바꿀 수 있습니까? 여기

당신이 무슨 뜻인지 볼 수 있습니다

질문의 두 번째 부분에 관해서

example

답변

27

그림을 부드럽게하는 가장 좋은 방법은 베 제르 곡선을 사용하는 것입니다. 여기 내 코드가있다. Apple의 개발 사이트에서 찾은 수정 된 버전이지만 원래 링크가 기억 나지 않습니다.

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 점을 기준으로 그려집니다. 컨트롤은 중간 지점이며 반환해야합니다. 새로운 중간 점은 이전과 다를 것입니다. 또한 위의 코드를 살펴 본다면 라인의 절반 만 그릴 것입니다. 다음 스트로크가 입력됩니다. 필수 항목입니다. 이 함수를 호출 내 코드 (위의 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]; 

현재로 '제어'를 거꾸로 아이 패드 포인트를 기준으로 중간 점을 얻고, 설정합니다 그 코드 포인트.

가장자리를 부드럽게 만듭니다. 이제 선폭과 관련하여 그 그림의 속도를 찾아야합니다. 선의 길이를 찾는 것이 가장 쉽습니다. 이는 컴포넌트 수학을 사용하여 쉽게 수행됩니다. 필자는 코드를 가지고 있지 않지만, 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

+0

또는 전체 코드를 추가 할 수 있습니까? 나는 완전한 방법을 의미합니다. 그것은 매우 친절합니다. – burki

+0

touches 추가, touchesMoved 및 touchesEnd가 추가되었습니다. 꽤 많은 OpenGL 그리기 응용 프로그램이 게시됩니다. – Beaker

4

(쓰기의 속도에 따라 라인의 폭을 변화하는 방법), 당신이해야 touchesBegan:withEvent:touchesMoved:withEvent: 방법에 UITouch 님의 timestamp 속성을 사용하여이를 달성 할 수 있습니다.

두 번째 연속 터치 이벤트의 시간 차이는 가장 최근의 UITouch 개체의 타임 스탬프를 저장하고 새 개체와 비교하여 계산할 수 있습니다. 스 와이프 동작의 거리를 시간차로 나누면 이동 속도를 측정 할 수 있습니다.

당신이해야 할 일은 라인 폭으로 쓰기 속도를 변환하는 방법을 제시하는 것입니다. 그러면 아마 임의의 값을 선택하고 결과에 만족할 때까지 조정할 수 있습니다.

+0

감사합니다. 나는 이미 이런 생각을했습니다. 내 첫 번째 문제를 해결하는 방법을 알고 있다면 좋을 것입니다. 당신이 upvote로 충분히 행복하기를 바랍니다. – burki