/******************************
** Title: earth and moon
** Author: 於梂 09008211
** Date:2010-12-11
******************************/
#include <Windows.h>
#include <stdio.h>
#include <cmath>
#include <gl/GLU.h>
#include <gl/glut.h>
#include <gl/GLAux.h>
#pragma comment(lib, "glaux.lib");
/* animation definition */
const double pi=3.1415926535897932384626433832795;
const double d=0.1; // lighting's angel change d for each 'a' or 'd' pressed
const double moonRotaV = 10; // speed of moon's rotation
const double sunR = 600; // distance from sun to earth
const double moonRa = 500; // the major semi axis of the orbit of moon
const double moonRb = 300; // the minor semi axis of the orbit of moon
double theta = 0; // of lighting, changed by key 'a' or 'd'
double depressionAngle = 30;
double moonTheta = 0; // of moon's revolution
double earthRota=0; // of earth's rotation
double moonRota=0; // of moon's rotation
GLfloat light_position[] = {sunR,0,0};
GLfloat light_specular[] = {1,1,1,1};
GLfloat light_diffuse[] = {0.5,0.5,0.5,1};
GLfloat light_ambient[] = {0.2,0.2,0.2,1};
GLfloat moon_position[] = {moonRa, 0,0};
bool pause = true; // flag for if the animation pauseed or not
bool setLighting();
bool setLightingPos();
/* OpenGL callback function declaration */
void myInit();
void myDisplay();
void myKeyboardFunc(unsigned char c, int x, int y);
void myIdleFunc();
/* texture function declaration */
AUX_RGBImageRec* textureImage; // used for store the .bmp read in
GLuint texture[2]; //texture[0] is the texture of earth, texture[1] is of moon
AUX_RGBImageRec* loadBMP(char* fileName);
bool loadTexture();
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
/* Set window */
glutInitWindowSize(1200,700);
glutInitWindowPosition(50,25);
glutCreateWindow("Lighting and texture");
/* Initialize OpenGL */
myInit();
/* set callback function */
glutDisplayFunc(myDisplay);
glutKeyboardFunc(myKeyboardFunc);
glutIdleFunc(myIdleFunc);
/* start OpenGL */
glutMainLoop();
return 0;
}
void myInit()
{
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
/* set matrix mode */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-600,600,-350,350,-400,400);
/* set lighting */
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
setLighting();
/* set texture */
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
loadTexture();
}
void myIdleFunc()
{
if (pause)
{
return ;
}
Sleep(30);
/* calculate the new orbit position of moon */
if ((moonTheta -= moonRotaV/360) > 2*pi )
{
moonTheta += 2*pi;
}
moon_position[0] = moonRa*cos(moonTheta);
moon_position[2] = moonRb*sin(moonTheta);
/* implement earth and moon's rotation */
if ((earthRota += 10) > 360 ) earthRota -= 360;
if ((moonRota += moonRotaV) > 360 ) moonRota -= 360;
glutPostRedisplay();
}
void myDisplay()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* generate earth */
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(depressionAngle, 1,0,0); // the angel between sight and the plane of moon's orbit is 30 degree
glPushMatrix();
glRotatef(earthRota,0,1,0);
glRotatef(-90,1,0,0); // make the north polar is on the top
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexCoord2f(0,0);
glTexCoord2f(1,0);
glTexCoord2f(1,1);
glTexCoord2f(0,1);
glColor3d(1,1,1);
GLUquadric* earth = gluNewQuadric();
gluQuadricTexture(earth, true);
gluSphere(earth,160,50,50);
glPopMatrix();
/* generate moon */
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(moon_position[0], moon_position[1], moon_position[2]);
glRotatef(moonRota,0,1,0);
glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexCoord2f(0,0);
glTexCoord2f(1,0);
glTexCoord2f(1,1);
glTexCoord2f(0,1);
glColor3d(1,1,1);
GLUquadric* moon = gluNewQuadric();
gluQuadricTexture(moon, true);
gluSphere(moon,50,50,50);
glPopMatrix();
glFlush();
glutSwapBuffers();
}
bool setLighting()
{
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
return true;
}
bool setLightingPos()
{
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
return true;
}
void myKeyboardFunc(unsigned char c, int x, int y)
{
switch (c)
{
case 'w':
case 'W':if ((depressionAngle += 5) > 90) depressionAngle = 90; break;
case 's':
case 'S':if ((depressionAngle -= 5) < -90) depressionAngle = -90; break;
case 'a':
case 'A':if ((theta += d) > pi*2) theta -= 2*pi; break;
case 'd':
case 'D':if ((theta -= d) < 0) theta += 2*pi;break;
case ' ':pause = !pause;break;
default:return;
}
light_position[0] = sunR * cos(theta);
light_position[2] = sunR * sin(theta);
if (setLightingPos())
{
glutPostRedisplay();
}
}
/* the follow function reference mostly from the Internet. I double the number the texture can be create.Also some place looks bad have been changed*/
bool loadTexture()
{
textureImage = NULL;
/* load texture of earth from earth.bmp */
if (textureImage = loadBMP("earth.bmp"))
{
glGenTextures(2, texture);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textureImage->sizeX, textureImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, textureImage->data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (textureImage->data)
{
free(textureImage->data);
}
free(textureImage);
}
else
{
return false;
}
/* load the texture of moon from moon.bmp */
if (textureImage = loadBMP("moon.bmp"))
{
glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textureImage->sizeX, textureImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, textureImage->data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (textureImage->data)
{
free(textureImage->data);
}
free(textureImage);
}
else
{
return false;
}
return true;
}
/* the follow function reference mostly from the Internet. But I replace the auxDIBImageLoad() with auxDIBImageLoadA() to make the program run correctly.
** As a result, file named with Chinese can't be recognized */
AUX_RGBImageRec* loadBMP(char *fileName)
{
FILE *pFile = NULL;
if (!fileName)
{
return NULL;
}
pFile = fopen(fileName, "r");
if (pFile)
{
fclose(pFile);
return auxDIBImageLoadA(fileName);
}
return NULL;
}