/************************************************** * File: InsideSphere.cpp * Author: Dr. Dalton R. Hunkins * Date: January 2009 * * User Interaction * Although the standard popup * menu to show code and to exit * are provided in this example, * its code is not included here. * * Mouse Motion * Drag Mouse with Left Button Down * orbits the camera (same as in * the Camera Animation tutorial) **************************************************/ #include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h> #include <cmath> #include <string> using std::string; #include <GL/Utils/ObjModel.h> #include <GL/utils/ImageMap.h> #include <GL/Utils/MathFunctions.h> // Global Variable Declarations double currentEyePoint[3]; double movingEyePoint[3]; double lookAtPoint[3]; double upVector[3]; double radius; double currentTheta; // angle of Longitude double currentPhi; // angle of Latitude bool dragging; int startX; int startY; double percentChangeX; double percentChangeY; int deviceWindowWidth; int deviceWindowHeight; ObjModel *sphere; ObjModel *plane; ImageMap *skyMap; // Setting Paths to Resources string parentDirectory = "OpenGLTutorials"; string imageMapPath; string objModelPath; string sphereFilename = "sphere.obj"; string planeFilename = "f-16.obj"; string skyFilename = "sky.bmp"; void setPaths(string pathName) { if (pathName[0] == '/') { pathName = pathName.substr(10, pathName.length()); imageMapPath = pathName.substr(0,1) + ":/"; objModelPath = pathName.substr(0,1) + ":/"; pathName = pathName.substr(2, pathName.length()); } int position = pathName.find(parentDirectory, 0); pathName = pathName.substr(0, position+parentDirectory.length()); imageMapPath += pathName + "/Resources/ImageMaps/"; objModelPath += pathName + "/Resources/Wavefront/"; } void setLighting() { float spotLightPosition[] = {0.0, 2.0, 2.0, 1.0}; float spotLightDirection[] = {0.0, -1.0, -1.0, 1.0}; float spotLightColor[] = {0.4, 0.4, 0.4, 1.0}; glLightfv(GL_LIGHT1, GL_DIFFUSE, spotLightColor); glLightfv(GL_LIGHT1, GL_POSITION, spotLightPosition); glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, spotLightDirection); glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 20.0); glEnable(GL_LIGHT1); } void init() { glClearColor(0.0, 0.0, 0.0, 1.0); // Set Viewing Values and Projection Transform movingEyePoint[0] = 0.0; movingEyePoint[1] = 1.0; movingEyePoint[2] = 2.0; lookAtPoint[0] = 0.0; lookAtPoint[1] = 0.0; lookAtPoint[2] = 0.0; upVector[0] = 0.0; upVector[1] = 1.0; upVector[2] = 0.0; radius = sqrt(0.0*0.0 + 1.0*1.0 + 2.0*2.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, 1.0, 0.1, 100.0); dragging = false; // Set Texture Mapping glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); skyMap->setTexture(); setLighting(); glEnable(GL_DEPTH_TEST); } void reshape(int width, int height) { deviceWindowWidth = width; deviceWindowHeight = height; glViewport(0, 0, width, height); } void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Set Viewing Transform glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(movingEyePoint.getX(), movingEyePoint.getY(), movingEyePoint.getZ(), lookAtPoint.getX(), lookAtPoint.getY(), lookAtPoint.getZ(), upVector.getX(), upVector.getY(), upVector.getZ()); // Draw the Models glEnable(GL_LIGHTING); glPushMatrix(); glScaled(0.5, 0.5, 0.5); plane->drawModel(); glPopMatrix(); glDisable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glScaled(4.0, 4.0, 4.0); glRotated(180.0, 0.0, 1.0, 0.0); sphere->drawModel(); glPopMatrix(); glDisable(GL_TEXTURE_2D); glutSwapBuffers(); } void computeAngles() { double eyeVector[3]; double projectionVector[] = {currentEyePoint[0], 0.0, currentEyePoint[2]}; double normalizedVector[3]; // compute angle of longitude normalize(projectionVector, projectionVector); if (projectionVector[0] > 0.0) currentTheta = acos(projectionVector[2]); else currentTheta = -acos(projectionVector[2]); // compute angle of latitude normalize(currentEyePoint, eyeVector); currentPhi = acos(dotProduct(eyeVector, projectionVector)); } void update(float percentChangeTheta, float percentChangePhi) { // add to current angle of longitude a percentage of 2PI // and add to current angle of latitude a percentage of PI double theta = currentTheta + percentChangeTheta * PI * 2.0; double phi = currentPhi + percentChangePhi * PI; if (phi > (PI / 2.0)) phi = PI / 2.0; if (phi < (-PI / 2.0)) phi = -PI / 2.0; movingEyePoint[0] = radius * sin(theta) * cos(phi); movingEyePoint[1] = radius * sin(phi); movingEyePoint[2] = radius * cos(theta) * cos(phi); } void mouse(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON) if (state == GLUT_DOWN) { startX = x; startY = y; dragging = true; currentEyePoint[0] = movingEyePoint[0]; currentEyePoint[1] = movingEyePoint[1]; currentEyePoint[2] = movingEyePoint[2]; computeAngles(); } else if (button == GLUT_UP){ dragging = false; } } void mouseMotion(int x, int y) { if (dragging) { percentChangeX = ((double) (x - startX)) / deviceWindowWidth; percentChangeY = ((double) (y - startY)) / (double) deviceWindowHeight; update(percentChangeX, percentChangeY); glutPostRedisplay(); } } int main (int argc, char** argv) { // Opening Resources string pathName = argv[0]; setPaths(pathName); skyMap = new ImageMap(imageMapPath, skyFilename); plane = new ObjModel(objModelPath, planeFilename); sphere = new ObjModel(objModelPath, sphereFilename); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowPosition(0, 0); glutInitWindowSize(500, 500); int cgWorldWindowHandle = glutCreateWindow("Inside Sphere"); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMouseFunc(mouse); glutMotionFunc(mouseMotion); init(); glutMainLoop(); return 0; }