Dan
Dan

Reputation: 2804

Cocoa/OpenGL coordinate transformations

I'm trying to plot some data by timestamp in a NSOpenGLView. I also want to overlay some non-openGL Cocoa elements above the data, such as highlighting boxes. My difficulty is in getting the coordinate systems to line up.

My data's timestamps are in seconds since the epoch. The values run from -2 to 2. I can plot the raw data without too much difficulty in OpenGL by doing gluOrtho(startTime, endTime, -2, 2). The difficulty comes when I try to mix this with scaling and Cocoa drawing.

For simplicity's sake, I'll use the example of a line. Here is a line plotted (with OpenGL) from (2/18/09 at 13:00:08, -1.5) to (2/18/09 13:00:13, 1.7), or (1234980008, -1.5) to (1234980013, 1.7) in seconds:

Scale=1 http://ccg.cc.gt.atl.ga.us/~anjiro/tmp/scale1.png

For discussion's sake, let's say I want to now use Cocoa to overlay a line, exactly the same, on top of the OpenGL line. I would prefer to be able to do it with the exact same coordinates, namely (1234980008, -1.5) -> (1234980013, 1.7).

So that's the first question. Now I want to see more detail, so I want to scale:

Scale=2 http://ccg.cc.gt.atl.ga.us/~anjiro/tmp/scale2.png

I still want to draw my same Cocoa line, but I also need to know, in data coordinates, what's visible in this window, so I don't have to draw extra data.

I've tried a variety of solutions, but can't quite get anything to work. Can I do this? If so, how? If not, what should I do instead?

Upvotes: 1

Views: 1299

Answers (1)

Renaud Pradenc
Renaud Pradenc

Reputation: 1219

I guess you already know that you obtain the rectangle of the view using -[NSView bounds]. Therefore, you get the following correspondances:

  • startTime <-> bounds.origin.x
  • endTime <-> bounds.origin.x + bounds.size.width
  • (-2) <-> bounds.origin.y
  • (+2) <-> bounds.origin.y + bounds.size.height

If I am not mistaken, this method should convert an NSOpenGL point to a view point:

- (NSPoint) pointWithTime:(long)time value:(float)value
{
    NSPoint point;

    point.x = [self bounds].origin.x 
        + [self bounds].size.width * ((time - startTime) / (endTime - startTime));
    point.y = [self bounds].origin.y
        + [self bounds].size.height * ((value - minValue) / (maxValue - minValue));

    return point;
}

(with minValue = -2 and maxValue = 2.)

For the second part of your question: use the rect provided to the -[NSView drawRect:] method to know which part of the view is to be refreshed. Set details in the Cocoa Drawing Guide which is loquacious about this point. The method may be called several times to draw different parts of the view.

Upvotes: 1

Related Questions