Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <math.h>
- #include <stdio.h>
- #include <GL/glut.h>
- #include "GluCylinders.h"
- // There's no real need to comment includes.
- // What a include supplies normally is obvious from the file name
- void animate(float t, float&, float&, float&);
- void renderCylinder(float x1, float y1, float z1,
- float x2,float y2, float z2,
- float radius, int subdivisions,
- GLUquadricObj *quadric);
- void renderCylinder_convenient(float x1, float y1, float z1,
- float x2,float y2, float z2,
- float radius,int subdivisions);
- // The next global variable controls the animation's state and speed.
- float RotateAngle = 0.0f; // Angle in degrees of rotation around y-axis
- float Azimuth = 0.0; // Rotated up or down by this amount
- float AngleStepSize = 3.0f; // Step three degrees at a time
- const float AngleStepMax = 10.0f;
- const float AngleStepMin = 0.1f;
- int WireFrameOn = 1; // == 1 for wire frame mode
- //points
- // I would not call this geometry but control points...
- float Geometry[9][3] = {
- { 4,2.0,0},
- { 4,2.0,0}, // Point1
- {-1.5,0.2,0},
- {-2,0.3,0},
- {-2.5,0.6,0},
- {-3,0.8,0},
- {-3.5,1.0,0},
- { -5.5,1.8,0}, //point 2
- { -5.5,1.8,0}
- };
- int x2[5],y2[5],z2[5];
- // LOD? Level of Detail? Length of Delay?
- // This is a case where a comment makes sense: Explaining abbreviations.
- // unsigned int LOD=20;
- void myKeyboardFunc( unsigned char key, int x, int y )
- {
- switch ( key ) {
- case 'w':
- WireFrameOn = 1-WireFrameOn;
- glutPostRedisplay();
- break;
- case 'R':
- AngleStepSize *= 1.5;
- if (AngleStepSize>AngleStepMax ) {
- AngleStepSize = AngleStepMax;
- }
- break;
- case 'r':
- AngleStepSize /= 1.5;
- if (AngleStepSize<AngleStepMin ) {
- AngleStepSize = AngleStepMin;
- }
- break;
- case 27: // Escape key
- exit(1);
- }
- }
- // glutSpecialFunc is called below to set this function to handle
- // all "special" key presses. See glut.h for the names of
- // special keys.
- void mySpecialKeyFunc( int key, int x, int y )
- {
- switch ( key ) {
- case GLUT_KEY_UP:
- Azimuth += AngleStepSize;
- if ( Azimuth>80.0f ) {
- Azimuth = 80.0f;
- }
- break;
- case GLUT_KEY_DOWN:
- Azimuth -= AngleStepSize;
- if ( Azimuth < -80.0f ) {
- Azimuth = -80.0f;
- }
- break;
- case GLUT_KEY_LEFT:
- RotateAngle += AngleStepSize;
- if ( RotateAngle > 180.0f ) {
- RotateAngle -= 360.0f;
- }
- break;
- case GLUT_KEY_RIGHT:
- RotateAngle -= AngleStepSize;
- if ( RotateAngle < -180.0f ) {
- RotateAngle += 360.0f;
- }
- break;
- }
- glutPostRedisplay();
- }
- /*
- * drawScene() handles the animation and the redrawing of the
- * graphics window contents.
- */
- void drawScene(void)
- {
- // Those should not be a drawScene static, but part of
- // a scene management structure. Which your code lacks,
- // unfortunately, and I'm not gonna introduce one.
- static float animation_time = 0.;
- static int j = 1; // why 1 indexed? This is not Lua
- if ( WireFrameOn ) {
- glPolygonMode ( GL_FRONT_AND_BACK, GL_LINE ); // Just show wireframes
- } else {
- glPolygonMode ( GL_FRONT_AND_BACK, GL_FILL ); // Show solid polygons
- }
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glEnable(GL_DEPTH_TEST);
- glMatrixMode( GL_MODELVIEW );
- glLoadIdentity();
- glTranslatef( -0.5, 0.0, -35.0 );
- glRotatef( RotateAngle, 0.0, 1.0, 0.0 );
- glRotatef( Azimuth, 1.0, 0.0, 0.0 );
- // Please, don't /code/ your geometry, it's ugly and unmaintainable. I omit that code here
- // (...)
- // Okay, I can just guess here, but it looks like you're intending to draw
- // a trace of the sphere as it moves around. I have no idea what that j
- // loop is meant for, though. But I guess you want to show the control points,
- // one after another. This another case _FOR_ comments: Explaining the idea of
- // the overall scheme. Don't write in a comment what a single statement does. I
- // can see that from the statement.
- // use the parametric time value 0 to current animation time.
- float x3, y3, z3;
- // first draw the trace
- glBegin(GL_LINE_STRIP);
- for(float t = 0; t < animation_time; t+=0.05) {
- animate(t, x3, y3, z3);
- glVertex3f( x3,y3,z3 );
- }
- glEnd();
- // Then draw the control point markers
- glColor3f(1,1,0);
- for(float t = 0; t < animation_time; t+=0.05) {
- animate(t, x3, y3, z3);
- renderCylinder_convenient(
- Geometry[j][0],Geometry[j][1],Geometry[j][2],
- x3,y3,z3,
- 0.3, 32);
- }
- // Last but not least draw sphere at the position for animation_time.
- animate(animation_time, x3, y3, z3);
- glutDrawSphere(...);
- // now, we want to play that animation a few times in
- // succession, but with different control points visible
- // or so I presume so after each animation time has reached 1
- // we increment the control point counter. And after that hit
- // its maximum we stop advancing the animation
- if(j<3) {
- if(animation_time < 1.0) {
- // Animation step should be a measured
- // value. However in case of your simple
- // graphics and in the case of v-synced
- // buffer swap, and the prevalence of LCD
- // screens updating at 60Hz we can make this
- // a constant:
- // One frame is 1/60th of a second and we
- // want to take the animation 5 seconds to
- // play:
- float animation_step = (1./60.) / (5.);
- animation_time += animation_step;
- } else {
- animation_time = 0.;
- j++;
- }
- }
- glutSwapBuffers();
- }
- // Called when the window is resized
- // w, h - width and height of the window in pixels.
- void resizeWindow(int w, int h)
- {
- double aspectRatio;
- // Technically all this should be done in the display function!
- // Define the portion of the window used for OpenGL rendering.
- glViewport( 0, 0, w, h ); // View port uses whole window
- // Set up the projection view matrix: perspective projection
- // Determine the min and max values for x and y that should appear in the window.
- // The complication is that the aspect ratio of the window may not match the
- // aspect ratio of the scene we want to view.
- w = (w==0) ? 1 : w;
- h = (h==0) ? 1 : h;
- aspectRatio = (double)w / (double)h;
- glMatrixMode( GL_PROJECTION );
- glLoadIdentity();
- gluPerspective( 15.0, aspectRatio, 25.0, 45.0 );
- }
- // Main routine
- // Set up OpenGL, define the callbacks and start the main loop
- int main( int argc, char** argv )
- {
- glutInit(&argc, argv);
- glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
- glutInitWindowPosition( 10, 60 );
- glutInitWindowSize( 360, 360 );
- glutCreateWindow( "GluCylinders" );
- glutKeyboardFunc( myKeyboardFunc );
- glutSpecialFunc( mySpecialKeyFunc );
- glutReshapeFunc( resizeWindow );
- glutIdleFunc( glutPostRedisplay ); // when idle -> redraw
- glutDisplayFunc( drawScene );
- fprintf(stdout, "Arrow keys control viewpoint.\n");
- fprintf(stdout, "Press \"w\" to toggle wireframe mode.\n");
- fprintf(stdout, "Press \"R\" or \"r\" to increase or decrease rate of movement (respectively).\n");
- // Start the main loop. glutMainLoop never returns.
- glutMainLoop( );
- return 0;
- }
- GLUquadricObj* myReusableQuadric = 0;
- void drawGluCylinder( double height, double radius, int slices, int stacks ) {
- drawGluSlantCylinder( height, radius, radius, slices, stacks );
- }
- void drawGluSlantCylinder( double height, double radiusBase, double radiusTop, int slices, int stacks )
- {
- if ( ! myReusableQuadric ) {
- myReusableQuadric = gluNewQuadric();
- // Should (but don't) check if pointer is still null --- to catch memory allocation errors.
- gluQuadricNormals( myReusableQuadric, GL_TRUE );
- }
- // Draw the cylinder.
- gluCylinder( myReusableQuadric, radiusBase, radiusTop, height, slices, stacks );
- }
- void drawGluCylinderWithCaps( double height, double radius, int slices, int stacks ) {
- drawGluSlantCylinderWithCaps( height, radius, radius, slices, stacks );
- }
- // animate shall calculate the new position for the next
- // render iteration. Don't do delays, busy loops and drawing
- // stuff here.
- void animate(float t, float &x3, float &y3, float &z3)
- {
- // I don't see it in this mess, but I
- // assume this is some kind of spline
- // interpolation, right?
- x3 = 0.5*((-Geometry[j-1][0] + 3*Geometry[j][0] -3*Geometry[j+1][0] + Geometry[j+2][0])*t*t*t + (2*Geometry[j-1][0] -5*Geometry[j][0] +4*Geometry[j+1][0] -Geometry[j+2][0])*t*t + (-Geometry[j-1][0] + Geometry[j+1][0])*t + 2*Geometry[j][0]);
- y3 = 0.5*((-Geometry[j-1][1] + 3*Geometry[j][1] -3*Geometry[j+1][1] + Geometry[j+2][1])*t*t*t+ (2*Geometry[j-1][1] -5*Geometry[j][1] +4*Geometry[j+1][1] -Geometry[j+2][1])*t*t +(-Geometry[j-1][1] + Geometry[j+1][1])*t + 2*Geometry[j][1]);
- z3 = 0.5*((-Geometry[j-1][2] + 3*Geometry[j][2] -3*Geometry[j+1][2] + Geometry[j+2][2])*t*t*t + (2*Geometry[j-1][2] -5*Geometry[j][2] +4*Geometry[j+1][2] -Geometry[j+2][2])*t*t +(-Geometry[j-1][2] + Geometry[j+1][2])*t + 2*Geometry[j][2]);
- }
- void renderCylinder(float x1, float y1, float z1, float x2,float y2, float z2, float radius,int subdivisions,GLUquadricObj *quadric)
- {
- float v,rx,ry,ax,vx = x2-x1;
- float vy = y2-y1;
- float vz = z2-z1; //handle the degenerate case of z1 == z2 with an approximation
- if(vz == 0)
- vz =.00000001;
- v = sqrt( vx*vx + vy*vy + vz*vz );
- ax = 57.2957795*acos( vz/v );
- if ( vz < 0.0 )
- ax = -ax;
- rx = -vy*vz;
- ry = vx*vz;
- glPushMatrix(); //draw the cylinder body
- glTranslatef( x1,y1,z1 );
- glRotatef(ax, rx, ry, 0.0);
- gluQuadricOrientation(quadric,GLU_OUTSIDE);
- gluCylinder(quadric, radius, radius, v, subdivisions, 1); //draw the first cap
- gluQuadricOrientation(quadric,GLU_INSIDE);
- gluDisk( quadric, 0.0, radius, subdivisions, 1);
- glTranslatef( 0,0,v ); //draw the second cap
- gluQuadricOrientation(quadric,GLU_OUTSIDE);
- gluDisk( quadric, 0.0, radius, subdivisions, 1);
- glPopMatrix();
- }
- void renderCylinder_convenient(
- float x1, float y1, float z1,
- float x2,float y2, float z2,
- float radius,int subdivisions)
- {
- //the same quadric can be re-used for drawing many cylinders
- // Instead of quadrics and coding your geometry you should
- // just import a 3D model and render that. It's easier and
- // allows for more artistic freedom. Yes, Yes, I know, your
- // teachers assigment; seriously, I'd tell a teacher demanding
- // this to f*** himself.
- GLUquadricObj *quadric=gluNewQuadric();
- gluQuadricNormals(quadric, GLU_SMOOTH);
- renderCylinder(x1,y1,z1,x2,y2,z2,radius,subdivisions,quadric);
- gluDeleteQuadric(quadric);}
- void drawGluSlantCylinderWithCaps(
- double height, double radiusBase, double radiusTop,
- int slices, int stacks )
- {
- // First draw the cylinder
- drawGluSlantCylinder( height, radiusBase, radiusTop, slices, stacks );
- // Draw the top disk cap
- glPushMatrix();
- glTranslated(0.0, 0.0, height);
- gluDisk( myReusableQuadric, 0.0, radiusTop, slices, stacks );
- glPopMatrix();
- // Draw the bottom disk cap
- glPushMatrix();
- glRotated(180.0, 1.0, 0.0, 0.0);
- gluDisk( myReusableQuadric, 0.0, radiusBase, slices, stacks );
- glPopMatrix();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement