//Accurate 3D Modeling of Molecules //Ben Parr //Period 6 #include #include #include #include #define N 1000 double theta=90.0,phi=90.0,oldphi=90.0,MAX=3.0;//spherical coordinates of eye position double up=1.0,zoomangle=90.0; int xmouse=-1,ymouse=-1; int bondnum=0,atomnum=0;//number of bonds and atoms in model int w; double xDiff,yDiff,zDiff,tempHeight,otherDist,tempAngle;//used for bond/cylinder positioning double bradius=.05;//bond radius GLUquadricObj *quadratic; struct atom { double x,y,z;//location double radius; double red,green,blue;//color }; struct bond { int type;//single bond=1, double bond=2 struct atom * a; struct atom * b; }; struct atom Atoms[N]; struct bond Bonds[N]; void init() { //initialize quadratic for cylinders quadratic=gluNewQuadric(); gluQuadricNormals(quadratic, GLU_SMOOTH); //set background color to gray glClearColor(0.75, 0.75, 0.75, 0.0); //initialize lighting GLfloat shine[]= {50.0}; glMaterialfv(GL_FRONT, GL_SHININESS, shine); GLfloat lightPos[] = { 2.5f, 2.5f, 4.0f, 1.0f }; glLightfv(GL_LIGHT0, GL_POSITION, lightPos); glShadeModel(GL_SMOOTH); glEnable(GL_COLOR_MATERIAL); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); } double distance(double tempX,double tempY,double tempZ) { return sqrt(pow(tempX,2)+pow(tempY,2)+pow(tempZ,2)); } void changeView() { //reposition eye glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //convert spherical coordinates to cartesian coordinates double x=MAX*sin(phi*(M_PI/180.0))*cos(theta*(M_PI/180.0)); double y=MAX*sin(phi*(M_PI/180.0))*sin(theta*(M_PI/180.0)); double z=MAX*cos(phi*(M_PI/180.0)); gluLookAt(x,y,z,0.0,0.0,0.0,0.0,0.0,up); } void zoom() { /* * zooming funtion is created by * calling gluPerspecive with * a different angle */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(zoomangle,1.0,.01,100.0); } void mouse(int button, int state, int x, int y) { if(button==3)//mouse wheel up { //zoom in if(zoomangle>2.0) zoomangle-=1.0; zoom(); changeView(); glutPostRedisplay(); } else if(button==4)//mouse wheel down { //zoom out if(zoomangle<177.0) zoomangle+=1.0; zoom(); changeView(); glutPostRedisplay(); } else if(button==GLUT_LEFT_BUTTON&&state==GLUT_DOWN) { xmouse=x; ymouse=y; oldphi=phi; } else { xmouse=-1; ymouse=-1; } } void motion(int x,int y) { if(xmouse!=-1 && ymouse!=-1) { //update spherical coordinates theta+=(xmouse-x)/2.0; phi+=(ymouse-y)/2.0; //keep phi between -90.0 and 90.0 phi=((int)((phi+540.0)*10.0))%3600/10.0-180.0; if(phi*oldphi<0) { oldphi=phi; up=-up; } xmouse=x; ymouse=y; changeView(); glutPostRedisplay(); } } void display(void) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //draw atoms for(w=0;wx-Bonds[w].a->x; yDiff=Bonds[w].b->y-Bonds[w].a->y; zDiff=Bonds[w].b->z-Bonds[w].a->z; tempHeight=distance(xDiff,yDiff,zDiff); if(tempHeight>0.0 && (xDiff!=0.0 || yDiff!=0.0)) { glTranslatef(Bonds[w].a->x,Bonds[w].a->y,Bonds[w].a->z); glRotatef(acos(zDiff/tempHeight)*180.0/M_PI,0.0,1.0,0.0); otherDist=distance(xDiff,yDiff,0.0); tempAngle=acos(xDiff/otherDist)*180.0/M_PI; if(yDiff<0.0) tempAngle*=-1.0; glRotatef(tempAngle,-otherDist,0.0,zDiff); } else if(xDiff==0.0 && yDiff==0.0 && tempHeight>0.0) { if(zDiff>0.0) glTranslatef(Bonds[w].a->x,Bonds[w].a->y,Bonds[w].a->z); else glTranslatef(Bonds[w].b->x,Bonds[w].b->y,Bonds[w].b->z); } gluCylinder(quadratic,bradius,bradius,tempHeight,50,50); glPopMatrix(); } //draw axis glBegin(GL_LINES); glColor3f(0.0,0.0,0.0); glVertex3f(1.,0.0,0.0); glVertex3f(-1.,0.0,0.0); glVertex3f(0.0,1.,0.0); glVertex3f(0.0,-1.,0.0); glVertex3f(0.0,0.0,1.); glVertex3f(0.0,0.0,-1.); glEnd(); glutSwapBuffers(); } void addAtom(double tempX,double tempY,double tempZ,double tempRadius,double tempRed,double tempGreen,double tempBlue) { struct atom tempAtom; tempAtom.x=tempX; tempAtom.y=tempY; tempAtom.z=tempZ; tempAtom.radius=tempRadius; tempAtom.red=tempRed; tempAtom.green=tempGreen; tempAtom.blue=tempBlue; Atoms[atomnum]=tempAtom; atomnum++; } void addBond(int tempType,int tempAtom1,int tempAtom2) { struct bond tempBond; tempBond.type=tempType; tempBond.a=&Atoms[tempAtom1]; tempBond.b=&Atoms[tempAtom2]; Bonds[bondnum]=tempBond; bondnum++; } void createFirstMol() { //create a methane molecule addAtom(0.0,0.0,0.0,.3,1.0,0.0,0.0); addAtom(.8,0.5,-.6,.2,0.0,0.0,1.0); addAtom(-.8,0.5,-.6,.2,0.0,0.0,1.0); addAtom(0.0,0.5,1.0,.2,0.0,0.0,1.0); addAtom(0.0,-1.1,0.0,.2,0.0,0.0,1.0); addBond(1,0,1); addBond(1,0,2); addBond(1,0,3); addBond(1,0,4); } int main(int argc,char** argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH); glutInitWindowSize(600,600); glutInitWindowPosition(50,50); glutCreateWindow("3D Model"); init(); createFirstMol(); zoom(); changeView(); glutDisplayFunc(display); glutMouseFunc(mouse); glutMotionFunc(motion); glutMainLoop(); return 0; }