#import "Scene.h" #define glReportError()\ {\ GLenum error=glGetError();\ if(GL_NO_ERROR!=error)\ {\ printf("GL error at:%d: %s\n",__LINE__,(char*)gluErrorString(error));\ }\ }\ #include #include #include @implementation Scene #define MM_TEXTURE_GL_ID 0 #define CLOUDS_TEXTURE_GL_ID 1 static GLUquadric* quad; -(id)init { self = [super init]; if(self) { [self reset]; } return self; } -(void)reset { translation.x=0.0; translation.y=0.0; translation.z=-3.0; rotation.x=-60.0;//start flipped rotation.y=0.0; rotation.z=0.0; scale.x=0.; scale.y=0.0; scale.z=-0.0; animating=NO;//YES; animationTime=0.0; accelerationX=10.0f; accelerationY=10.0f; accelerationZ=10.0f; accelerationScale=0.01f; higlightTime = 0; textureProvider = [[TextureProvider alloc]init]; bStartup = YES; } -(void) dealloc { gluDeleteQuadric(quad); [textureProvider dealloc]; glDeleteTextures(1, &bumpmap_texture); [super dealloc]; } -(void)prepareOpenGL { //glEnable(GL_DEPTH_TEST); /* Enable hidden-surface removal */ glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); GLfloat position[] = { -3.0f, 3.0f, 0.0f, 1.5f }; glLightfv(GL_LIGHT0, GL_POSITION, position); glColorMaterial ( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ) ; glEnable ( GL_COLOR_MATERIAL ) ; glEnable(GL_TEXTURE_2D); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glBindTexture(GL_TEXTURE_2D, MM_TEXTURE_GL_ID); NSSize mmTextSize; const void* mmTextData = [textureProvider mmTextureSize:&mmTextSize]; glTexImage2D (GL_TEXTURE_2D, 0, 4, mmTextSize.width, mmTextSize.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, mmTextData); gluBuild2DMipmaps(GL_TEXTURE_2D, 4, mmTextSize.width, mmTextSize.height, GL_RGBA, GL_UNSIGNED_BYTE, mmTextData); glBindTexture(GL_TEXTURE_2D, CLOUDS_TEXTURE_GL_ID); NSSize cloudsTextSize; const void* cloudsTextData = [textureProvider cloudsTextureSize:&cloudsTextSize]; glTexImage2D (GL_TEXTURE_2D, 0, 4, cloudsTextSize.width, cloudsTextSize.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, cloudsTextData); gluBuild2DMipmaps(GL_TEXTURE_2D, 4, cloudsTextSize.width, cloudsTextSize.height, GL_RGBA, GL_UNSIGNED_BYTE, cloudsTextData); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); quad = gluNewQuadric(); gluQuadricTexture(quad,YES); } - (void)setViewportRect:(NSRect)bounds { glViewport(0,0,bounds.size.width,bounds.size.height); glReportError(); glMatrixMode(GL_PROJECTION); glReportError(); glLoadIdentity(); glReportError(); gluPerspective(30.0f, bounds.size.width/bounds.size.height, 1.0f, 15.0f); glReportError(); glMatrixMode(GL_MODELVIEW); glReportError(); glLoadIdentity(); glReportError(); } -(void)render { glClearColor(0.03f,0.03f,0.03f,1.0f); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //glEnable (GL_MULTISAMPLE_ARB); //glHint (GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); glPushMatrix(); { glTranslatef(translation.x,translation.y,translation.z); glReportError(); if(animating) { animationTime+=1; } rotation.y-=accelerationZ; rotation.x-=accelerationY; rotation.z+=accelerationX; glRotatef(rotation.x+animationTime,1.0f,0.0f,0.0f); glRotatef(rotation.y+animationTime,0.0f,1.0f,0.0f); glRotatef(rotation.z+animationTime,0.0f,0.0f,1.0f); accelerationX*=0.95f; accelerationY*=0.95f; accelerationZ*=0.93f; glReportError(); if(scale.x+accelerationScale>0 && scale.x+accelerationScale<2.f) { scale.x+=accelerationScale; scale.y+=accelerationScale; scale.z-=accelerationScale; } glScalef(scale.x*(1+0.5*sin(animationTime/30.)),scale.y*(1+0.5*sin(animationTime/30.)),scale.z *(1+0.5*sin(animationTime/30.))); if(!bStartup) accelerationScale*=0.93f; else accelerationScale*=0.995f; if(accelerationScale<0.000000001) bStartup = NO; glEnable(GL_TEXTURE_2D); // glBlendFunc(GL_SRC_ALPHA, GL_ONE); glEnable(GL_DEPTH_TEST); glBindTexture(GL_TEXTURE_2D, MM_TEXTURE_GL_ID); glColor4f(1.0f,1.0f,1.0f,1.f); gluSphere( quad, 0.7, 50, 50 ); //glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBindTexture(GL_TEXTURE_2D, CLOUDS_TEXTURE_GL_ID); glRotatef(-rotation.x-animationTime,1.0f,0.0f,0.0f); glRotatef(-rotation.y-animationTime,0.0f,1.0f,0.0f); glRotatef(-rotation.z-animationTime,0.0f,0.0f,1.0f); gluSphere( quad, 0.71, 50, 50 ); glDisable(GL_BLEND); glReportError(); } glPopMatrix(); glReportError(); glFinish(); } - (void)mouseDown:(NSEvent*)theEvent { oldPoint=[theEvent locationInWindow]; higlightTime = 100; } - (void)mouseDragged:(NSEvent*)theEvent { NSPoint point=[theEvent locationInWindow]; if([theEvent modifierFlags]&NSShiftKeyMask) { accelerationZ += 0.02*(point.x-oldPoint.x); } else { accelerationX += 0.02*(point.x-oldPoint.x); accelerationY += 0.02*(point.y-oldPoint.y); } oldPoint=point; higlightTime+=10; } - (void)keyDown:(NSEvent*)event { unichar c=[[event charactersIgnoringModifiers] characterAtIndex:0]; switch(c) { case 'r': case 'R': [self reset]; break; case ' ': case 'a': case 'A': animating=!animating; break; default: break; } } -(void)translateAndStoreMouseDownInViewPoint:(NSPoint)point { GLdouble model_view[16]; glGetDoublev(GL_MODELVIEW_MATRIX, model_view); GLdouble projection[16]; glGetDoublev(GL_PROJECTION_MATRIX, projection); GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); double dx, dy, dz; GLfloat depth[2]; glReadPixels (point.x, point.y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, depth); gluUnProject(point.x, point.y, depth[0], model_view, projection, viewport, &dx, &dy, &dz); clickPointInSpace.x = dx; clickPointInSpace.y = dy; clickPointInSpace.z = dz; } - (void)scrollWheel:(NSEvent *)theEvent { accelerationScale+=0.001f*[theEvent deltaY]; accelerationZ-=0.4f*[theEvent deltaX]; }