繁体   English   中英

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

[英]Using Matrices to Move Triangle without GL OpenGL matrix functions

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

该程序的行为是不确定的,因此难怪您会得到“随机”数字。

    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 ++语言本身中。 您显然应该亲自为他们编写源代码。 您可能需要确保已检查了如何定义矩阵乘法-矩阵的直接加法函数具有两个嵌套循环,而简单的乘法函数具有三个嵌套循环。

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

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

(角度单位的问题目前被以下事实掩盖了,即在程序静态初始化之后, theta的值从未真正在旋转矩阵中使用,因此您必须先解决矩阵初始化问题,然后才能真正看到角度单位是否正常工作。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM