tags:

views:

436

answers:

2

Hi,

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];
}
+1  A: 

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.

Brad Larson
A: 

... now I feel really stupid. I was so much focused on the fact that it moved when I released the Mouse that I didn't even looked at the point I recorded. Though I am sure I used to record it, it must have been rubbed away by a wrong manipulation... and I didn't even realize.

Then, sorry for asking about something that stupid.. I will burry myself somewhere I will be able to hide my shame.

Also, thanks for the link about the trackball example. Although it is not designed for OpenGL purpose, I think I can use it with little adaptations. Thanks again for it.

Gael LE BELLEGO
Why not mark his answer as Accepted, then?
Peter Hosey