
Struggling to Understand GL.Translate & GL.Rotate
Posted Tuesday, 28 February, 2012 - 15:54 by m_elias inI have been reading through a couple OpenGL books and experimenting with OpenTK. According to what I read, OpenTK seems to implement the Translate and Rotate commands differently, almost backwards to what I expect. I have very little experience so I don't doubt that my understanding is just wrong but maybe someone can help me get the ol' Solar sample program transcribed for OpenTK. I have been trying to do it myself with cubes instead of spheres. Here is the source, I'm not concerned about the keyboard inputs. I am actually using a glControl in my C# forms project but any way you do it, I need to see how these examples look in OpenTK.
/* * Solar.c * * Program to demonstrate how to use a local * coordinate method to position parts of a * model in relation to other model parts. * * Draws a simple solar system, with a sun, planet and moon. * Based on sample code from the OpenGL programming guide * by Woo, Neider, Davis. Addison-Wesley. * * Author: Samuel R. Buss * * Software accompanying the book * 3D Computer Graphics: A Mathematical Introduction with OpenGL, * by S. Buss, Cambridge University Press, 2003. * * Software is "as-is" and carries no warranty. It may be used without * restriction, but if you modify it, please change the filenames to * prevent confusion between different versions. * Bug reports: Sam Buss, sbuss@ucsd.edu. * Web page: http://math.ucsd.edu/~sbuss/MathCG * * USAGE: * Press "r" key to toggle (off and on) running the animation * Press "s" key to single-step animation * The up arrow key and down array key control the * time step used in the animation rate. Each key * press multiplies or divides the times by a factor * of two (2). * Press ESCAPE to exit. * */ #include "Solar.h" #include <stdlib.h> #include <GL/glut.h> // OpenGL Graphics Utility Library static GLenum spinMode = GL_TRUE; static GLenum singleStep = GL_FALSE; // These three variables control the animation's state and speed. static float HourOfDay = 0.0; static float DayOfYear = 0.0; static float AnimateIncrement = 24.0; // Time step for animation (hours) // glutKeyboardFunc is called below to set this function to handle // all normal key presses. static void KeyPressFunc( unsigned char Key, int x, int y ) { switch ( Key ) { case 'R': case 'r': Key_r(); break; case 's': case 'S': Key_s(); 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. static void SpecialKeyFunc( int Key, int x, int y ) { switch ( Key ) { case GLUT_KEY_UP: Key_up(); break; case GLUT_KEY_DOWN: Key_down(); break; } } static void Key_r(void) { if ( singleStep ) { // If ending single step mode singleStep = GL_FALSE; spinMode = GL_TRUE; // Restart animation } else { spinMode = !spinMode; // Toggle animation on and off. } } static void Key_s(void) { singleStep = GL_TRUE; spinMode = GL_TRUE; } static void Key_up(void) { AnimateIncrement *= 2.0; // Double the animation time step } static void Key_down(void) { AnimateIncrement /= 2.0; // Halve the animation time step } /* * Animate() handles the animation and the redrawing of the * graphics window contents. */ static void Animate(void) { // Clear the redering window glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if (spinMode) { // Update the animation state HourOfDay += AnimateIncrement; DayOfYear += AnimateIncrement/24.0; HourOfDay = HourOfDay - ((int)(HourOfDay/24))*24; DayOfYear = DayOfYear - ((int)(DayOfYear/365))*365; } // Clear the current matrix (Modelview) glLoadIdentity(); // Back off eight units to be able to view from the origin. glTranslatef ( 0.0, 0.0, -8.0 ); // Rotate the plane of the elliptic // (rotate the model's plane about the x axis by fifteen degrees) glRotatef( 15.0, 1.0, 0.0, 0.0 ); // Draw the sun -- as a yellow, wireframe sphere glColor3f( 1.0, 1.0, 0.0 ); glutWireSphere( 1.0, 15, 15 ); // Draw the Earth // First position it around the sun // Use DayOfYear to determine its position glRotatef( 360.0*DayOfYear/365.0, 0.0, 1.0, 0.0 ); glTranslatef( 4.0, 0.0, 0.0 ); glPushMatrix(); // Save matrix state // Second, rotate the earth on its axis. // Use HourOfDay to determine its rotation. glRotatef( 360.0*HourOfDay/24.0, 0.0, 1.0, 0.0 ); // Third, draw the earth as a wireframe sphere. glColor3f( 0.2, 0.2, 1.0 ); glutWireSphere( 0.4, 10, 10); glPopMatrix(); // Restore matrix state // Draw the moon. // Use DayOfYear to control its rotation around the earth glRotatef( 360.0*12.0*DayOfYear/365.0, 0.0, 1.0, 0.0 ); glTranslatef( 0.7, 0.0, 0.0 ); glColor3f( 0.3, 0.7, 0.3 ); glutWireSphere( 0.1, 5, 5 ); // Flush the pipeline, and swap the buffers glFlush(); glutSwapBuffers(); if ( singleStep ) { spinMode = GL_FALSE; } glutPostRedisplay(); // Request a re-draw for animation purposes } // Initialize OpenGL's rendering modes void OpenGLInit(void) { glShadeModel( GL_FLAT ); glClearColor( 0.0, 0.0, 0.0, 0.0 ); glClearDepth( 1.0 ); glEnable( GL_DEPTH_TEST ); } // ResizeWindow is called when the window is resized static void ResizeWindow(int w, int h) { float aspectRatio; h = (h == 0) ? 1 : h; w = (w == 0) ? 1 : w; glViewport( 0, 0, w, h ); // View port uses whole window aspectRatio = (float)w/(float)h; // Set up the projection view matrix (not very well!) glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluPerspective( 60.0, aspectRatio, 1.0, 30.0 ); // Select the Modelview matrix glMatrixMode( GL_MODELVIEW ); } // Main routine // Set up OpenGL, hook up callbacks, and start the main loop int main( int argc, char** argv ) { // Need to double buffer for animation glutInit(&argc,argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH ); // Create and position the graphics window glutInitWindowPosition( 0, 0 ); glutInitWindowSize( 600, 360 ); glutCreateWindow( "Solar System Demo" ); // Initialize OpenGL. OpenGLInit(); // Set up callback functions for key presses glutKeyboardFunc( KeyPressFunc ); glutSpecialFunc( SpecialKeyFunc ); // Set up the callback function for resizing windows glutReshapeFunc( ResizeWindow ); // Callback for graphics image redrawing glutDisplayFunc( Animate ); // Start the main loop. glutMainLoop never returns. glutMainLoop( ); return(0); // Compiler requires this to be here. (Never reached) }


Comments
Re: Struggling to Understand GL.Translate & GL.Rotate
The rendering stuff translates pretty much straight from C to C#. If this is your first OpenTK project you might want to build a basic camera and practice just viewing basic things before anything else. If not, ignore me :-)
I'm not sure if you are asking for explanation in general of OpenGL translate and rotate, or 'if OpenTK does it differently', which I don't believe it does. You might want to take a look at the official OpenGl programming guide chapter 3 here, which also has the solar system sample, but breaks down the components and describes the opengl state machine in more detail especially as pertains to model transformations. It's pretty standard that "translating then rotating is different than rotating then translating." The chapter does cover this with good examples.
Also, this earlier post might help with additional understanding: http://www.opentk.com/node/1178
Since you asked, assuming you've defined q1 q2 and q3 (will be used as spheres later on) somewhere else, here's my super quick version of the relevant code, where you would put around the end of a rendering function. I pretty much just copied and pasted into an existing project from the sample C code and renamed functions where necessary and it works fine.
IntPtr q1 = OpenTK.Graphics.Glu.NewQuadric();
IntPtr q2 = OpenTK.Graphics.Glu.NewQuadric();
IntPtr q3 = OpenTK.Graphics.Glu.NewQuadric();
Hope this helps,
Re: Struggling to Understand GL.Translate & GL.Rotate
As expected I have a lot to learn yet. My biggest frustration is translating the glut opengl tutorials to opentk. For example, when I searched for "opentk sphere", I got hits for some of the forum posts here that created a custom function for it (which I couldn't figure out), so I didn't know that OpenTK.Graphics.Glu.Sphere existed. I think my biggest issue is understanding the Modelview, Projection, Perspective and Viewport matrices and implementation. There are other seasonal work projects coming up so I think I will put this one on the back burner and hopefully when I pick it back up it all makes more sense. What I am working towards is plotting a coverage map with GPS coordinates. Something like the screen shots at these links. Thanks for taking the time to post your response.