简体   繁体   English

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

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

I don't know how to do this without OpenGL matrix functions. 没有OpenGL矩阵函数,我不知道该怎么做。

Transform the triangle by multiplying each vertex position by a 2D affine scaling, rotation, or translation matrix as specified below through keyboard input. 通过将每个顶点位置乘以2D仿射缩放,旋转或平移矩阵来变换三角形,如下所示(通过键盘输入)。

Keyboard input: 键盘输入:

 '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 

You may NOT use OpenGL matrix functions such as glScale, glTranslate, or glRotate to perform your transformations. 您不得使用glScale,glTranslate或glRotate等OpenGL矩阵函数执行转换。

This is what I have so far... when I build the program the triangle doesn't move, but I get random numbers after pressing some keys so I know it's doing something: 到目前为止,这就是我的意思。。。。。。。。。。。。。。。。。。。。。。。。。。。。

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

The behavior of this program is undefined, so no wonder you get "random" numbers. 该程序的行为是不确定的,因此难怪您会得到“随机”数字。

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

This does not perform matrix addition or multiplication. 执行矩阵加法或乘法。 It merely adds the product of one element of one matrix and one element of another matrix to one element of a third matrix. 它仅将一个矩阵的一个元素与另一矩阵的一个元素的乘积与第三矩阵的一个元素相加。 Or at least it would do so if any of those elements were actually in any of those matrices, but actually the bottom right element of cVert is cVert[2][1] --remember, C++ numbers rows and columns starting from zero, so the declaration float cVert[3][2] says that the first index has 3 values (0, 1, or 2) and the second has 2 values (0 or 1)-- and similarly for the other two matrices. 至少如果这些元素中的任何一个确实在这些矩阵中的任何一个中,它会这样做,但是实际上cVert右下角元素是cVert[2][1]记住,C ++从零开始对行和列进行编号,所以声明float cVert[3][2]表示第一个索引具有3个值(0、1或2),第二个索引具有2个值(0或1),其他两个矩阵也类似。 Your program didn't crash, so all those locations are in accessible memory somewhere, but they are accessing completely different data than you intended. 您的程序没有崩溃,所以所有这些位置都在某个位置的可访问内存中,但是它们访问的数据与您预期的完全不同。

As already noted in a comment, matrix addition and multiplication are not built into the C++ language itself. 正如评论中已经提到的,矩阵加法和乘法未内置在C ++语言本身中。 You are clearly meant to write the source code for them yourself. 您显然应该亲自为他们编写源代码。 You may want to make sure you have reviewed how matrix multiplication is defined--a straightforward addition function for matrices has two nested loops, but a straightforward multiplication function has three nested loops. 您可能需要确保已检查了如何定义矩阵乘法-矩阵的直接加法函数具有两个嵌套循环,而简单的乘法函数具有三个嵌套循环。

Another problem is that rotVert is initialized statically using the previous static definition of theta . 另一个问题是,使用先前的theta静态定义对rotVert进行了静态初始化。 In itself there is nothing wrong with this (though not much good in it either), but understand that changes you make to the value of theta later do not automatically propagate back to rotVert . 它本身没有任何问题(尽管也没有什么不好),但是请理解,您以后对theta值所做的更改不会自动传播回rotVert The initializers of rotVert in the curly braces are evaluated once before your main function runs, their numeric values are copied into rotVert , and then that particular piece of code is never used again. 花括号中的rotVert初始化程序将在main函数运行之前进行一次评估,将其数值复制到rotVert ,然后不再使用该特定代码。

Your rotations will also be a bit crazy if you aren't more careful about your angle units. 如果您不更注意角度单位,旋转也会有些疯狂。 You know that sin(theta) and cos(theta) will interpret theta as a number of radians. 您知道sin(theta)cos(theta)会将theta解释为许多弧度。 If you call the trig functions exactly that way (with parameter theta ), then theta = theta + 2.0; 如果以这种方式(使用参数theta )调用trig函数,则theta = theta + 2.0; will add two radians (about 114 degrees), not 2 degrees, to your angle of rotation. 会将两个弧度 (大约114度)而不是2度添加到旋转角度。 Either figure out what 2 degrees is in radians, or convert your degree-measured angle to radians every time you pass it to a trig function. 弄清楚2度的弧度是多少,或者在每次将其传递给Trig函数时将以度为单位的角度转换为弧度。

(The problem with the angle units is currently masked by the fact that the value of theta never actually get used in your rotation matrix after static initialization of your program, so you'll have to fix the matrix-initialization problem before you can really see whether the angle units are working correctly.) (角度单位的问题目前被以下事实掩盖了,即在程序静态初始化之后, theta的值从未真正在旋转矩阵中使用,因此您必须先解决矩阵初始化问题,然后才能真正看到角度单位是否正常工作。)

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

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