在opengl中查找图像的旋转中心

时间:2014-05-23 02:15:47

标签: c++ opengl rotation

所以我有这段代码,它几乎在屏幕上绘制了各种2D纹理,尽管有多个精灵必须被解剖掉'从纹理(spritesheet)。问题是旋转不能正常工作;当它旋转时,它不会在纹理的中心旋转,这正是我想要做的。我已将其缩小到翻译错误:

    glTranslatef(x + sr->x/2 - sr->w/2,
                 y + sr->y/2 - sr->h/2,0);

    glRotatef(ang,0,0,1.f);

    glTranslatef(-x + -sr->x/2 - -sr->w/2,
                 -y + -sr->y/2 - -sr->h/2,0);

X和Y是它被绘制的位置,sheet rect结构包含从纹理中绘制的sprite的位置X和Y,以及w和h,它们是宽度和高度精灵'从纹理。我尝试了各种其他公式,例如:

 glTranslatef(x, y, 0);

 The below three switching the negative sign to positive (x - y to x + y)

 glTranslatef(sr->x/2 - sr->w/2, sr->y/2 - sr->h/2 0 );

 glTranslatef(sr->x - sr->w/2, sr->y - sr->h/2, 0 );

 glTranslatef(sr->x - sr->w, sr->y - sr->w, 0 );

 glTranslatef(.5,.5,0);

说:

也许会有所帮助
glOrtho(0,screen_width,screen_height,0,-2,10);

正在使用中。

我已经尝试过阅读各种教程,浏览各种论坛,询问各种各样的人,但似乎不是一个有效的解决方案,我也找不到任何有用的资源向我解释我是怎么做的找到图像的中心,以便将其翻译为'(0,0)'。我对OpenGL很陌生,所以很多这些东西需要一段时间才能消化。

这是整个功能:

void Apply_Surface( float x, float y, Sheet_Container* source, Sheet_Rect* sr , float ang = 0, bool flipx = 0, bool flipy = 0, int e_x = -1, int e_y = -1 ) {
 float imgwi,imghi;

 glLoadIdentity();
 glEnable(GL_TEXTURE_2D);
 glBindTexture(GL_TEXTURE_2D,source->rt());     
 // rotation
 imghi = source->rh();
 imgwi = source->rw();
 Sheet_Rect t_shtrct(0,0,imgwi,imghi);
 if ( sr == NULL ) // in case a sheet rect is not provided, assume it's width
                   //and height of texture with 0/0 x/y
    sr = &t_shtrct;

 glPushMatrix();

     // 
     int wid, hei;
     glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&wid);
     glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&hei);
     glTranslatef(-sr->x + -sr->w,
                 -sr->y + -sr->h,0);
     glRotatef(ang,0,0,1.f);

     glTranslatef(sr->x + sr->w,
                 sr->y + sr->h,0);

     // Yeah, out-dated way of drawing to the screen but it works for now.
     GLfloat tex[] = {
        (sr->x+sr->w * flipx) /imgwi, 1 - (sr->y+sr->h  *!flipy )/imghi,
        (sr->x+sr->w * flipx) /imgwi, 1 - (sr->y+sr->h  * flipy)/imghi,
        (sr->x+sr->w * !flipx) /imgwi, 1 - (sr->y+sr->h * flipy)/imghi,
        (sr->x+sr->w * !flipx) /imgwi, 1 - (sr->y+sr->h *!flipy)/imghi
     };
     GLfloat vertices[] = { // vertices to put on screen
          x,        (y + sr->h),
          x,         y,
         (x +sr->w), y,
         (x +sr->w),(y +sr->h)
     };
     // index array
     GLubyte index[6] = { 0,1,2, 2,3,0 };
     float fx = (x/(float)screen_width)-(float)sr->w/2/(float)imgwi;
     float fy = (y/(float)screen_height)-(float)sr->h/2/(float)imghi;

     // activate arrays
     glEnableClientState(GL_VERTEX_ARRAY);
     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     // pass verteices and texture information
     glVertexPointer(2, GL_FLOAT, 0, vertices);
     glTexCoordPointer(2, GL_FLOAT, 0, tex);
     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, index);

     glDisableClientState(GL_VERTEX_ARRAY);
     glDisableClientState(GL_TEXTURE_COORD_ARRAY);

 glPopMatrix();

 glDisable(GL_TEXTURE_2D);

}

工作表容器类:

class Sheet_Container {
    GLuint texture;
    int width, height;
public:
    Sheet_Container();
    Sheet_Container(GLuint, int = -1,int = -1);
    void Load(GLuint,int = -1,int = -1);
    float rw();
    float rh();
    GLuint rt();
};

Sheet rect class:

struct Sheet_Rect {
    float x, y, w, h;
    Sheet_Rect();
    Sheet_Rect(int xx,int yy,int ww,int hh);
};

图片加载功能:

Sheet_Container Game_Info::Load_Image(const char* fil) {
    ILuint t_id;
    ilGenImages(1, &t_id);
    ilBindImage(t_id);
    ilLoadImage(const_cast<char*>(fil));
    int width = ilGetInteger(IL_IMAGE_WIDTH), height = ilGetInteger(IL_IMAGE_HEIGHT);
    return Sheet_Container(ilutGLLoadImage(const_cast<char*>(fil)),width,height);
}

1 个答案:

答案 0 :(得分:1)

您的四边形(两个三角形)位于:

( x + sr->w / 2,  y + sr->h / 2 )

您需要将该点移动到原点,旋转,然后将其移回:

 glTranslatef ( (x + sr->w / 2.0f),  (y + sr->h / 2.0f), 0.0f); // 3rd
 glRotatef    (0,0,0,1.f);                                      // 2nd
 glTranslatef (-(x + sr->w / 2.0f), -(y + sr->h / 2.0f), 0.0f); // 1st

这是我认为你被绊倒的地方。人们自然会认为OpenGL按照它们出现的顺序(从上到下)应用转换,但事实并非如此。每当它乘以两个矩阵时,OpenGL就会有效地交换操作数:

M1 x M2 x M3
~~~~~~~
  (1)
  ~~~~~~~~~~
      (2)

(1) M2 * M1
(2) M3 * (M2 * M1)   -->   M3 * M2 * M1  (row-major / textbook math notation)

这个术语的技术术语是后乘法,它都与在OpenGL(column-major)中实现矩阵的方式有关。我只想说,您应该从下到上阅读glTranslatefglRotatefglScalef等来电。

除此之外,你当前的轮换没有任何意义。

您告诉GL围绕轴旋转 0度&lt; 0,0,1&gt; (换言之,z轴)。轴是正确的,但 0度旋转不会做任何事情;)