如果没有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();
}
这个程序的行为是未定义的,所以难怪你会得到"随机"数字。
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
是使用前面的CCD_ 5的静态定义。这本身并没有错(尽管也没有什么好处),但要理解您稍后对theta
的值所做的更改donot会自动传播回rotVert
。大括号中rotVert
的初始值设定项在运行main
函数,将它们的数值复制到rotVert
中,然后那段特定的代码再也不用了。
如果你不小心你的角度单位,你的旋转也会有点疯狂。您知道sin(theta)
和cos(theta)
会将theta
解释为若干弧度。如果您完全以这种方式调用trig函数(使用参数theta
),那么CCD_ 15将添加两个弧度(约114度)而不是2度,根据你的旋转角度。要么算出2度的弧度是多少,或者每次将度数测量的角度传递给三角函数时,将其转换为弧度。
(角度单位的问题目前被以下事实所掩盖:的theta
在静态初始化后从未实际用于旋转矩阵因此,您必须先解决矩阵初始化问题,然后才能真正了解角度单位是否正常工作。)