1

NSOpenGLViewを使用してドキュメントベースのXcodeプロジェクトを作成すると、奇妙な問題が発生します。アプリケーションは、マウスクリックに応答して、単一のドキュメントで正常に動作します。[ファイル]/[新規]を選択して2番目のドキュメントを開くと、新しいフロントウィンドウが上部に表示されますが、マウスクリックは前の(背景)オブジェクトに送信されます。新しいウィンドウを移動しても、クリックは前のオブジェクトに送信されます。ただし、新しいウィンドウのサイズを変更したり、前のウィンドウで前後にクリックしたりすると、すべてうまく機能します。したがって、問題は、新しい(フロント)ウィンドウがアクティブなコンテキストにならないことであるように思われます。解決策を提案できますか?Xcode 4.4コード(44kb)をhttp://www.mccauslandcenter.sc.edu/CRNL/sw/GLdoc.zipに配置しました。

  1. 新しいドキュメントベースのアプリケーションを作成する
  2. MyOpenGLView.mファイルとMyOpenGLView.hファイルをプロジェクトに追加します
  3. Targets / BuildPhasesの場合、OpenGL.frameworkを「LinkBinaryWithLibraries」に追加します
  4. Targets / BuildPhasesの場合、MyOpenGLView.mを「CompileSources」に追加します
  5. インターフェイスビルダーでa。)ドキュメントのウィンドウを選択し、属性インスペクターで「ワンショット」をオフにしますb。)オブジェクトライブラリからOpenGLビューを追加しますc。)IDインスペクターで、新しく作成されたNSOpenGLViewのクラスをMyOpenGLViewに設定します
  6. プロジェクトを実行する

----開始MyOpenGLView.h

#import <Cocoa/Cocoa.h>
#import <GLUT/GLUT.h>

@interface MyOpenGLView : NSOpenGLView
{
    NSTimer* timer; //animation timer
    NSPoint mouseloc;
    NSPoint screenSize;
    int hourglassSize;
    BOOL updateGL;
}

@end

----開始MyOpenGLView.m

// document based OpenGL application inspired by http://www.alecjacobson.com/weblog/?p=2110
#import "MyOpenGLView.h"

@implementation MyOpenGLView

-(void)prepareOpenGL
{
    //NSLog(@"preparing");
}

- (void)reshape
{
    //NSLog(@"reshaping");
    NSRect rectView = [self bounds];
    screenSize.x = rectView.size.width;
    screenSize.y = rectView.size.height;
}

void enter2D (int width, int height) //Enter2D = reshapeGL
{
    glDisable(GL_DEPTH_TEST);
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, width, 0, height,-1,1); //map view to match pixel size, e.g. gluOrtho2D(0, width, 0, height);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glEnable (GL_BLEND); //allow transparent objects
    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

void drawTriangle (int sz, int left, int bottom)
{
    glLoadIdentity ();
    glTranslatef(left,bottom,0.0f);
    glBegin(GL_TRIANGLES);
    glVertex3f( sz/2, sz, 0.0f);// Top
    glVertex3f(0.0,0.0, 0.0); // Bottom Left
    glVertex3f( sz,0.0f, 0.0f);  // Bottom Right
    glEnd(); // Finished Drawing The Triangle
}

void drawHourGlass (int sz, NSPoint center)
{
    glLoadIdentity ();
    glTranslatef(center.x,center.y,0.0f);
    glBegin(GL_TRIANGLES); //lower triangle
    glVertex3f( 0.0, 0.0, 0.0f); // Top
    glVertex3f(-sz,-sz, 0.0);// Bottom Left
    glVertex3f( sz,-sz, 0.0f);// Bottom Right
    glEnd(); 
    glBegin(GL_TRIANGLES); //upper triangle
    glVertex3f( 0.0, 0.0, 0.0f); // bottom
    glVertex3f(-sz,sz, 0.0);// Top Left
    glVertex3f( sz,sz, 0.0f);// Top Right
    glEnd();
}

-(void)drawRect:(NSRect)rect
{
    updateGL = FALSE;
    //NSLog(@" %f %f",rect.size.width,rect.size.height);
    enter2D(screenSize.x,screenSize.y);
    glClearColor(0.8,0.9,1,1); //background - blue sky
    glClear(GL_COLOR_BUFFER_BIT);
    glColor4f(0.6,0.3,0.1,1.0); //mountains - brown opaque
    drawTriangle(100,10,0);
    drawTriangle(70,80,0);
    glColor4f(0.1,0.1,0.1,0.7); //crosshair - gray, slightly translucent
    drawHourGlass (hourglassSize, mouseloc);
    glFlush();     // Flush all OpenGL calls
}

- (void)mouseDown:(NSEvent *)event
{
    mouseloc = [self convertPoint:[event locationInWindow] fromView:nil];
    updateGL = TRUE;
}

int constrain (int size)
{
    if (size < 5)
        return 5;
    else if (size > 50)
        return 50;
    else
        return size;
}

- (void) magnifyWithEvent:(NSEvent *)event;
{
    if ([event magnification] > 0)
        hourglassSize = hourglassSize + 5;
    else
        hourglassSize = hourglassSize - 5;
    hourglassSize = constrain(hourglassSize);
    updateGL = TRUE;
}

- (void)scrollWheel:(NSEvent *)event
{
    if (event.deltaY < 0)
       hourglassSize = hourglassSize + 5;
    if (event.deltaY > 0)
        hourglassSize = hourglassSize - 5;
    hourglassSize = constrain(hourglassSize);
    updateGL = TRUE;
}

- (void)animationTimer:(NSTimer *)timer
{
    if (updateGL == TRUE)
        [self drawRect:[self bounds]];
}

-(BOOL)acceptsFirstResponder { return YES; }
-(BOOL)becomeFirstResponder { return YES; }
-(BOOL)resignFirstResponder { return YES; }

- (void) awakeFromNib
{
    // [[self window] setAcceptsMouseMovedEvents:YES];
    mouseloc.x = 30;
    mouseloc.y = 40;
    hourglassSize = 30;
    timer = [NSTimer timerWithTimeInterval:(1.0f/60.0f) target:self selector:@selector(animationTimer:) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    // ensure timer fires during resize
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSEventTrackingRunLoopMode];
    updateGL = TRUE;
}

@end
4

1 に答える 1

1

この問題(Appleが配布する古いデモの一部に存在する)に遭遇した他の人のために、OSXの最新バージョン(10.4以降)では、タイマーの代わりにCVDisplayLinkを使用してOpenGLビューを更新します。

http://developer.apple.com/library/mac/#qa/qa1385/_index.html

Alec Jacobsonは、このソリューションの概要をここに示し ますhttp://www.alecjacobson.com/weblog/?p=2185

于 2012-09-28T20:23:09.010 に答える