Rotating an object in OpenGL about it's centre

viraj
  • Rotating an object in OpenGL about it's centre viraj

    Im writing a game for which, one of the models are loaded from an .obj file.

    It's a model of a plane, and I want to rotate the propeller. The object file is broken into groups, and the propeller is identified, so that's all good. I'm writing the game in C++ with OpenGl/GLFW The drawing function is:

    int win_width;
    int win_height;
    glfwGetWindowSize(&win_width, &win_height);
    float win_aspect = (float)win_width / (float)win_height;
    glViewport(0, 0, win_width, win_height);
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(90, win_aspect, 1, 100.0);
    
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0, 0, 30.0, 0, 0, 0, 0.0, 1.0, 0.0);
    
    glEnable(GL_DEPTH);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_NORMALIZE); 
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHT1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    glColor3f(0.0f, 0.0f, 0.0f);
    int vertexIndex = 0, normalIndex;
    glRotatef(90, 0, 1, 0);
    glPushMatrix();
    for(int a = 0; a < (int)groups.size(); a++)
    {
        if(groups[a].type == "prop")
        {
    //Code for rotation
            glPopMatrix();
            glPushMatrix();
            float x,y,z;
            x = y = z = 0;
            int Count = 0;
            for(int k = 0; k < groups[a].faces.size(); k++)
            {
                for(int p = 0; p < groups[a].faces[k].vertices.size(); p++)
                {
                    int _index = groups[a].faces[k].vertices[p];
                    y += vertices[_index].Dimensions[_y] ;
                    z += vertices[_index].Dimensions[_z];
                    Count++;
                }
            }
            z /= Count;
            y /= Count;
            glTranslatef(0, -y, -z);
            glRotatef(angle, 1, 0, 0);
            glTranslatef(0, y, z);
        }
        for(int b = 0; b < (int)groups[a].faces.size(); b++)
        {
            glBegin(GL_POLYGON);
            for(int c = 0; c < (int)groups[a].faces[b].vertices.size(); c++)
            {
                vertexIndex = groups[a].faces[b].vertices[c];
                glVertex3d(vertices[vertexIndex].Dimensions[_x], vertices[vertexIndex].Dimensions[_y], vertices[vertexIndex].Dimensions[_z]);
            }
            glEnd();
        }
    }
    glPopMatrix();
    glfwSwapBuffers();
    

    Since I don't know the exact centre of the propeller, that's what the for loop before the rotation is for. It finds the average of the y and z co-ordinates.

    After I find it, I translate to -y,-z , rotate it, and then translate back. This makes the propeller spin as I want it to, but it also rotates along the origin >.< http://people.sc.fsu.edu/~jburkardt/data/obj/cessna.obj <- This is the object file.

    groups is a vector of objects and each object has a vector of faces. I'm sure that the vertices and faces are being loaded correctly, since the whole model renders correctly.

  • OpenGL uses a column vector convention, which means the matrices must be applied in the opposite of the order in which you actually want the transformations to occur. Just replace this:

    glTranslatef(0, -y, -z);
    glRotatef(angle, 1, 0, 0);
    glTranslatef(0, y, z);
    

    with this:

    glTranslatef(0, y, z);
    glRotatef(angle, 1, 0, 0);
    glTranslatef(0, -y, -z);
    

    and that should fix it.

Tags
c++ opengl 3d rotation
Related questions and answers
  • ); // Set The Color Of The Model ( NEW ) // ORIGINAL DRAWING CODE //Draw the model as an interpolation between the two frames glBegin(GL_TRIANGLES); for(int i = 0; i... NEHE'S TUT glBegin (GL_TRIANGLES); // Tell OpenGL What We Want To Draw for(int i = 0; i &lt; numTriangles; i++) { MD2Triangle* triangle... ( NEW ) for (int j = 0; j &lt; Objects[i].numMatFaces; j ++) { glPushMatrix(); // Move the model glTranslatef(Objects[i].pos.x

  • _Commands, m_MD2Header.num_glcommands * sizeof(int)); // Read all the data. for(int i = 0; i &lt; m_MD2Header.num_frames; ++i) { md2_frame_t* Frame = (md2_frame_t*)&amp;Buffer... char index_normal; }; typedef short md2_textcoord_t[2]; struct md2_frame_t { float scale[3]; vec3_t translate; char name[16]; md2_vertex_t vertices[1]; // First vertex of this frame...; float current_time, old_time, interpol; int type, current_frame, next_frame; }; struct md2_glcmd_t { float s; float t; int index; }; #define MD2_IDENT (('2'&lt;&lt;24) + ('P'&lt;&lt;16

  • ; unsigned int m_TextureID; void initFBO() { m_FBOWidth = screen_width; m_FBOHeight = screen_height; glGenRenderbuffers(1, &amp;depth_buffer); glBindRenderbuffer(GL_RENDERBUFFER...(); ///////////////////////////////////////// // Render to Window glClearColor(0, 0, 0, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(0, 0, screen_width, screen_height); glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT...); translate(M, Vector3(0,0,-50)); drawBox(M); } void drawRotatingBox() { Matrix4 M(1); rotate(M, rotation(Vector3(1, 0, 0), rotation_x)); rotate(M, rotation(Vector3(0, 1, 0), rotation_y

  • be on the depth buffer is 0.0 viewport.MaxDepth = 1; // the farthest an object can be on the depth buffer is 1.0 device->RSSetViewports(1, &amp;viewport); // set the viewport...(zbd)); zbd.Width = SCREEN_WIDTH; // set the width of the depth buffer zbd.Height = SCREEN_HEIGHT; // set the height of the depth buffer zbd.ArraySize = 1; // we are only creating one texture... memcpy(pVoid, OurVertices, sizeof(OurVertices)); // copy the vertices to the buffer pBuffer->Unmap(); // create the index buffer out of DWORDs DWORD OurIndices[] = { 0, 1, 2, // side 1

  • of x,y,z positions // clear screen and depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); //glTranslatef(0.0f, 0.0f, -cRadius); glRotatef(xrot,1.0,0.0,0.0...i wanna walk to terrain... first i created the terrain void desenha_terreno(float px, float pz){ for (int z = 0; z &lt; iwidth-1; z++) { glBegin(GL_TRIANGLE_STRIP); for (int x = 0; x &lt..., 1.0f); glVertex3f(terreno[x+1][z+1][0], terreno[x+1][z+1][1], terreno[x+1][z+1][2]); } glEnd(); } } I can move the camera with the functions: void keyboard (unsigned char key, int

  • ; break; } } glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); glTranslatef(200.0f, 200.0f, 0.0f); glRotatef(x,0.0f,0.0f, 1.0f...); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Clear the background of our window to red glMatrixMode (GL_PROJECTION); glLoadIdentity (); glOrtho(0, XSIZE, YSIZE, 0, 0, 1); glMatrixMode (GL_MODELVIEW); glDisable(GL_DEPTH_TEST); GLuint image; ilInit(); ilutRenderer(ILUT_OPENGL); ILuint texid; ILboolean success; ilGenImages(1, &amp;texid

  • if we have it enabled if(postFlag&&amp;fboSetup) { glFlush(); glBindFramebuffer(GL_FRAMEBUFFER, 0); glUseProgram(fboProgram); glClear(GL_COLOR_BUFFER_BIT); glBindTexture(GL...); //start rendering scene one way or another glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glUniformMatrix4fv(mats.projHandle,1,GL_FALSE, glm::value_ptr(mats.projMatrix)); glUniformMatrix4fv... is the init code for the FBO and it's texture: glGenTextures(1,&amp;fboimg); glBindTexture(GL_TEXTURE_2D,fboimg); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf

  • ); glDisableClientState( GL_COLOR_ARRAY ); glBindBuffer( GL_ARRAY_BUFFER, 0 ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); } Back to the Vertex Array Object though. My code for creating the Vertex... in the shader code) for( int n = 0; n &lt; vShaderArgs.size(); n ++) glBindAttribLocation( m_nProgramId, n, vShaderArgs[n].sFieldName.c_str() ); // Create and bind to a vertex array object, which... for( int n = 0; n &lt; vShaderArgs.size(); n ++ ) { glEnableVertexAttribArray(n); glVertexAttribPointer( n, vShaderArgs[n].nFieldSize, GL_FLOAT, GL_FALSE

  • , texscale + sourceY); glVertex2i(x, y + tileHeight); glEnd(); glLoadIdentity(); My initialization code for OpenGL: // Set the OpenGL state after creating the context with SDL_SetVideoMode glClearColor(0, 0, 0, 0); glDisable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); //Enable 2D rendering glViewport(0, 0, Width, Height); //Set Up openGL viewport (screen) glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, Width, Height, 0, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); Just in-case, here's my image loading code, I think that perhaps this may be were the problem lies somehow

Data information