2 * CITS2231 Graphics Scene Editor
\r
3 * @author Ashley Tyndall (20915779), Jenna de la Harpe (20367932)
\r
12 #include <GL/glut.h>
\r
16 #include "globals.h"
\r
22 * Event hander for main menu events
\r
23 * @param id ID of menu item selected
\r
25 void processMainEvents(int id) {
\r
27 case M_ROTATE_MOVE_CAMERA:
\r
28 manipulateState = STATE_CAMERA_ROTATE_MOVE;
\r
30 case M_POSITION_SCALE:
\r
31 manipulateState = STATE_OBJECT_POSITION_SCALE;
\r
33 case M_ROTATION_TEXTURE_SCALE:
\r
34 manipulateState = STATE_OBJECT_ROTATION_TEXTURE_SCALE;
\r
43 * Event hander for materials menu events
\r
44 * @param id ID of menu item selected
\r
46 void processMaterialEvents(int id) {
\r
48 case M_MATERIAL_ALL_RGB:
\r
52 case M_MATERIAL_AMBIENT_RGB:
\r
56 case M_MATERIAL_DIFFUSE_RGB:
\r
60 case M_MATERIAL_SPECULAR_RGB:
\r
64 case M_MATERIAL_ALL_ADSS:
\r
68 case M_MATERIAL_RED_ADSS:
\r
72 case M_MATERIAL_GREEN_ADSS:
\r
76 case M_MATERIAL_BLUE_ADSS:
\r
84 * Event hander for light menu events
\r
85 * @param id ID of menu item selected
\r
87 void processLightEvents(int id) {
\r
89 case M_LIGHT_MOVE_LIGHT_1:
\r
90 manipulateState = STATE_LIGHT_1_MOVE;
\r
93 case M_LIGHT_RGBALL_LIGHT_1:
\r
97 case M_LIGHT_MOVE_LIGHT_2:
\r
98 manipulateState = STATE_LIGHT_2_MOVE;
\r
101 case M_LIGHT_RGBALL_LIGHT_2:
\r
109 * Event hander for object menu events
\r
110 * @param id ID of object selected
\r
112 void processObjectEvents(int id) {
\r
113 addSceneObject(id);
\r
114 manipulateState = STATE_OBJECT_POSITION_SCALE;
\r
115 glutPostRedisplay();
\r
119 * Event hander for texture menu events
\r
120 * @param id ID of texutre selected
\r
122 void processTextureEvents(int id) {
\r
123 if ( curObject >= 0 ) {
\r
124 sceneObjs[curObject].texture.id = id;
\r
125 sceneObjs[curObject].texture.scale = 1;
\r
126 glutPostRedisplay();
\r
131 * Event hander for ground texture menu events
\r
132 * @param id ID of ground texture selected
\r
134 void processGTextureEvents(int id) {
\r
135 currentGroundTexture = id;
\r
136 glutPostRedisplay();
\r
140 * Creates menu for program
\r
143 // Construct material menu
\r
144 int materialMenu = glutCreateMenu(processMaterialEvents);
\r
145 glutAddMenuEntry("All R/G/B", M_MATERIAL_ALL_RGB);
\r
146 glutAddMenuEntry("Ambient R/G/B", M_MATERIAL_AMBIENT_RGB);
\r
147 glutAddMenuEntry("Diffuse R/G/B", M_MATERIAL_DIFFUSE_RGB);
\r
148 glutAddMenuEntry("Specular R/G/B", M_MATERIAL_SPECULAR_RGB);
\r
149 glutAddMenuEntry("All Amb/Diff/Spec/Shine", M_MATERIAL_ALL_ADSS);
\r
150 glutAddMenuEntry("Red Amb/Diff/Spec/Shine", M_MATERIAL_RED_ADSS);
\r
151 glutAddMenuEntry("Green Amb/Diff/Spec/Shine", M_MATERIAL_GREEN_ADSS);
\r
152 glutAddMenuEntry("Blue Amb/Diff/Spec/Shine", M_MATERIAL_BLUE_ADSS);
\r
154 // Construct light menu
\r
155 int lightMenu = glutCreateMenu(processLightEvents);
\r
156 glutAddMenuEntry("Move Light 1", M_LIGHT_MOVE_LIGHT_1);
\r
157 //glutAddMenuEntry("R/G/B/All Light 1", M_LIGHT_RGBALL_LIGHT_1);
\r
158 glutAddMenuEntry("Move Light 2", M_LIGHT_MOVE_LIGHT_2);
\r
159 //glutAddMenuEntry("R/G/B/All Light 2", M_LIGHT_RGBALL_LIGHT_2);
\r
161 // Construct object menu
\r
162 int objectMenu = makeSubmenuFromArray( objectMenuEntries, NMESH, processObjectEvents );
\r
164 // Construct texture / ground texture menus
\r
165 int textureMenu = makeSubmenuFromArray( textureMenuEntries, NTEXTURE, processTextureEvents );
\r
166 int gTextureMenu = makeSubmenuFromArray( textureMenuEntries, NTEXTURE, processGTextureEvents );
\r
168 // Construct main menu
\r
169 glutCreateMenu(processMainEvents);
\r
170 glutAddMenuEntry("Rotate/Move Camera", M_ROTATE_MOVE_CAMERA);
\r
171 glutAddSubMenu("Add object", objectMenu);
\r
172 glutAddMenuEntry("Position/Scale", M_POSITION_SCALE);
\r
173 glutAddMenuEntry("Rotation/Texture Scale", M_ROTATION_TEXTURE_SCALE);
\r
174 //glutAddSubMenu("Material", materialMenu);
\r
175 glutAddSubMenu("Texture", textureMenu);
\r
176 glutAddSubMenu("Ground texture", gTextureMenu);
\r
177 glutAddSubMenu("Lights", lightMenu);
\r
178 glutAddMenuEntry("Exit", M_EXIT);
\r
180 // Bind to right mouse button
\r
181 glutAttachMenu(GLUT_RIGHT_BUTTON);
\r
185 * Called when window is resized
\r
186 * @param w New width
\r
187 * @param h New height
\r
189 void windowReshape(int w, int h) {
\r
190 glViewport(0, 0, (GLsizei) w, (GLsizei) h);
\r
196 * Called when mouse event occurs
\r
197 * @param btn Mouse button
\r
198 * @param state State of mouse button
\r
199 * @param x Mouse x position
\r
200 * @param y Mouse y position
\r
202 void mouse(int button, int state, int x, int y) {
\r
203 if ( button == GLUT_LEFT_BUTTON && glutGetModifiers() == GLUT_ACTIVE_SHIFT ) {
\r
204 button = GLUT_MIDDLE_BUTTON; // Holding shift with left button is the same as the middle button
\r
207 case GLUT_LEFT_BUTTON:
\r
208 case GLUT_MIDDLE_BUTTON:
\r
209 if ( state == GLUT_DOWN ) {
\r
210 buttonSelected = button;
\r
211 } else if ( state == GLUT_UP ) {
\r
212 buttonSelected = -1;
\r
221 * Called when motion event occurs
\r
222 * @param x Mouse x position
\r
223 * @param y Mouse y position
\r
225 void motion(int x, int y) {
\r
226 if ( buttonSelected == -1 ) return; // No button selected, no action
\r
228 float diffx = x - startx;
\r
229 float diffy = y - starty;
\r
231 switch ( manipulateState ) {
\r
232 case STATE_CAMERA_ROTATE_MOVE:
\r
236 if ( buttonSelected == GLUT_LEFT_BUTTON ) {
\r
239 } else if ( buttonSelected == GLUT_MIDDLE_BUTTON ) {
\r
245 case STATE_OBJECT_POSITION_SCALE:
\r
247 if ( buttonSelected == GLUT_LEFT_BUTTON ) {
\r
248 // w: left/right, h: near/far
\r
249 float angler = 2 * M_PI * ( (rotate*camRotateFactor)/360.0 );
\r
250 sceneObjs[curObject].x += diffx * cos(angler) * leftrightFactor + diffy * cos(M_PI/2 + angler) * nearfarFactor;
\r
251 sceneObjs[curObject].z += diffx * sin(angler) * leftrightFactor + diffy * sin(M_PI/2 + angler) * nearfarFactor;
\r
253 } else if ( buttonSelected == GLUT_MIDDLE_BUTTON ) {
\r
255 float max = (float)height/bigsmallFactor;
\r
256 float scaling = (diffx + max) / max;
\r
258 sceneObjs[curObject].scale[0] *= scaling;
\r
259 sceneObjs[curObject].scale[1] *= scaling;
\r
260 sceneObjs[curObject].scale[2] *= scaling;
\r
263 sceneObjs[curObject].y -= diffy * updownFactor;
\r
268 case STATE_OBJECT_ROTATION_TEXTURE_SCALE:
\r
270 if ( buttonSelected == GLUT_LEFT_BUTTON ) {
\r
272 sceneObjs[curObject].rotation.y += diffx * rotateFactor;
\r
275 sceneObjs[curObject].rotation.x += diffy * rotateFactor;
\r
277 } else if ( buttonSelected == GLUT_MIDDLE_BUTTON ) {
\r
279 sceneObjs[curObject].rotation.x += diffx * rotateFactor;
\r
281 // h: texture scale
\r
282 // **NOTE: Seems to be problem with scaling, delayed action
\r
283 float max = (float)height/texscaleFactor;
\r
284 float scaling = (-diffy + max) / max;
\r
285 sceneObjs[curObject].texture.scale *= scaling;
\r
291 case STATE_LIGHT_1_MOVE:
\r
292 case STATE_LIGHT_2_MOVE:
\r
293 ; // Semi-colon required to allow variable declaration below
\r
296 if ( manipulateState == STATE_LIGHT_2_MOVE ) i = 1;
\r
298 if ( buttonSelected == GLUT_LEFT_BUTTON ) {
\r
299 // w: left/right, h: near/far
\r
300 float angler = 2 * M_PI * ( (rotate*camRotateFactor)/360.0 );
\r
301 lightObjs[i].position[0] += diffx * cos(angler) * lleftrightFactor + diffy * cos(M_PI/2 + angler) * lnearfarFactor;
\r
302 lightObjs[i].position[2] += diffx * sin(angler) * lleftrightFactor + diffy * sin(M_PI/2 + angler) * lnearfarFactor;
\r
304 } else if ( buttonSelected == GLUT_MIDDLE_BUTTON ) {
\r
305 // w: increase/decrease some light param
\r
306 // **NOTE: Currently not implemented
\r
309 lightObjs[i].position[1] -= diffy * updownFactor;
\r
319 glutPostRedisplay();
\r
326 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
\r
328 // Redraw projection matrix
\r
329 glMatrixMode(GL_PROJECTION);
\r
333 if ( width <= height ) {
\r
334 aspect = (float)height / (float)width;
\r
336 aspect = (float)width / (float)height;
\r
346 glMatrixMode(GL_MODELVIEW);
\r
350 0.0, 0.0, 15.0 + (zoom*zoomFactor), /* eye is at (x,y,z) */
\r
351 0.0, 0.0, 0.0, /* center is at (x,y,z) */
\r
352 0.0, 10.0, 0.0 /* up is in postivie Y direction */
\r
355 glRotatef(camAngle*camAngleFactor, 1.0, 0.0, 0.0); // Set camera angle upward
\r
359 /* Perform scene rotations based on user mouse input. */
\r
360 glRotatef(rotate*camRotateFactor, 0.0, 1.0, 0.0);
\r
364 // Draw sceneObjs array
\r
365 for ( int i = 0; i < nObjects; i++ ) {
\r
367 SceneObject so = sceneObjs[i];
\r
369 // Apply translation vector
\r
370 glTranslatef(so.x, so.y, so.z);
\r
372 // Apply independant rotation vectors
\r
373 glRotatef(so.rotation.x, 1.0, 0.0, 0.0);
\r
374 glRotatef(so.rotation.y, 0.0, 1.0, 0.0);
\r
375 glRotatef(so.rotation.z, 0.0, 0.0, 1.0);
\r
377 // Apply scaling vector
\r
378 glScalef(so.scale[0], so.scale[1], so.scale[2]);
\r
381 if ( so.texture.id > 0 ) {
\r
382 getTexture(so.texture.id);
\r
383 glBindTexture(GL_TEXTURE_2D, so.texture.id);
\r
384 glMatrixMode(GL_TEXTURE);
\r
385 glScalef(so.texture.scale, so.texture.scale, so.texture.scale);
\r
386 glMatrixMode(GL_MODELVIEW);
\r
388 glBindTexture(GL_TEXTURE_2D, 0);
\r
391 // Draw actual object
\r
392 if ( so.mesh > 0 ) {
\r
394 } else if ( so.mesh == -1 ) { // a mesh of -1 draws the teapot
\r
395 // The teapot does not obey the right-hand rule
\r
396 glFrontFace(GL_CW);
\r
397 glutSolidTeapot(1);
\r
398 glFrontFace(GL_CCW);
\r
401 glBindTexture(GL_TEXTURE_2D, 0);
\r
416 * @param argc Number of arguments
\r
417 * @param argv Array of arguments
\r
418 * @return Program exit code
\r
420 int main(int argc, char **argv) {
\r
422 strcpy(dataDir, argv[1]);
\r
423 else if(opendir(dirDefault1))
\r
424 strcpy(dataDir, dirDefault1);
\r
425 else if(opendir(dirDefault2))
\r
426 strcpy(dataDir, dirDefault2);
\r
427 else fileErr(dirDefault1);
\r
429 for(int i=0; i<NMESH; i++) meshes[i]=NULL;
\r
430 for(int i=0; i<NTEXTURE; i++) textures[i]=NULL;
\r
432 glutInit(&argc, argv);
\r
434 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
\r
436 glutInitWindowSize(width, height);
\r
437 glutCreateWindow("Scene Editor - Ashley Tyndall (20915779), Jenna de la Harpe (20367932)");
\r
439 glShadeModel(GL_SMOOTH); // Enables Smooth Shading
\r
440 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black Background
\r
441 glClearDepth(1.0f); // Depth Buffer Setup
\r
443 glEnable(GL_DEPTH_TEST); // Enables Depth Testing
\r
444 glDepthFunc(GL_LEQUAL); // the type
\r
445 //glEnable(GL_CULL_FACE);
\r
448 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
\r
450 glutReshapeFunc(windowReshape);
\r
451 glutDisplayFunc(display);
\r
452 glutMouseFunc(mouse);
\r
453 glutMotionFunc(motion);
\r
456 initializeLights();
\r