在没有GL OpenGL矩阵函数的情况下使用矩阵移动三角形

时间:2014-09-22 15:06:14

标签: c++ opengl matrix

如果没有OpenGL矩阵函数,我不知道如何做到这一点。

  

通过将每个顶点位置乘以2D来变换三角形   仿射缩放,旋转或平移矩阵,如下所述   通过键盘输入。

     

键盘输入:

's' key, scale by 1.1 units in X and Y
'r' key, rotate clockwise (in XY plane) by 2.0 degrees
't' key, translate 0.1 unit in X and Y
'q' key, quit program
     

您不能使用诸如glScale,glTranslate或glRotate之类的OpenGL矩阵函数来执行转换。

这就是我到目前为止......当我构建程序时,三角形不会移动,但是在按下某些键后我会得到随机数,所以我知道它正在做某事:

#include <iostream>
using namespace std;
#include <math.h>
#include <GLUT/glut.h>

void myInit();
void myDraw();
void keyboard( unsigned char, int, int );
float sum;


float theta = 3.14;
int k = 0;

float cVert[3][2]= 
{ 
  -1.0, -1.0, 
  1.0, -1.0,
  0.0, 1.0
};

float triVert[3][2] = 
{
    -1.0, -1.0, 
    1.0, -1.0,
    0.0, 1.0
};

float rotVert[3][3] =
{
  1,0,0,
  0, cos(theta), -sin(theta),
  0, sin(theta), cos(theta)
};

float scaleVert[3][2] =
{
  1.1, 0.0,
  0.0, 1.1, 
  0.0, 0.0
};

int main( int argc, char *argv[] )
{   
  // Initialize window system 
  glutInit( &argc, argv );
  glutInitDisplayMode( GLUT_SINGLE | GLUT_RGB );
  glutInitWindowSize( 640, 480 );
  glutCreateWindow( "Lab 4" );

  // Initialize graphics 
  myInit();

  // Callbacks
  glutDisplayFunc( myDraw );
    glutKeyboardFunc( keyboard );

    // Event loop 
  glutMainLoop();
}

// Initialize drawing
void myInit()
{
  // Background color 
  glClearColor(0.0, 0.0, 0.0, 1.0);

  // 2D world projection
  glMatrixMode( GL_PROJECTION );
  glLoadIdentity();
  gluOrtho2D( -10.0, 10.0, -10.0, 10.0 );
}

// Display callback 
void myDraw()
{
    // Clear the screen 
  glClearColor(0.0, 0.0, 0.0, 1.0);
  glClear(GL_COLOR_BUFFER_BIT );

  // // Draw triangle in initial position
  // glColor3f( 1.0, 0.0, 0.0 );
  // glBegin( GL_LINE_LOOP );
     //  glVertex2f( triVert[0][0], triVert[0][1] );
        // glVertex2f( triVert[1][0], triVert[1][1] );
        // glVertex2f( triVert[2][0], triVert[2][1] );
  // glEnd();

  // Draw triangle in new position here
  glBegin( GL_LINE_LOOP );
    glColor3f( 0.0, 1.0, 0.0 );
    glVertex2f(cVert[0][0], cVert[0][1]);
    glVertex2f(cVert[1][0], cVert[1][1]);
    glVertex2f(cVert[2][0], cVert[2][1]);
    cout << cVert[3][2] << " ";
  glEnd();

  // Execute draw commands 
  glFlush();
}

// Keyboard callback 
void keyboard( unsigned char key, int x, int y )
{
  // Process keys 
  switch (key)
    {
  case 's': //scale by 1.1 units in X and Y
      for(k=0;k<3;++k)
       {
        cVert[3][2] = cVert[3][2]+(scaleVert[3][2]*triVert[3][2]);
        cout << cVert[3][2]<<" ";
        }
      break;
  case 'r': //rotate clockwise (in XY plane) by 2.0 degrees
       for(k=0;k<3;++k)
       {
        cVert[3][2] = cVert[3][2]+(rotVert[3][3]*triVert[3][2]);
        theta = theta + 2.0;
         cout << cVert[3][2]<<" ";
         cout << theta << " ";
        }
      break;
  case 't': //translate 0.1 unit in X and Y
      break;
    case 'q':                       // exit program
      exit(1);
      break;
    }

  // Redraw the scene 
  glutPostRedisplay();
}

1 个答案:

答案 0 :(得分:1)

这个程序的行为是未定义的,所以难怪你得到&#34;随机&#34;号。

    cVert[3][2] = cVert[3][2]+(scaleVert[3][2]*triVert[3][2]);

执行矩阵加法或乘法。 它只是添加了一个矩阵和一个元素的一个元素的乘积 另一个矩阵到第三个矩阵的一个元素。 或者至少它这样做,如果这些元素中的任何一个实际上在其中任何一个 矩阵,但实际上cVert的右下角元素是cVert[2][1] --remember,C ++编号从零开始的行和列,所以声明 float cVert[3][2]表示第一个索引有3个值(0,1或2) 第二个有2个值(0或1) - 对于其他两个矩阵也是如此。 你的程序没有崩溃,因此所有这些位置都在可访问的内存中, 但是他们访问的数据与你想要的完全不同。

正如评论中已经指出的那样,矩阵加法和乘法不是内置的 C ++语言本身。您显然是要为它们编写源代码 你自己。您可能希望确定已经查看了矩阵乘法的方法 定义 - 矩阵的直接加法函数有两个嵌套循环, 但是直接的乘法函数有三个嵌套循环。

另一个问题是使用前一个静态初始化rotVert theta的静态定义。 本身没有任何问题(虽然也没有太大的好处), 但要了解您稍后对theta的值所做的更改 not 自动传播回rotVert。 大括号中rotVert的初始值设定项在之前评估 main函数运行,其数值被复制到rotVert,然后 那段特殊的代码永远不会再使用了。

如果你不小心你的角度单位,你的旋转也会有点疯狂。 您知道sin(theta)cos(theta)会将theta解释为多个弧度。 如果你完全按照这种方式调用trig函数(使用参数theta),那么 theta = theta + 2.0;将添加两个弧度(约114度),而不是2度, 到你的旋转角度。要么弄清楚2度是弧度, 或者每次将它传递给三角函数时,将度数测量角度转换为弧度。

(角度单位的问题目前被这个值掩盖了 在静态初始化之后,theta实际上从未在旋转矩阵中使用过 你的程序,所以你必须先解决矩阵初始化问题 真的看看角度单位是否正常工作。)