#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 <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <Quartz/Quartz.h>
@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];
}