【问题标题】:Using Matrices to Move Triangle without GL OpenGL matrix functions在没有 GL OpenGL 矩阵函数的情况下使用矩阵移动三角形
【发布时间】:2014-11-16 14:41:38
【问题描述】:

如果没有 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

您不得使用 OpenGL 矩阵函数(例如 glScale、glTranslate 或 glRotate)来执行转换。

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

#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();
}

【问题讨论】:

  • 这个作业告诉你该做什么。您必须构建相应的转换矩阵并将您的顶点与它们相乘。编写一个函数来进行 3×3 矩阵乘法和一些帮助程序来构建正确的变换矩阵。然后使用那些。
  • 我不是很清楚,我认为这就是我当时正在做的事情,将矩阵乘以表示变换或旋转或缩放的矩阵。
  • 我看到一些循环遍历变量 k,但该变量从未用作矩阵的索引。此外,您不应该逐字粘贴矩阵乘法。编写函数 mat3x3_mul(mat3x3 out, mat3x3 a, mat3x3b)mat3x3_mul_vec3(vec3 out, mat3x34 M, vec3 v) 并使用它们。你可能想看看我的 linmath.h 如何做到这一点:github.com/datenwolf/linmath.h/blob/master/linmath.h - 不包含 mat3x3 代码,但无论矩阵的维度如何,乘法规则都是相同的。

标签: c++ opengl matrix


【解决方案1】:

这个程序的行为是未定义的,所以难怪你得到“随机”数字。

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

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

正如评论中已经指出的那样,矩阵加法和乘法没有内置到 C++ 语言本身。您显然是要为他们编写源代码 你自己。您可能需要确保您已经查看了矩阵乘法 已定义——一个简单的矩阵加法函数有两个嵌套循环, 但是一个简单的乘法函数有三个嵌套循环。

另一个问题是rotVert是使用前面的静态初始化的 theta 的静态定义。 这本身并没有什么问题(尽管也没有什么好处), 但请理解您稍后对theta 的值所做的更改 自动传播回rotVert。 花括号中rotVert 的初始化程序在您之前评估一次 main函数运行,它们的数值被复制到rotVert,然后 那段特定的代码再也不会被使用了。

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

(角度单位的问题目前被以下事实所掩盖 的theta 在静态初始化后从未真正用于您的旋转矩阵 你的程序,所以你必须先解决矩阵初始化问题 真的看看角度单位是否工作正常。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-16
    • 2019-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多