[英]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.