Gael LE BELLEGO
Gael LE BELLEGO

Reputation: 31

"MouseDragged" but NSOpenGlView not refreshed until "MouseUp"

I have a curious problem about an App which MainView is inherited from NSOpenGlView. I am able to draw many things in it, like a basic OpenGL tutorial.... but when I try to implement a basic trackball, it looks like the app waits until I release the mouse button before it refreshes my view... even if I call directly the "DrawRect" callback from the "MouseDragged" callback, it acts the same. Then, I really can't find out how to do such a basic thing and what is the problem about my solution..

Any idea?

My NSOpenGLVIew has double buffer, and and additional depth buffer. Here are the main messages.

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

- (void)mouseDragged:(NSEvent *)theEvent {

//[[self openGLContext] makeCurrentContext];


float curPos[3], dx, dy, dz;

dx = curPos[0] - lastPos[0];
dy = curPos[1] - lastPos[1];
dz = curPos[2] - lastPos[2];

angle = 90.0 * sqrt(dx*dx + dy*dy + dz*dz);
axis[0] = lastPos[1]*curPos[2] - lastPos[2]*curPos[1];
axis[1] = lastPos[2]*curPos[0] - lastPos[0]*curPos[2];
axis[2] = lastPos[0]*curPos[1] - lastPos[1]*curPos[0];

//glutPostRedisplay();

//[self drawRect:self.bounds]; // different attempts
[self setNeedsDisplay:YES]; //
//[self display]; 

}

#pragma mark Mouse Handling

- (void)mouseDown:(NSEvent *)theEvent {

m_PreviousMouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil];
ptov(m_PreviousMouseLoc.x,m_PreviousMouseLoc.y,m_width,m_height,lastPos);

}

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



- (void)mouseUp:(NSEvent *)theEvent {

[self setNeedsDisplay:YES];

}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


void ptov(int x, int y, int width, int height, float v[3]){

float a,d;

// project x,y onto  1/2 sphere  centered within width and height
v[0] = (2.0*x - width)/ width;
v[1] = (height - 2.0*y)/ height;
d = sqrt(v[0]*v[0] + v[1]*v[1]);
v[2] = cos((PI/2)*((d < 1.0) ? d : 1.0));
a = 1.0 / sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
v[0] *=a;
v[1] *=a;
v[2] *=a;

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


 -(void)prepareOpenGL{

if( ![ self loadGLTextures ] ){
    NSLog(@"Failed to load GL Textures");
}


 GLint swapInt = 1;

 [[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];     // set to vbl sync 


//glEnable( GL_TEXTURE_2D );                // Enable texture mapping
glShadeModel( GL_SMOOTH );                // Enable smooth shading
glClearColor( 0.0f, 0.0f, 0.0f, 0.5f );   // Black background
glClearDepth( 1.0f );                     // Depth buffer setup
glEnable(GL_DEPTH_TEST);                                // Enables Depth Testing
    glEnable (GL_BLEND);
glDepthFunc(GL_LEQUAL);                                 // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  // Really Nice Perspective Calculations

glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 


glPolygonOffset (1.0f, 1.0f);

firstOccurenceOfDrawRect = NO;


/* // set start values...
rVel[0] = 0.3; rVel[1] = 0.1; rVel[2] = 0.2; 
rAccel[0] = 0.003; rAccel[1] = -0.005; rAccel[2] = 0.004;*/

    [[self window] setAcceptsMouseMovedEvents: YES]; 

glViewport(0, 0, (GLsizei) self.bounds.size.width, (GLsizei) self.bounds.size.height);  
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 - (void) drawRect: (NSRect) rect
 { 
 ///    if (firstOccurenceOfDrawRect)
//  [self initGL];

 // On charge la matrice de projection pour définir ce que l'on va voir et comment
glMatrixMode(GL_PROJECTION);

// On centre
glLoadIdentity();

// On prend du recul
glOrtho(-1.0f, 1.0f, -1.5f, 1.5f, -10.0f, 10.0f);

// On efface ce qui a été dessiné auparavant
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// On va maintenant définir ce que l'on veut dessiner
glMatrixMode(GL_MODELVIEW);


// Avant de commencer à dessiner, on va affecter de deux rotations le repère des coordonnées du cube pour le faire "bouger"
glLoadIdentity();
glRotatef(angle, axis[0], axis[1], axis[2]); 

//  [self resizeGL]; // forces projection matrix update (does test for size changes)
//  [self updateModelView];

    glColor3f (1.0, 1.0, 1.0); 
    glDisable(GL_CULL_FACE);
    glFrontFace(GL_CW);
    glutSolidTeapot(200.0);
    glFrontFace(GL_CCW);

    glEnable(GL_TEXTURE_2D);

    glBindTexture( GL_TEXTURE_2D, texture[ 0 ] );   // Select our texture

    glBegin( GL_QUADS );
    // Front
    glTexCoord2f( 0.0f, 0.0f );
    glVertex3f( -1.0f, -1.0f,  0.0f );   // Bottom left
    glTexCoord2f( 1.0f, 0.0f );
    glVertex3f(  1.0f, -1.0f,  0.0f );   // Bottom right
    glTexCoord2f( 1.0f, 1.0f );
    glVertex3f(  1.0f,  1.0f,  0.0f );   // Top right
    glTexCoord2f( 0.0f, 1.0f );
    glVertex3f( -1.0f,  1.0f,  0.0f );   // Top left
    glEnd();

    glBindTexture( GL_TEXTURE_2D, texture[ 1 ] );   // Select our texture

    glBegin( GL_QUADS );
    // side
    glTexCoord2f( 1.0f, 0.0f );
    glVertex3f(  0.0f, -1.0f, -1.0f );   // Bottom right
    glTexCoord2f( 1.0f, 1.0f );
    glVertex3f(  0.0f,  1.0f, -1.0f );   // Top right
    glTexCoord2f( 0.0f, 1.0f );
    glVertex3f(  0.0f,  1.0f,  1.0f );   // Top left
    glTexCoord2f( 0.0f, 0.0f );
    glVertex3f(  0.0f, -1.0f,  1.0f );   // Bottom left
    glEnd();


    glBindTexture( GL_TEXTURE_2D, texture[ 2 ] );   // Select our texture

    glBegin( GL_QUADS );
    // Top
    glTexCoord2f( 0.0f, 1.0f );
    glVertex3f( -1.0f,  0.0f, -1.0f );   // Top left
    glTexCoord2f( 0.0f, 0.0f );
    glVertex3f( -1.0f,  0.0f,  1.0f );   // Bottom left
    glTexCoord2f( 1.0f, 0.0f );
    glVertex3f(  1.0f,  0.0f,  1.0f );   // Bottom right
    glTexCoord2f( 1.0f, 1.0f );
    glVertex3f(  1.0f,  0.0f, -1.0f );   // Top right
    glEnd();

    glDisable(GL_TEXTURE_2D); 

 glColor3f (1.0, 1.0, 1.0); 
 glDisable(GL_CULL_FACE);
 glFrontFace(GL_CW);
 glutSolidTeapot(200.0);


[self postRemoteImage];

[[self openGLContext] flushBuffer];
}

Upvotes: 3

Views: 1191

Answers (1)

Brad Larson
Brad Larson

Reputation: 170319

Is this the entire code for the relevant methods? If so, you're never grabbing the mouse's position when you're dragging. curPos[] is uninitialized and may be returning the same values for each time you get a mouseDragged: message. This may make your object always rotate to the same position, making it appear like it's not moving.

Try inserting an NSLog in your mouseDragged: method to make sure that it's being called for your mouse drags (it probably is, but it's good to check).

There's a slight possibility that you're not giving the main run loop a chance to refresh the display, but I think that's unlikely. I've done something similar in my code and had it work just fine with everything on the main thread.

Rather than rolling your own trackball implementation, I suggest looking at Bill Dudney's trackball example code. While it is for the iPhone and deals with Core Animation, the trackball object he uses should be applicable to your case.

Upvotes: 1

Related Questions