views:

122

answers:

1

OK, I'm still quite new to Xcode/Cocoa etc, so please forgive me if this issue is something totally obvious, but it seems to me to completely defy any logical software behaviour that I have ever seen.

I have a project which uses OpenGL in Snow Leopard. I have created a very basic solid teapot (using glut, obviously) and have shone a light on it. When I have an unused variable declared in my code (within the body of the method which sets up the light properties, position etc.), the compiler issues a warning and the light does not appear in the viewport.

This is an image of the teapot with no light shining on it:

http://yfrog.com/eqscreenshot20100815at447p

Note the code line above the window with the warning attached to it.

However, if I comment out the line where the unused variable is declared, the light now appears in the viewport. See the image below (note that the line has been commented out):

http://yfrog.com/61screenshot20100815at502p

I've cleaned before building, and have also tried manually deleting the created '.app' executable as well as created object files. Each time, if the variable is present, the light does not appear.

Maybe I'm wrong, but this seems odd: isn't a warning just that - a warning only? Shouldn't the code still compile and run the same way both times? How can this happen? The variable is not used anywhere else in the entire project.

Thanks to anybody who helps out here, and once again I apologise if this is something basic that I've missed.

P.S. Code for the NSOpenGLView subclass that I'm using:

#import "MyOpenGLView.h"
#import <OpenGL/gl.h>
#import <OpenGL/glu.h>
#import <GLUT/GLUT.h>


@implementation MyOpenGLView

#pragma mark Init

- (void) awakeFromNib
{
 [self setUpOpenGL];
}


- (void) setUpOpenGL
{
 [[self openGLContext] makeCurrentContext];

 glEnable(GL_DEPTH_TEST);
 glEnable(GL_LIGHTING);
 glEnable(GL_LIGHT0);
 glShadeModel(GL_SMOOTH);
 glClearColor(0.4, 0.4, 0.4, 1.0);

 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 gluPerspective(45.0, [self bounds].size.width / [self bounds].size.height, 0.1, 1000.0);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();

 glViewport(0.0, 0.0, [self bounds].size.width, [self bounds].size.height);

 [[self openGLContext] update];
}


#pragma mark Helper


- (void) setLight: (int) number x: (GLfloat) x y: (GLfloat) y z: (GLfloat) z color: (NSColor *) color ambientContribution: (GLfloat) ambientContribution
{
 /* Determine which light is being set. */
 GLint lightNumber = 0;
 switch (number) {
  case 0:
   lightNumber = GL_LIGHT0;
   break;
  default:
   break;
 };

 /* The position of the light. */
 GLfloat lightPosition[] = {
  x, y, z
 };


 /* Various color components. */
 GLfloat red = [color redComponent];
 GLfloat green = [color greenComponent];
 GLfloat blue = [color blueComponent];
 GLfloat alpha = [color alphaComponent];

 /* The contribution of this light source to
  * the ambient light of the entire scene. */
 GLfloat lightAmbient[] = {
  red * ambientContribution, green * ambientContribution, blue * ambientContribution, alpha * ambientContribution
 };

 /* The color of the light glow cast on an object by this light. */
 GLfloat lightDiffuse[] = {
  red, green, blue, alpha
 };

 /* Color of specular highlight created by this light. */
 GLfloat unusedVar = 1.0;
 GLfloat lightSpecular[] = {
  1.0, 1.0, 1.0, 1.0
 };

 glLightfv(lightNumber, GL_AMBIENT, lightAmbient);
 glLightfv(lightNumber, GL_POSITION, lightPosition);
 glLightfv(lightNumber, GL_DIFFUSE , lightDiffuse);
 glLightfv(lightNumber, GL_SPECULAR, lightSpecular);
}



- (void) setMaterialColor: (NSColor *) color shininess: (GLfloat) shininess
{
 GLfloat materialDiffuse[] = {
  [color redComponent], [color greenComponent], [color blueComponent], [color alphaComponent]
 };
 GLfloat * materialAmbient = materialDiffuse;
 GLfloat * materialSpecular = materialDiffuse;
 GLfloat materialShininess[] = {
  shininess
 };
 glMaterialfv(GL_FRONT, GL_AMBIENT, materialAmbient);
 glMaterialfv(GL_FRONT, GL_DIFFUSE, materialDiffuse);
 glMaterialfv(GL_FRONT, GL_SPECULAR, materialSpecular);
 glMaterialfv(GL_FRONT, GL_SHININESS, materialShininess);
}


#pragma mark Animation & drawing


- (BOOL) isOpaque
{
 return NO;
}

- (void) updateAnimation
{
 // TODO: not used yet.
}


- (void) drawOrigin: (NSColor *) color
{
 glColor3f([color redComponent], [color greenComponent], [color blueComponent]);

 glutSolidSphere(0.10, 12, 12);

 glBegin(GL_LINES);
 {
  glVertex3f(0.0, 0.0, 0.0);
  glVertex3f(1.0, 0.0, 0.0);
 }
 glEnd();

 glBegin(GL_LINES);
 {
  glVertex3f(0.0, 0.0, 0.0);
  glVertex3f(0.0, 1.0, 0.0);
 }
 glEnd();

 glBegin(GL_LINES);
 {
  glVertex3f(0.0, 0.0, 0.0);
  glVertex3f(0.0, 0.0, 1.0);
 }
 glEnd(); 
}


- (void) drawRect:(NSRect)dirtyRect
{
 [[self openGLContext] makeCurrentContext];
 [self setUpOpenGL];

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

 /* Move view position. */
 gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); 

 [self drawOrigin: [NSColor redColor]];

 /* Lighting. */
 [self setLight: 0 x: -5.0 y: 5.0 z: 10.0 color: [NSColor colorWithCalibratedRed: 1.0 green: 1.0 blue: 0.80 alpha: 1.0] ambientContribution: 0.10];

 /* Draw objects. */
 [self setMaterialColor: [NSColor colorWithCalibratedRed: 0.3 green:0.3 blue: 0.80 alpha: 1.0] shininess: 100.0];
 glutSolidTeapot(1.0);

 glFlush();
}
@end
+3  A: 

One problem you have is that glLightfv() takes three parameters, the last of which is an array of four glFloats - always. Your lightPosition array is too small. It's likely that the unused variable makes the floating point numbers in that array sensible for all four elements instead of just the first three.

JeremyP
Oh, wow! Well spotted! Adding a final '1.0' to the lightPosition array seems to have solved the problem. What a daft mistake to make... Thanks so much for clearing it up for me. Now I can sleep. :S
Benjamin Selby
Glad it fixed your issue. Would you like to accept the answer then :-)
JeremyP
And for future reference, any time you have an issue where putting in or taking out a variable definition, it's almost certain that the problem is due to an incorrect assumption about the size of something causing a bounds issue. So in this instance, I looked up the definition of the function to get the parameter sizes and checked all of the variables you were passing to make sure they were big enough.
JeremyP
I should have thought to check the basics. Thanks very much for your help.
Benjamin Selby