#include #include #include #include #include "ToolBar.h" #include "Project4.h" #include "Cubes.h" #include "Tetrahedron.h" #include "Camera.h" #include "Light.h" // the height for tool bar const int m_BarHeight=35; // Projection type GLfloat gAt[3][3]={{-1.0,0.0,0.0}, {0.0,-1.0,0.0},{0.0,0.0,-1.0}}; GLfloat gUp[3][3]={{0.0,1.0,0.0},{1.0,0.0,0.0},{0.0,1.0,0.0}}; int m_Direction; unsigned char *m_pProj[3]= {(unsigned char *) "Proj:+X ", (unsigned char *) "Proj:+Y ", (unsigned char *) "Proj:+Z "}; //Shade -FLAT -SMOOTH int m_Shading; unsigned char *m_pShade[2]={(unsigned char *) "Shade:flat ",(unsigned char *) "Shade:smooth "}; //Light type unsigned char *m_pLight[3]={(unsigned char *) "Light:point ",(unsigned char *) "Light:Direction",(unsigned char *) "Light:spot "}; // The width and height of windows int m_width, m_height; int m_CenterX, m_CenterY; //In screen coordinate: left=0, top=0; In Glut coordinate: left=0,bottom=0 const float m_OrthoWidth=8.0; float m_VectFactorX=16.0/256; // is used to calculate m_TVector,m_Scalor, 256 is the width of viewport float m_VectFactorY=16.0/256; float m_RotateFactor=360/256;// is used to calculate m_Theta // the position when mouse button is pressed int m_xp0, m_yp0, m_zp0; CObjectInScene *m_pObj[MAXOBJS]; int m_objects=4; CCubes m_Cube; CTetrahedron m_Triangle; CCamera m_Camera; CLight m_Light; // Is changing position or rotating or scaling int m_IsChanging=0; //int m_ShowCube=0,m_ShowTriangle=0; //Temporary Vector,angle,scalor for translate, rotate,scale when drag mouse GLfloat m_TVector[3]; GLfloat m_RVector[3]; GLfloat m_Theta; GLfloat m_Scalor[3]; // GLint m_MouseButton; // Position for button box int m_Cube_X0,m_Cube_Y0,m_Cube_X1,m_Cube_Y1; int m_Triangle_X0,m_Triangle_Y0,m_Triangle_X1,m_Triangle_Y1; int m_Menu_X0,m_Menu_Y0,m_Menu_X1,m_Menu_Y1; bool m_ShowMenu; //true-right click to product menu // the selected object int m_ObjSel ; // FILE *fp; void create_Menu(void); //Init matix for cube and triangle void myinit(void){ // Initiate the selected object int i; m_ObjSel=TRIANGLE; for(i=0;i<3;i++){ m_Scalor[i]=1.0;} m_MouseButton=-1; m_pObj[CUBE]=&m_Cube; m_pObj[TRIANGLE]=&m_Triangle; m_pObj[CAMERA]=&m_Camera; m_pObj[LIGHT]=&m_Light; m_objects=4; fp=fopen("scene","r"); if (fp==NULL) {printf("file not exist.");} else { for(i=0;ireadProperty(fp); } fclose(fp); printf("read scene success!\n"); } //for three standard orthographic projections m_Direction=ZAXIS; m_ShowMenu=false; } void myOrtho(int w, int h){ float wid,hei; if (w <= h) { wid=m_OrthoWidth; hei=m_OrthoWidth * (GLfloat) h / (GLfloat)w; } else { wid=m_OrthoWidth * (GLfloat) w / (GLfloat) h; hei=m_OrthoWidth ; } glOrtho(-wid,wid, -hei, hei, -5.0*m_OrthoWidth, 5.0*m_OrthoWidth); m_VectFactorX=wid*2/w; m_VectFactorY=hei*2/h; } void initOrtho(int w, int h){ glMatrixMode(GL_PROJECTION); glLoadIdentity(); myOrtho(w,h); glMatrixMode(GL_MODELVIEW); } void myReshape(int w, int h) { m_width=w/2; m_CenterX=m_width/2; m_RotateFactor=(float)360/m_width; if (h>m_BarHeight) { m_height=h; m_CenterY=(m_height-m_BarHeight)/2; } } // draw the tool bar void drawToolBar(){ int x,y; bool v; unsigned char *str1=(unsigned char *) "Cube"; unsigned char *str2=(unsigned char *)"Triangle"; unsigned char *str3=(unsigned char *)"Menu"; CLight *p; glPushAttrib(GL_ALL_ATTRIB_BITS); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, (GLdouble)m_width*2, 0.0, (GLdouble) m_height , -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); x=4; y=10; glViewport(0, 0,m_width*2,m_height); m_Cube_Y0=2; m_Triangle_Y0=2; m_Menu_Y0=2; //produce button for CUBE m_Cube_X0=x; v=m_pObj[CUBE]->isVisible(); if(v) glColor3fv(highlightFontColor); else glColor3fv(normalFontColor); x+=4; draw_string(str1,&x,&y); m_Cube_X1=x+4; m_Cube_Y1=m_BarHeight-2; if(v){ glColor3fv(highlightToolboxColor); screen_box(m_Cube_X0+2,m_Cube_Y0+2,m_Cube_X1-2,m_Cube_Y1-2); } glColor3fv(normalToolboxColor); screen_box(m_Cube_X0,m_Cube_Y0,m_Cube_X1,m_Cube_Y1); //produce button for Triangle x+=8; m_Triangle_X0=x; v=m_pObj[TRIANGLE]->isVisible(); if(v) glColor3fv(highlightFontColor); else glColor3fv(normalFontColor); x+=4; draw_string(str2,&x,&y); m_Triangle_X1=x+4; m_Triangle_Y1=m_BarHeight-2; if (v){ glColor3fv(highlightToolboxColor); screen_box(m_Triangle_X0+2,m_Triangle_Y0+2,m_Triangle_X1-2,m_Triangle_Y1-2); } glColor3fv(normalToolboxColor); screen_box(m_Triangle_X0,m_Triangle_Y0,m_Triangle_X1,m_Triangle_Y1); //produce button for Menu x+=8; m_Menu_X0=x; v=m_ShowMenu; if(v) glColor3fv(highlightFontColor); else glColor3fv(normalFontColor); x+=4; draw_string(str3,&x,&y); m_Menu_X1=x+4; m_Menu_Y1=m_BarHeight-2; if (v){ glColor3fv(highlightToolboxColor); screen_box(m_Menu_X0+2,m_Menu_Y0+2,m_Menu_X1-2,m_Menu_Y1-2); } glColor3fv(normalToolboxColor); screen_box(m_Menu_X0,m_Menu_Y0,m_Menu_X1,m_Menu_Y1); //show status: x+=8; draw_string(m_pProj[m_Direction],&x,&y); x+=8; p=(CLight *) m_pObj[LIGHT]; draw_string(m_pLight[p->LightType],&x,&y); x+=8; draw_string(m_pShade[(m_Shading==GL_FLAT)? 0:1],&x,&y); //produce frame glColor3fv(highlightToolboxColor); glBegin(GL_LINE_STRIP); glVertex2i(1, m_BarHeight); glVertex2i(m_width*2-1, m_BarHeight); glVertex2i(m_width*2-1, m_height-1); glVertex2i(1, m_height-1); glVertex2i(1, m_BarHeight); glEnd(); glBegin(GL_LINES); glVertex2i(m_width,m_BarHeight); glVertex2i(m_width,m_height-1); glEnd(); glPopAttrib(); } void drawViewport(GLenum mode){ //set viewport int w,h,i; CObjectInScene *p; w=m_width; h=m_height-m_BarHeight; if (mode == GL_RENDER){ // glPushAttrib(GL_ALL_ATTRIB_BITS); glViewport(1, m_BarHeight+1, w-1, h-1); glMatrixMode(GL_PROJECTION); glLoadIdentity(); initOrtho(w,h); } glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0,0.0,0.0,gAt[m_Direction][0],gAt[m_Direction][1],gAt[m_Direction][2],gUp[m_Direction][0],gUp[m_Direction][1],gUp[m_Direction][2]); if (mode == GL_RENDER){ glBegin(GL_LINES); glColor3f(1.0, 0.0, 0.0); glVertex3d(0.0, 0.0, 0.0); glVertex3d(m_OrthoWidth, 0.0, 0.0); glColor3f(0.0, 1.0, 0.0); glVertex3d(0.0, 0.0, 0.0); glVertex3d(0.0, m_OrthoWidth, 0.0); glColor3f(0.0, 0.0, 1.0); glVertex3d(0.0, 0.0, 0.0); glVertex3d(0.0, 0.0, m_OrthoWidth); glEnd(); } for(i=0;iisVisible()){ if (mode == GL_SELECT) glLoadName(i+1); // load cube's matrix to the modelview matrix glLoadIdentity(); gluLookAt(0.0,0.0,0.0,gAt[m_Direction][0],gAt[m_Direction][1],gAt[m_Direction][2], gUp[m_Direction][0],gUp[m_Direction][1],gUp[m_Direction][2]); if(m_ObjSel==i) glTranslatef(m_TVector[0], m_TVector[1], m_TVector[2]); glMultMatrixf(p->TMatrix); if(m_ObjSel==i) glScalef(m_Scalor[0],m_Scalor[1],m_Scalor[2]); glMultMatrixf(p->SMatrix); if(m_ObjSel==i) glRotatef(m_Theta, m_RVector[0], m_RVector[1], m_RVector[2]); glMultMatrixf(p->RMatrix); p->render(); } } // if (mode == GL_RENDER) glPopAttrib(); } void drawCameraViewport(void){ int w,h,i; CObjectInScene *p; CCamera *p_Camera; CLight *p_Light; CGeometry *p_Geometry; GLfloat Eye[3],At[3],Up[3]; float asp; w=m_width-2; h=m_height-m_BarHeight-2; asp=w/h; glPushAttrib(GL_ALL_ATTRIB_BITS); glShadeModel(m_Shading); glViewport(w+1, m_BarHeight+1, w, h); p_Camera=(CCamera *)m_pObj[CAMERA]; p_Light=(CLight *)m_pObj[LIGHT]; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(p_Camera->Fov,asp,p_Camera->Near,p_Camera->Far); glMatrixMode(GL_MODELVIEW); for(i=0;i<3;i++){ Eye[i]=p_Camera->TMatrix[12+i]; At[i]=p_Camera->At[i]; Up[i]=p_Camera->Up[i]; } //draw coordinates glLoadIdentity(); gluLookAt(Eye[0],Eye[1],Eye[2],At[0],At[1],At[2],Up[0],Up[1],Up[2]); glBegin(GL_LINES); glColor3f(1.0, 0.0, 0.0); glVertex3d(0.0, 0.0, 0.0); glVertex3d(m_OrthoWidth, 0.0, 0.0); glColor3f(0.0, 1.0, 0.0); glVertex3d(0.0, 0.0, 0.0); glVertex3d(0.0, m_OrthoWidth, 0.0); glColor3f(0.0, 0.0, 1.0); glVertex3d(0.0, 0.0, 0.0); glVertex3d(0.0, 0.0, m_OrthoWidth); glEnd(); //set up light glLoadIdentity(); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); switch(p_Light->LightType){ case POINT: p_Light->PosOrDir[3]=1.0; glLightfv(GL_LIGHT0,GL_POSITION,p_Light->PosOrDir); break; case DIRECTION: p_Light->PosOrDir[3]=0.0; glLightfv(GL_LIGHT0,GL_POSITION,p_Light->PosOrDir); break; case SPOTLIGHT: glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION,p_Light->PosOrDir); glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, p_Light->Exponent); glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, p_Light->SpotCutOff); break; } glLightfv(GL_LIGHT0,GL_DIFFUSE,p_Light->Diffuse); glLightfv(GL_LIGHT0,GL_SPECULAR,p_Light->Specular); glLightf(GL_LIGHT0,GL_CONSTANT_ATTENUATION,p_Light->Attenuation); glLightModelfv(GL_LIGHT_MODEL_AMBIENT,p_Light->Ambient); //draw Geometry for(i=CUBE;iisVisible()){ glLoadIdentity(); gluLookAt(Eye[0],Eye[1],Eye[2],At[0],At[1],At[2],Up[0],Up[1],Up[2]); p_Geometry=(CGeometry *)p; glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,p_Geometry->Ambient); glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,p_Geometry->Diffuse); glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,p_Geometry->Specular); if(m_ObjSel==i) glTranslatef(m_TVector[0], m_TVector[1], m_TVector[2]); glMultMatrixf(p->TMatrix); if(m_ObjSel==i) glScalef(m_Scalor[0],m_Scalor[1],m_Scalor[2]); glMultMatrixf(p->SMatrix); if(m_ObjSel==i) glRotatef(m_Theta, m_RVector[0], m_RVector[1], m_RVector[2]); glMultMatrixf(p->RMatrix); p->renderSolid(); } } glPopAttrib(); } void display(void) { // Clear the RGB buffer and the depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Draw Tool bar drawToolBar(); // Draw Edit Scene drawViewport(GL_RENDER); //draw camera Viewport drawCameraViewport(); // Flush the buffer to force drawing of all objects thus far glFlush(); glutSwapBuffers(); } int pickButton(int x, int y){ if(y m_Cube_X0 && x < m_Cube_X1) return CUBE; else if(x >m_Triangle_X0 && xm_Menu_X0 && xsetSelected(false); m_ObjSel=tmp; m_pObj[m_ObjSel]->setSelected(true); } }else if (btn==GLUT_MIDDLE_BUTTON){ if (tmp!=m_ObjSel){ rt=1; } if(m_ObjSel!=NONE) m_pObj[m_ObjSel]->setSelected(false); m_ObjSel=tmp; if(m_ObjSel!=NONE) m_pObj[m_ObjSel]->setSelected(true); } return rt; } void mouse(int btn, int state, int x, int y) { static int changed; // need redisplay int i; // float xp, yp; CObjectInScene *p; if(m_MouseButton==NONE && state==GLUT_DOWN) m_MouseButton=btn; //select the first pressed button, changed=0; switch(btn){ case GLUT_LEFT_BUTTON: //Rotate and select object if(m_MouseButton!=GLUT_LEFT_BUTTON) break; if(state==GLUT_UP){ m_MouseButton=NONE; if(y> m_height-m_BarHeight) break; // if select object if(m_IsChanging && m_ObjSel!=NONE){ m_IsChanging=0; //Produce the Rotate matrix glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glRotatef(m_Theta, m_RVector[0], m_RVector[1], m_RVector[2]); glMultMatrixf(m_pObj[m_ObjSel]->RMatrix); glGetFloatv( GL_MODELVIEW_MATRIX, m_pObj[m_ObjSel]->RMatrix); changed=1; } m_RVector[0]=0.0; m_RVector[1]=0.0; m_RVector[2]=0.0; m_Theta=0.0; } else{ if (y>m_height-m_BarHeight){ //in tool bar area and GLUT_DOWN i=pickButton(x,y); if(i!=NONE) { p=m_pObj[i]; p->changeVisible(); if (p->isVisible()){ p->setSelected(true); // p->initMatrix(); if (m_ObjSel!=NONE) m_pObj[m_ObjSel]->setSelected(false); m_ObjSel=i; } else if (p->isSelected()){ m_ObjSel=NONE; p->setSelected(false); } changed=1; } } else{ // in object area m_xp0=x; m_yp0=y; m_zp0=0.0; changed=pickObject(btn,x,y); } } break; case GLUT_MIDDLE_BUTTON://Translate if(m_MouseButton!=GLUT_MIDDLE_BUTTON ) break; if(state==GLUT_UP){ m_MouseButton=NONE; if(y> m_height-m_BarHeight|| m_ObjSel==NONE) break; // if select object if(m_IsChanging){ m_IsChanging=0; //Produce the translate matrix glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(m_TVector[0], m_TVector[1], m_TVector[2]); glMultMatrixf(m_pObj[m_ObjSel]->TMatrix); glGetFloatv( GL_MODELVIEW_MATRIX, m_pObj[m_ObjSel]->TMatrix); changed=1; }; m_TVector[0]=0.0; m_TVector[1]=0.0; m_TVector[2]=0.0; } else if (y m_height-m_BarHeight|| m_ObjSel==NONE) break; if(m_IsChanging){ m_IsChanging=0; if(m_xp0==x && m_yp0==y) break; // mouse didn't move //Calculate Scalor p=m_pObj[m_ObjSel]; //Produce the translate matrix glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glScalef(m_Scalor[0], m_Scalor[1], m_Scalor[2]); glMultMatrixf(p->SMatrix); glGetFloatv( GL_MODELVIEW_MATRIX, p->SMatrix); changed=1; } m_Scalor[0]=1.0; m_Scalor[1]=1.0; m_Scalor[2]=1.0; }else if (ym_height-m_BarHeight|| y<0 ||x>m_width||x<0) { x=(x<0)?0:x; x=(x>m_width)?m_width:x; y=(y<0)?0:y; y=(y>m_height-m_BarHeight)?m_height-m_BarHeight:y; mouse(m_MouseButton, GLUT_UP, x, y); m_MouseButton=NONE; return; } m_IsChanging=1; switch(m_MouseButton){ case GLUT_LEFT_BUTTON: //Rotate if(m_ObjSelTRIANGLE) return; switch(m_Direction){ case ZAXIS: m_RVector[0]=(y-m_yp0)*m_VectFactorX; m_RVector[1]=(x-m_xp0)*m_VectFactorY; m_RVector[2]=0.0; break; case XAXIS: m_RVector[0]=0.0; m_RVector[1]=(x-m_xp0)*m_VectFactorY; m_RVector[2]=(m_yp0-y)*m_VectFactorX; break; case YAXIS: m_RVector[0]=(x-m_xp0)*m_VectFactorY; m_RVector[1]=0.0; m_RVector[2]=(y-m_yp0)*m_VectFactorX; break; } //*m_RotateFactor; m_Theta=(float)sqrt(pow(y-m_yp0,2)+pow(x-m_xp0,2)); break; case GLUT_MIDDLE_BUTTON: //Translate switch(m_Direction){ case ZAXIS: m_TVector[0]=(x-m_xp0)*m_VectFactorX; m_TVector[1]=(m_yp0-y)*m_VectFactorY; m_TVector[2]=0.0; break; case XAXIS: m_TVector[0]=0.0; m_TVector[1]=(m_yp0-y)*m_VectFactorY; m_TVector[2]=(m_xp0-x)*m_VectFactorX; break; case YAXIS: m_TVector[0]=(m_yp0-y)*m_VectFactorY; m_TVector[1]=0.0; m_TVector[2]=(x-m_xp0)*m_VectFactorX; break; } break; case GLUT_RIGHT_BUTTON: //Scale if(m_ObjSel>NONE && m_ObjSelTMatrix[12]/m_VectFactorX; //Objects' center position m_Scalor[1]=(m_CenterY-y)-p->TMatrix[13]/m_VectFactorY; m_Scalor[2]=1.0; pos[0]=(m_xp0-m_CenterX)-p->TMatrix[12]/m_VectFactorX; pos[1]=(m_CenterY-m_yp0)-p->TMatrix[13]/m_VectFactorY; pos[2]=1.0; break; case XAXIS: m_Scalor[0]=1.0; m_Scalor[1]=(m_CenterY-y)-p->TMatrix[13]/m_VectFactorY; m_Scalor[2]=(m_CenterX-x)-p->TMatrix[12]/m_VectFactorX; pos[0]=1.0; pos[1]=(m_CenterY-m_yp0)-p->TMatrix[13]/m_VectFactorY; pos[2]=(m_CenterX-m_xp0)-p->TMatrix[12]/m_VectFactorX; break; case YAXIS: m_Scalor[0]=(m_CenterY-y)-p->TMatrix[13]/m_VectFactorY; m_Scalor[1]=1.0; m_Scalor[2]=(x-m_CenterX)-p->TMatrix[12]/m_VectFactorX; pos[0]=(m_CenterY-m_yp0)-p->TMatrix[13]/m_VectFactorY; pos[1]=1.0; pos[2]=(m_xp0-m_CenterX)-p->TMatrix[12]/m_VectFactorX; break; } for(i=0;i<3;i++){ if (pos[i]==0) m_Scalor[i]=1.0; else m_Scalor[i]=fabs(m_Scalor[i]/pos[i]); } } break; } glutPostRedisplay(); } void keys(unsigned char key, int x, int y){ int i; CObjectInScene *p; switch(key){ case 'x': case 'X': m_Direction=XAXIS; break; case 'y': case 'Y': m_Direction=YAXIS; break; case 'z': case 'Z': m_Direction=ZAXIS; break; case 's': case 'S': fp=fopen("scene","w"); if (fp==NULL) {printf("error in saving scene."); return;} for(i=0;iwriteProperty(fp); } printf("save scene success!\n"); fclose(fp); break; case 'r': case 'R': fp=fopen("scene","r"); if (fp==NULL) {printf("file not exist."); return;} for(i=0;iisSelected()||m_ObjSel==NONE ) p->readProperty(fp); } fclose(fp); printf("read scene success!\n"); break; } glutPostRedisplay(); } void projection_menu(int d){ unsigned char key; switch (d){ case XAXIS: key='x'; break; case YAXIS: key='y'; break; case ZAXIS: key='z'; break; } keys(key,0,0); } void scene_menu(int d){ if (d==1)keys('r',0,0); else keys('s',0,0); } void light_menu(int d){ int i; i=d-1; CLight *p; p=(CLight *) m_pObj[LIGHT]; p->LightType=i; glutPostRedisplay(); } void shadow_menu(int d){ if (d==1) m_Shading=GL_FLAT; else m_Shading=GL_SMOOTH; glutPostRedisplay(); } void right_menu(int d){ } void create_Menu(){ int p_menu,s_menu,l_menu,d_menu; p_menu=glutCreateMenu(projection_menu); glutAddMenuEntry("+X",XAXIS); glutAddMenuEntry("+Y",YAXIS); glutAddMenuEntry("+Z",ZAXIS); s_menu=glutCreateMenu(scene_menu); glutAddMenuEntry("Read",1); glutAddMenuEntry("Save",2); l_menu=glutCreateMenu(light_menu); glutAddMenuEntry("Point",1); glutAddMenuEntry("Direction",2); glutAddMenuEntry("Spot",3); d_menu=glutCreateMenu(shadow_menu); glutAddMenuEntry("Flat",1); glutAddMenuEntry("Smooth",2); glutCreateMenu(right_menu); glutAddSubMenu("Projections",p_menu); glutAddSubMenu("Scene",s_menu); glutAddSubMenu("Light",l_menu); glutAddSubMenu("Shade",d_menu); glutAttachMenu(GLUT_RIGHT_BUTTON); } int main(int argc, char **argv) { // Set top left corner of window to be at location (0, 0) // Set the window size to be 512x256 pixels glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); m_width=256; m_height= 256+m_BarHeight; m_CenterX=128; m_CenterY=128; glutInitWindowSize(2*m_width, m_height); glutInitWindowPosition(100,100); glutCreateWindow("Project4 By Weirong Zhu"); myinit(); printf("Please use three button mouse\n"); glutReshapeFunc(myReshape); // Set the clear color to black glClearColor(0.0, 0.0, 0.0, 1.0); glutKeyboardFunc(keys); // Enable depth testing for hidden line removal glEnable(GL_DEPTH_TEST); // Assign display() to be the function called whenever a display // event occurs, generally after a resize or expose event glutDisplayFunc(display); glutMouseFunc (mouse); glutMotionFunc(motion); glutMainLoop(); }