Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I make my own recordedPath in GLPaint Sample Code

I've recently downloaded the GLPaint sample code and looked at a very interesting part in it. There is a recordedPaths NSMutableArray that has points in it that are then read and drawn by GLPaint.

It's declared here:

NSMutableArray *recordedPaths;
recordedPaths = [NSMutableArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Recording" ofType:@"data"]];
if([recordedPaths count])
     [self performSelector:@selector(playback:) withObject:recordedPaths afterDelay:0.2];

This is the code for playback:

 - (void) playback:(NSMutableArray*)recordedPaths {

     NSData*                    data = [recordedPaths objectAtIndex:0];

     CGPoint*               point = (CGPoint*)[data bytes];

     NSUInteger               count = [data length] / sizeof(CGPoint),

                              i;



     //Render the current path

     for(i = 0; i < count - 1; ++i, ++point)

          [self renderLineFromPoint:*point toPoint:*(point + 1)];



     //Render the next path after a short delay 

     [recordedPaths removeObjectAtIndex:0];

     if([recordedPaths count])

          [self performSelector:@selector(playback:) withObject:recordedPaths afterDelay:0.01];

}

From this I understand that recordedPaths is a mutable array that his in it struct c arrays of CGPoint that are then read and rendered. I'd like to put in my own array and i've been having trouble with that.

I tried changing the recordedPaths declaration to this:

      NSMutableArray *myArray = [[NSMutableArray alloc] init];

      CGPoint* points;

      CGPoint a = CGPointMake(50,50);

      int i;

      for (i=0; i<100; i++,points++) {

           a = CGPointMake(i,i);

           points = &a;

      }

      NSData *data = [NSData dataWithBytes:&points length:sizeof(*points)];

      [myArray addObject:data];

This didn't work though... Any advice?

like image 405
gizmoitai Avatar asked Feb 27 '23 11:02

gizmoitai


2 Answers

If you look at the Recording.data you will notice that each line is its own array. To capture the ink and play it back you need to have an array of arrays. For purposes of this demo - declare a mutable array - writRay

    @synthesize writRay;
//init in code
 writRay = [[NSMutableArray alloc]init];

Capture the ink

// Handles the continuation of a touch.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{  

 CGRect    bounds = [self bounds];
 UITouch*   touch = [[event touchesForView:self] anyObject];

 // Convert touch point from UIView referential to OpenGL one (upside-down flip)
 if (firstTouch) {
  firstTouch = NO;
  previousLocation = [touch previousLocationInView:self];
  previousLocation.y = bounds.size.height - previousLocation.y;
  /******************* create a new array for this stroke's points **************/
  [writRay addObject:[[NSMutableArray alloc]init]];
  /***** add 1st point *********/
  [[writRay objectAtIndex:[writRay count] -1]addObject:[NSValue valueWithCGPoint:previousLocation]];
 } else {
  location = [touch locationInView:self];
     location.y = bounds.size.height - location.y;
  previousLocation = [touch previousLocationInView:self];
  previousLocation.y = bounds.size.height - previousLocation.y;
  /********* add additional points *********/
  [[writRay objectAtIndex:[writRay count] -1]addObject:[NSValue valueWithCGPoint:previousLocation]];
 }

 // Render the stroke
 [self renderLineFromPoint:previousLocation toPoint:location];

}

Playback the ink.

- (void)playRay{

 if(writRay != NULL){

  for(int l = 0; l < [writRay count]; l++){
    //replays my writRay -1 because of location point
   for(int p = 0; p < [[writRay objectAtIndex:l]count] -1; p ++){
    [self renderLineFromPoint:[[[writRay objectAtIndex:l]objectAtIndex:p]CGPointValue] toPoint:[[[writRay objectAtIndex:l]objectAtIndex:p + 1]CGPointValue]];
   }
  }
 }
}

For best effect shake the screen to clear and call playRay from changeBrushColor in the AppController.

like image 63
Jim Geldermann Avatar answered Mar 07 '23 21:03

Jim Geldermann


  CGPoint* points;
  CGPoint a = CGPointMake(50,50);
  int i;
  for (i=0; i<100; i++,points++) {
       a = CGPointMake(i,i);
       points = &a;
  }
  NSData *data = [NSData dataWithBytes:&points length:sizeof(*points)];

Wrong code.

(1) You need an array of points. Simply declaring CGPoint* points; won't create an array of points, just an uninitialized pointer of CGPoint. You need to allocate space for the array either with

CGPoint points[100];

or

CGPoint* points = malloc(sizeof(CGPoint)*100);

Remember to free the points if you choose the malloc way.

(2) To copy value to the content of the pointer you need to use

*points = a;

But I suggest you keep the pointer points invariant in the loop, since you're going to reuse it later. Use the array syntax points[i].

(3)

sizeof(*points)

Since *points is just one CGPoint, so the sizeof is always 8 bytes. You need to multiply the result by 100 to get the correct length.

(4)

 [NSData dataWithBytes:&points ...

points already is a pointer to the actual data. You don't need to take the address of it again. Just pass points directly.


So the final code should look like

  CGPoint* points = malloc(sizeof(CGPoint)*100); // make a cast if the compiler warns.
  CGPoint a;
  int i;
  for (i=0; i<100; i++) {
       a = CGPointMake(i,i);
       points[i] = a;
  }
  NSData *data = [NSData dataWithBytes:points length:sizeof(*points)*100];
  free(points);
like image 36
kennytm Avatar answered Mar 07 '23 19:03

kennytm