文章目录
实验补充1 层级建模-机械手臂
一、 实验目的
- 了解层级建模基本概念
- 掌握简单平移,缩放,旋转的矩阵构建
- 了解变换矩阵在层级模型父子节点间的传递关系
二、 理论背景
层次模型是指用树型(层次)结构表示实体类型及实体间联系的数据模型称为层次模型(Hierarchical Model)。
以实例代码中的机械手臂为例,其对应的层次模型表示如下
在对层次模型中的节点进行操作的时候,此操作不但会影响该节点的位置和方向,同样会影响该节点的所有子孙节点。如在机械手臂模型中,底座的操作会影响整个模型,但是上臂的操作只影响自己。
三、 实验内容
-
绘制每一个节点,完成base(),lower_arm(),upper_arm()三个函数。
-
构建子节点局部变化矩阵,根据遍历顺序完成display()函数。
实验中按照层次模型深度优先遍历顺序,按照(底座,下臂,上臂)的顺序对节点进行绘制,其基本代码如下:
model_view = RotateY(Theta[Base] );//底座变换矩阵
base();//首先绘制底座
model_view *= ( Translate(0.0, BASE_HEIGHT, 0.0) *
RotateZ(Theta[LowerArm]) );//下臂变换矩阵
lower_arm();//绘制下臂
model_view *= ( Translate(0.0, LOWER_ARM_HEIGHT, 0.0) *
RotateZ(Theta[UpperArm]) );//上臂变换矩阵
upper_arm();//绘制上臂
通过以上代码可以看出子节点的变换矩阵等于父节点的变换矩阵乘以子节点的局部变换矩阵。
节点的绘制以底座为例:
void base()
{
mat4 instance = ( Translate( 0.0, 0.5 * BASE_HEIGHT, 0.0 ) *
Scale( BASE_WIDTH,BASE_HEIGHT,BASE_WIDTH ) );
//按长宽高缩放正方体,并且平移到合适的位置
glUniformMatrix4fv( ModelView, 1, GL_TRUE, model_view * instance );// 将变换矩阵传给shader
glDrawArrays( GL_TRIANGLES, 0, NumVertices );//渲染三角面片
}
Void base()
函数,对底座进行绘制,在display()函数中调用。
1)示例代码中已经实现了base()函数,在display()函数添加代码
model_view = RotateY(Theta[Base]);//底座旋转矩阵
base();//绘制底座
可以得到如下(a)的结果,将整个实验内容完成可以得到(b)的效果
2)示例代码中已经实现了完整的菜单添加功能,学生无需再添加生成菜单的代码;在程序窗口点击鼠标中键即可弹出菜单,如图©所示,选中需要操作的节点以后,通过鼠标左键和右键完成机器模型的变化。
完整代码
#include "Angel.h"
#pragma comment(lib, "glew32.lib")
typedef Angel::vec4 point4;
typedef Angel::vec4 color4;
const int NumVertices = 36; //(6 faces)(2 triangles/face)(3 vertices/triangle)
point4 points[NumVertices];
color4 colors[NumVertices];
point4 vertices[8] = {
point4(-0.5, -0.5, 0.5, 1.0),
point4(-0.5, 0.5, 0.5, 1.0),
point4(0.5, 0.5, 0.5, 1.0),
point4(0.5, -0.5, 0.5, 1.0),
point4(-0.5, -0.5, -0.5, 1.0),
point4(-0.5, 0.5, -0.5, 1.0),
point4(0.5, 0.5, -0.5, 1.0),
point4(0.5, -0.5, -0.5, 1.0)
};
// RGBA olors
color4 vertex_colors[8] = {
color4(0.0, 0.0, 0.0, 1.0), // black
color4(1.0, 0.0, 0.0, 1.0), // red
color4(1.0, 1.0, 0.0, 1.0), // yellow
color4(0.0, 1.0, 0.0, 1.0), // green
color4(0.0, 0.0, 1.0, 1.0), // blue
color4(1.0, 0.0, 1.0, 1.0), // magenta
color4(1.0, 1.0, 1.0, 1.0), // white
color4(0.0, 1.0, 1.0, 1.0) // cyan
};
// Parameters controlling the size of the Robot's arm
const GLfloat BASE_HEIGHT = 2.0;
const GLfloat BASE_WIDTH = 5.0;
const GLfloat LOWER_ARM_HEIGHT = 5.0;
const GLfloat LOWER_ARM_WIDTH = 0.5;
const GLfloat UPPER_ARM_HEIGHT = 5.0;
const GLfloat UPPER_ARM_WIDTH = 0.5;
// Shader transformation matrices
mat4 model_view;
GLuint ModelView, Projection;
// Array of rotation angles (in degrees) for each rotation axis
enum { Base = 0, LowerArm = 1, UpperArm = 2, NumAngles = 3 };
int Axis = Base;
GLfloat Theta[NumAngles] = { 0.0 };
// Menu option values
const int Quit = 4;
//----------------------------------------------------------------------------
int Index = 0;
void
quad(int a, int b, int c, int d)
{
colors[Index] = vertex_colors[a]; points[Index] = vertices[a]; Index++;
colors[Index] = vertex_colors[a]; points[Index] = vertices[b]; Index++;
colors[Index] = vertex_colors[a]; points[Index] = vertices[c]; Index++;
colors[Index] = vertex_colors[a]; points[Index] = vertices[a]; Index++;
colors[Index] = vertex_colors[a]; points[Index] = vertices[c]; Index++;
colors[Index] = vertex_colors[a]; points[Index] = vertices[d]; Index++;
}
void
colorcube()//这里生成单位立方体的六个表面
{
quad(1, 0, 3, 2);
quad(2, 3, 7, 6);
quad(3, 0, 4, 7);
quad(6, 5, 1, 2);
quad(4, 5, 6, 7);
quad(5, 4, 0, 1);
}
//----------------------------------------------------------------------------
/* Define the three parts */
/* Note use of push/pop to return modelview matrix
to its state before functions were entered and use
rotation, translation, and scaling to create instances
of symbols (cube and cylinder */
void
base()//绘制底座
{
mat4 instance = (Translate(0.0, 0.5 * BASE_HEIGHT, 0.0) *
Scale(BASE_WIDTH,
BASE_HEIGHT,
BASE_WIDTH));
glUniformMatrix4fv(ModelView, 1, GL_TRUE, model_view * instance);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
}
//----------------------------------------------------------------------------
void
upper_arm()//绘制大臂
{
//中心在height*0.5的地方
mat4 instance = (Translate(0.0, 0.5 * UPPER_ARM_HEIGHT, 0.0) *
Scale(UPPER_ARM_WIDTH,
UPPER_ARM_HEIGHT,
UPPER_ARM_WIDTH));//仿照上面的base函数,只需要把base全部替换成upper即可
glUniformMatrix4fv(ModelView, 1, GL_TRUE, model_view * instance);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
}
//----------------------------------------------------------------------------
void
lower_arm()//绘制小臂
{
//与上同理
mat4 instance = (Translate(0.0, 0.5 * LOWER_ARM_HEIGHT, 0.0) *
Scale(LOWER_ARM_WIDTH,
LOWER_ARM_HEIGHT,
LOWER_ARM_WIDTH));
glUniformMatrix4fv(ModelView, 1, GL_TRUE, model_view * instance);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
}
//----------------------------------------------------------------------------
void
display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//在此添加代码完成整个机械手臂绘制
model_view = RotateY(Theta[Base]);//底座旋转矩阵
base();//绘制底座
//为了保证TRS的顺序,必须让Translate在rotate的前面
//由于绘制的函数中采用的是绘制中心位置的方法,我们需要给其在这里添加上偏移量
//也就是在初始的时候就将其偏移量设定在base的高度上
model_view *= (Translate(0.0, BASE_HEIGHT, 0.0) *
RotateZ(Theta[LowerArm]));
lower_arm();//绘制下臂
model_view *= (Translate(0.0, LOWER_ARM_HEIGHT, 0.0) *
RotateZ(Theta[UpperArm]));
upper_arm();//绘制上臂
glutSwapBuffers();
}
//----------------------------------------------------------------------------
void
init(void)
{
colorcube();
// Create a vertex array object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create and initialize a buffer object
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(points) + sizeof(colors),
NULL, GL_DYNAMIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(points), points);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(points), sizeof(colors), colors);
// Load shaders and use the resulting shader program
GLuint program = InitShader("vshader81.glsl", "fshader81.glsl");
glUseProgram(program);
GLuint vPosition = glGetAttribLocation(program, "vPosition");
glEnableVertexAttribArray(vPosition);
glVertexAttribPointer(vPosition, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(0));
GLuint vColor = glGetAttribLocation(program, "vColor");
glEnableVertexAttribArray(vColor);
glVertexAttribPointer(vColor, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(sizeof(points)));
ModelView = glGetUniformLocation(program, "ModelView");
Projection = glGetUniformLocation(program, "Projection");
glEnable(GL_DEPTH_TEST);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glClearColor(1.0, 1.0, 1.0, 1.0);
}
//----------------------------------------------------------------------------
void
mouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
// Incrase the joint angle
Theta[Axis] += 5.0;
if (Theta[Axis] > 360.0) { Theta[Axis] -= 360.0; }
}
if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
// Decrase the joint angle
Theta[Axis] -= 5.0;
if (Theta[Axis] < 0.0) { Theta[Axis] += 360.0; }
}
glutPostRedisplay();
}
//----------------------------------------------------------------------------
void
menu(int option)
{
if (option == Quit) {
exit(EXIT_SUCCESS);
}
else {
Axis = option;
}
}
//----------------------------------------------------------------------------
void
reshape(int width, int height)
{
glViewport(0, 0, width, height);
GLfloat left = -10.0, right = 10.0;
GLfloat bottom = -5.0, top = 15.0;
GLfloat zNear = -10.0, zFar = 10.0;
GLfloat aspect = GLfloat(width) / height;
if (aspect > 1.0) {
left *= aspect;
right *= aspect;
}
else {
bottom /= aspect;
top /= aspect;
}
mat4 projection = Ortho(left, right, bottom, top, zNear, zFar);
glUniformMatrix4fv(Projection, 1, GL_TRUE, projection);
model_view = mat4(1.0); // An Identity matrix
}
//----------------------------------------------------------------------------
void
keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 033: // Escape Key
case 'q': case 'Q':
exit(EXIT_SUCCESS);
break;
}
}
//----------------------------------------------------------------------------
int
main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(512, 512);
glutInitContextVersion(3, 2);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutCreateWindow("robot");
glewExperimental = GL_TRUE;
glewInit();
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
glutCreateMenu(menu);
// Set the menu values to the relevant rotation axis values (or Quit)
glutAddMenuEntry("base", Base);
glutAddMenuEntry("lower arm", LowerArm);
glutAddMenuEntry("upper arm", UpperArm);
glutAddMenuEntry("quit", Quit);
glutAttachMenu(GLUT_MIDDLE_BUTTON);
glutMainLoop();
return 0;
}
vshader:
#version 330 core
in vec4 vPosition;
in vec4 vColor;
out vec4 color;
uniform mat4 ModelView;
uniform mat4 Projection;
void main()
{
color = vColor;
gl_Position = Projection * ModelView * vPosition;
}
fshader:
#version 330 core
in vec4 color;
out vec4 fColor;
void main()
{
fColor = color;
}
实验补充2 层级建模-人形机器人
一、 实验目的
- 掌握根据层级结构深度遍历层级树的方法
- 掌握采用堆栈的方式在父子和兄弟节点直接传递变换矩阵的方法。
二、 理论背景
在上一次的上机实验课中,我们已经掌握了简单的每个父节点最多只有一个子节点层级建模方法,本节课中我们将学习在更复杂的层级模型中使用堆栈的方式来保存和恢复节点变换矩阵的方法。和上次实验使用的简单层级结构不同,本次实验的节点在完成自己和子孙节点的绘制以后需要恢复父节点的变换矩阵,因为该节点的兄弟节点需要父节点的变换矩阵。
本次上机课要使用的模型和层次结构参考下图:
在上图的层级结构中,头节点完成绘制以后,它的兄弟节点左上臂,右上臂,左上腿,右上腿等节点同样需要父节点躯干的变换矩阵,所以在绘制节点之前需要使用堆栈保存父节点的变化矩阵,在绘制兄弟节点之前从堆栈恢复父节点的变换矩阵。
三、 实验内容
- 参考上次上机课的内容绘制每一个节点,完成torso(), head(), left_upper_arm(), left_lower_arm(), right_upper_arm(), right_lower_arm(), left_upper_leg(), left_lower_leg(), right_upper_leg(), right_lower_leg()函数。
- 按深度优先顺序,既 “躯干 -> 头 -> 左上臂 -> 左下臂 -> 右上臂 -> 右下臂 -> 左上腿 -> 左下腿 -> 右上腿 -> 右下腿”的顺序完成层级树的遍历,完成display()函数。
节点的绘制可以参考上次上机实验课的节点绘制方法,以本次的躯干绘制为例:
void torso()
{
mvstack.push( model_view );//保存父节点矩阵
mat4 instance = ( Translate( 0.0, 0.5 * TORSO_HEIGHT, 0.0 ) *
Scale( TORSO_WIDTH, TORSO_HEIGHT, TORSO_WIDTH ) );//本节点局部变换矩阵
glUniformMatrix4fv( ModelView, 1, GL_TRUE, model_view * instance );//父节点矩阵*本节点局部变换矩阵
glDrawArrays( GL_TRIANGLES, 0, NumVertices );
model_view = mvstack.pop();//恢复父节点矩阵
}
层级树的遍历绘制和堆栈使用参考如下伪代码:
model_view = RotateY( theta[Torso] );//躯干变换矩阵
torso();//躯干绘制
mvstack.push( model_view );//保存躯干变换矩阵
model_view *= 头结点局部变换矩阵;
head();//头部绘制
model_view = mvstack.pop();//恢复躯干变换矩阵
mvstack.push( model_view ); //保存躯干变换矩阵
model_view *= 左上臂局部变换矩阵;
left_upper_arm();//左上臂绘制
model_view *= 左下臂局部变换矩阵;
left_lower_arm();//左下臂绘制
model_view = mvstack.pop();//恢复躯干变换矩阵
mvstack.push( model_view ); //保存躯干变换矩阵
model_view *= 右上臂局部变换矩阵;
right_upper_arm();//右上臂绘制
model_view *= 右下臂局部变换矩阵
right_lower_arm();//右下臂绘制
model_view = mvstack.pop();//恢复躯干变换矩阵
mvstack.push( model_view ); //保存躯干变换矩阵
model_view *= 左上腿局部变换矩阵;
left_upper_leg();//左上腿绘制
model_view *= 左下腿局部变换矩阵;
left_lower_leg();//左下腿绘制
model_view = mvstack.pop();//恢复躯干变换矩阵
mvstack.push( model_view ); //保存躯干变换矩阵
model_view *= 右上腿局部变换矩阵;
right_upper_leg();//右上腿绘制
model_view *= 右上腿局部变换矩阵;
right_lower_leg();//右下腿绘制
model_view = mvstack.pop();//恢复躯干变换矩阵
↑层级结构遍历和绘制代码
四、 主要参考函数
- Void torso()
该函数完成躯干节点的绘制 - 上次实验课的display()函数,该函数调用每个节点的绘制方法,同时构建各个节点的局部变化矩阵;同时参考本文档实验内容的层级结构遍历和绘制伪代码完成本次上机课的display()函数。
五、 示例和练习
1)示例代码中已经实现了躯干绘制代码,在display()函数中添加代码
model_view = RotateY(theta[Torso]);//躯干变换矩阵
torso();//躯干绘制
可以绘制出躯干的效果如(a),将整个实验内容完成可以得到(b)的效果
2)示例代码中已经实现了完整的菜单添加功能,学生无需再添加生成菜单的代码;在程序窗口点击鼠标中键即可弹出菜单,如图©所示,选中需要操作的节点以后,通过鼠标左键和右键完成机器模型的变化。
因为比较简单就不解析了,其实就是儿子在父亲的矩阵上,然后用堆栈保存下矩阵,然后进行偏移位置,然后绘制,然后再恢复堆栈中的矩阵。
在对每个子矩阵进行修改时,给子矩阵乘上Rotate的矩阵
以躯干为例:
void
display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
model_view = RotateY(theta[Torso]);//躯干变换矩阵
model_view *= Translate(RobotPos.x, RobotPos.y, RobotPos.z);
// std::cout << RobotPos.x << " " << RobotPos.y << " " << RobotPos.z << std::endl;
torso();//躯干绘制}
参数是每个部位都有的角度参数。
enum {
Torso,
Head1,
Head2,
RightUpperArm,
RightLowerArm,
LeftUpperArm,
LeftLowerArm,
RightUpperLeg,
RightLowerLeg,
LeftUpperLeg,
LeftLowerLeg,
NumJointAngles,
Quit
};
// Joint angles with initial values
GLfloat
theta[NumJointAngles] = {
0.0, // Torso
0.0, // Head1
0.0, // Head2
180.0, // RightUpperArm
0.0, // RightLowerArm
0.0, // LeftUpperArm
0.0, // LeftLowerArm
180.0, // RightUpperLeg
0.0, // RightLowerLeg
180.0, // LeftUpperLeg
0.0 // LeftLowerLeg
};
完整代码:
#include "Angel.h"
#include <assert.h>
#pragma comment(lib, "glew32.lib")
typedef Angel::vec4 point4;
typedef Angel::vec4 color4;
const int NumVertices = 36; //(6 faces)(2 triangles/face)(3 vertices/triangle)
point4 points[NumVertices];
color4 colors[NumVertices];
vec3 RobotPos;
point4 vertices[8] = {
point4(-0.5, -0.5, 0.5, 1.0),
point4(-0.5, 0.5, 0.5, 1.0),
point4(0.5, 0.5, 0.5, 1.0),
point4(0.5, -0.5, 0.5, 1.0),
point4(-0.5, -0.5, -0.5, 1.0),
point4(-0.5, 0.5, -0.5, 1.0),
point4(0.5, 0.5, -0.5, 1.0),
point4(0.5, -0.5, -0.5, 1.0)
};
// RGBA olors
color4 vertex_colors[8] = {
color4(0.0, 0.0, 0.0, 1.0), // black
color4(1.0, 0.0, 0.0, 1.0), // red
color4(1.0, 1.0, 0.0, 1.0), // yellow
color4(0.0, 1.0, 0.0, 1.0), // green
color4(0.0, 0.0, 1.0, 1.0), // blue
color4(1.0, 0.0, 1.0, 1.0), // magenta
color4(1.0, 1.0, 1.0, 1.0), // white
color4(0.0, 1.0, 1.0, 1.0) // cyan
};
point4 color_torso = point4(0, 0, 1, 1);
point4 color_head = point4(0, 1, 1, 1);
point4 color_left_upper_arm = point4(1, 0, 1, 1);
point4 color_left_lower_arm = point4(0.4, 0.5, 0.6, 1);
point4 color_right_upper_arm = point4(0, 1, 0, 1);
point4 color_right_lower_arm = point4(0.5, 0.5, 0.5, 1);
point4 color_left_upper_leg = point4(0.5, 0.5, 0.5, 1);
point4 color_left_lower_leg = point4(0.3, 0.3, 0.3, 1);
point4 color_right_upper_leg = point4(0.7, 0.7, 0.7, 1);
point4 color_right_lower_leg = point4(0.3, 0.3, 0.3, 1);
//----------------------------------------------------------------------------
class MatrixStack {
int _index;
int _size;
mat4* _matrices;
public:
MatrixStack(int numMatrices = 100) :_index(0), _size(numMatrices)
{
_matrices = new mat4[numMatrices];
}
~MatrixStack()
{
delete[]_matrices;
}
void push(const mat4& m) {
assert(_index + 1 < _size);
_matrices[_index++] = m;
}
mat4& pop(void) {
assert(_index - 1 >= 0);
_index--;
return _matrices[_index];
}
};
MatrixStack mvstack;
mat4 model_view;
GLuint ModelView, Projection;
GLuint draw_color;
//----------------------------------------------------------------------------
#define TORSO_HEIGHT 5.0
#define TORSO_WIDTH 3.0
#define UPPER_ARM_HEIGHT 3.0
#define LOWER_ARM_HEIGHT 2.0
#define UPPER_LEG_WIDTH 0.5
#define LOWER_LEG_WIDTH 0.5
#define LOWER_LEG_HEIGHT 2.0
#define UPPER_LEG_HEIGHT 3.0
#define UPPER_LEG_WIDTH 0.5
#define UPPER_ARM_WIDTH 0.5
#define LOWER_ARM_WIDTH 0.5
#define HEAD_HEIGHT 1.5
#define HEAD_WIDTH 1.0
// Set up menu item indices, which we can alos use with the joint angles
enum {
Torso,
Head1,
Head2,
RightUpperArm,
RightLowerArm,
LeftUpperArm,
LeftLowerArm,
RightUpperLeg,
RightLowerLeg,
LeftUpperLeg,
LeftLowerLeg,
NumJointAngles,
Quit
};
// Joint angles with initial values
GLfloat
theta[NumJointAngles] = {
0.0, // Torso
0.0, // Head1
0.0, // Head2
180.0, // RightUpperArm
0.0, // RightLowerArm
0.0, // LeftUpperArm
0.0, // LeftLowerArm
180.0, // RightUpperLeg
0.0, // RightLowerLeg
180.0, // LeftUpperLeg
0.0 // LeftLowerLeg
};
GLint angle = Head2;
//----------------------------------------------------------------------------
int Index = 0;
void
quad(int a, int b, int c, int d)
{
colors[Index] = vertex_colors[a]; points[Index] = vertices[a]; Index++;
colors[Index] = vertex_colors[a]; points[Index] = vertices[b]; Index++;
colors[Index] = vertex_colors[a]; points[Index] = vertices[c]; Index++;
colors[Index] = vertex_colors[a]; points[Index] = vertices[a]; Index++;
colors[Index] = vertex_colors[a]; points[Index] = vertices[c]; Index++;
colors[Index] = vertex_colors[a]; points[Index] = vertices[d]; Index++;
}
void
colorcube(void)//这里生成单位立方体的六个表面
{
quad(1, 0, 3, 2);
quad(2, 3, 7, 6);
quad(3, 0, 4, 7);
quad(6, 5, 1, 2);
quad(4, 5, 6, 7);
quad(5, 4, 0, 1);
}
//----------------------------------------------------------------------------
void
torso()
{
mvstack.push(model_view);//保存父节点矩阵
mat4 instance = (Translate(0.0, 0.5 * TORSO_HEIGHT, 0.0) *
Scale(TORSO_WIDTH, TORSO_HEIGHT, TORSO_WIDTH));//本节点局部变换矩阵
glUniformMatrix4fv(ModelView, 1, GL_TRUE, model_view * instance);//父节点矩阵*本节点局部变换矩阵
glUniform4fv(draw_color, 1, color_torso);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
model_view = mvstack.pop();//恢复父节点矩阵
}
void
head()
{
mvstack.push(model_view);//保存父节点矩阵
mat4 instance = (Translate(0.0, 0.5 * HEAD_HEIGHT, 0.0) *
Scale(HEAD_WIDTH, HEAD_HEIGHT, HEAD_WIDTH));//本节点局部变换矩阵
glUniformMatrix4fv(ModelView, 1, GL_TRUE, model_view * instance);//父节点矩阵*本节点局部变换矩阵
glUniform4fv(draw_color, 1, color_head);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
model_view = mvstack.pop();//恢复父节点矩阵
}
void
left_upper_arm()
{
mvstack.push(model_view);//保存父节点矩阵
mat4 instance = (Translate(0.0, 0.5 * UPPER_ARM_HEIGHT, 0.0) *
Scale(UPPER_ARM_WIDTH, UPPER_ARM_HEIGHT, UPPER_ARM_WIDTH));//本节点局部变换矩阵
glUniformMatrix4fv(ModelView, 1, GL_TRUE, model_view * instance);//父节点矩阵*本节点局部变换矩阵
glUniform4fv(draw_color, 1, color_left_upper_arm);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
model_view = mvstack.pop();//恢复父节点矩阵
}
void
left_lower_arm()
{
mvstack.push(model_view);//保存父节点矩阵
mat4 instance = (Translate(0.0, 0.5 * LOWER_ARM_HEIGHT, 0.0) *
Scale(LOWER_ARM_WIDTH, LOWER_ARM_HEIGHT, LOWER_ARM_WIDTH));//本节点局部变换矩阵
glUniformMatrix4fv(ModelView, 1, GL_TRUE, model_view * instance);//父节点矩阵*本节点局部变换矩阵
glUniform4fv(draw_color, 1, color_left_lower_arm);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
model_view = mvstack.pop();//恢复父节点矩阵
}
void
right_upper_arm()
{
mvstack.push(model_view);//保存父节点矩阵
mat4 instance = (Translate(0.0, 0.5 * UPPER_ARM_HEIGHT, 0.0) *
Scale(UPPER_ARM_WIDTH, UPPER_ARM_HEIGHT, UPPER_ARM_WIDTH));//本节点局部变换矩阵
glUniformMatrix4fv(ModelView, 1, GL_TRUE, model_view * instance);//父节点矩阵*本节点局部变换矩阵
glUniform4fv(draw_color, 1, color_right_upper_arm);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
model_view = mvstack.pop();//恢复父节点矩阵
}
void
right_lower_arm()
{
mvstack.push(model_view);//保存父节点矩阵
mat4 instance = (Translate(0.0, 0.5 * LOWER_ARM_HEIGHT, 0.0) *
Scale(LOWER_ARM_WIDTH, LOWER_ARM_HEIGHT, LOWER_ARM_WIDTH));//本节点局部变换矩阵
glUniformMatrix4fv(ModelView, 1, GL_TRUE, model_view * instance);//父节点矩阵*本节点局部变换矩阵
glUniform4fv(draw_color, 1, color_right_lower_arm);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
model_view = mvstack.pop();//恢复父节点矩阵
}
void
left_upper_leg()
{
mvstack.push(model_view);//保存父节点矩阵
mat4 instance = (Translate(0.0, 0.5 * UPPER_LEG_HEIGHT, 0.0) *
Scale(UPPER_LEG_WIDTH, UPPER_LEG_HEIGHT, UPPER_LEG_WIDTH));//本节点局部变换矩阵
glUniformMatrix4fv(ModelView, 1, GL_TRUE, model_view * instance);//父节点矩阵*本节点局部变换矩阵
glUniform4fv(draw_color, 1, color_left_upper_leg);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
model_view = mvstack.pop();//恢复父节点矩阵
}
void
left_lower_leg()
{
mvstack.push(model_view);//保存父节点矩阵
mat4 instance = (Translate(0.0, 0.5 * LOWER_LEG_HEIGHT, 0.0) *
Scale(LOWER_LEG_WIDTH, LOWER_LEG_HEIGHT, LOWER_LEG_WIDTH));//本节点局部变换矩阵
glUniformMatrix4fv(ModelView, 1, GL_TRUE, model_view * instance);//父节点矩阵*本节点局部变换矩阵
glUniform4fv(draw_color, 1, color_left_lower_leg);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
model_view = mvstack.pop();//恢复父节点矩阵
}
void
right_upper_leg()
{
mvstack.push(model_view);//保存父节点矩阵
mat4 instance = (Translate(0.0, 0.5 * UPPER_LEG_HEIGHT, 0.0) *
Scale(UPPER_LEG_WIDTH, UPPER_LEG_HEIGHT, UPPER_LEG_WIDTH));//本节点局部变换矩阵
glUniformMatrix4fv(ModelView, 1, GL_TRUE, model_view * instance);//父节点矩阵*本节点局部变换矩阵
glUniform4fv(draw_color, 1, color_right_upper_leg);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
model_view = mvstack.pop();//恢复父节点矩阵
}
void
right_lower_leg()
{
mvstack.push(model_view);//保存父节点矩阵
mat4 instance = (Translate(0.0, 0.5 * LOWER_LEG_HEIGHT, 0.0) *
Scale(LOWER_LEG_WIDTH, LOWER_LEG_HEIGHT, LOWER_LEG_WIDTH));//本节点局部变换矩阵
glUniformMatrix4fv(ModelView, 1, GL_TRUE, model_view * instance);//父节点矩阵*本节点局部变换矩阵
glUniform4fv(draw_color, 1, color_right_lower_leg);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
model_view = mvstack.pop();//恢复父节点矩阵
}
//----------------------------------------------------------------------------
void
display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
model_view = RotateY(theta[Torso]);//躯干变换矩阵
model_view *= Translate(RobotPos.x, RobotPos.y, RobotPos.z);
// std::cout << RobotPos.x << " " << RobotPos.y << " " << RobotPos.z << std::endl;
torso();//躯干绘制
//
mvstack.push(model_view);
model_view *= (Translate(0.0, TORSO_HEIGHT+HEAD_HEIGHT/2, 0.0) *RotateX(theta[Head1]) * RotateY(theta[Head2])*Translate(0,-HEAD_HEIGHT / 2,0));
head();//头部绘制
model_view = mvstack.pop();
//
mvstack.push(model_view);
model_view *= (Translate(-1*(TORSO_WIDTH/*+UPPER_ARM_WIDTH*/)/2,TORSO_HEIGHT, 0.0) *RotateX(theta[LeftUpperArm]));
left_upper_arm();//绘制左上臂1
mvstack.push(model_view);
model_view *= RotateZ(50);
left_upper_arm();//绘制左上臂2
model_view *= (Translate(0.0, UPPER_ARM_HEIGHT, 0.0) *RotateX(theta[LeftLowerArm]));
left_lower_arm();//绘制左下臂2
model_view = mvstack.pop();
model_view *= (Translate(0.0, UPPER_ARM_HEIGHT, 0.0) *RotateX(theta[LeftLowerArm]));
left_lower_arm();//绘制左下臂
model_view = mvstack.pop();
//
mvstack.push(model_view);
model_view *= (Translate((TORSO_WIDTH /*+ UPPER_ARM_WIDTH*/) / 2,TORSO_HEIGHT, 0.0) *RotateX(theta[RightUpperArm]));
right_upper_arm();//绘制右上臂
model_view *= (Translate(0.0, UPPER_ARM_HEIGHT, 0.0) * RotateX(theta[RightLowerArm]));
right_lower_arm();//绘制右下臂
model_view = mvstack.pop();
//
mvstack.push(model_view);
model_view *= (Translate(-0.5*TORSO_WIDTH ,0.0, 0.0) *
RotateX(theta[LeftUpperLeg]));
left_upper_leg();//绘制左上腿
model_view *= (Translate(0.0, UPPER_LEG_HEIGHT, 0.0) *
RotateX(theta[LeftLowerLeg]));
left_lower_leg();//绘制左下腿
model_view = mvstack.pop();
//
mvstack.push(model_view);
model_view *= (Translate(0.5*TORSO_WIDTH,0.0, 0.0) *RotateX(theta[RightUpperLeg]));
right_upper_leg();//绘制右上腿
model_view *= (Translate(0.0, UPPER_LEG_HEIGHT, 0.0) *
RotateX(theta[RightLowerLeg]));
right_lower_leg();//绘制右下腿
model_view = mvstack.pop();
glutSwapBuffers();
}
//----------------------------------------------------------------------------
void
mouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
theta[angle] += 5.0;
if (theta[angle] > 360.0) { theta[angle] -= 360.0; }
}
if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
theta[angle] -= 5.0;
if (theta[angle] < 0.0) { theta[angle] += 360.0; }
}
glutPostRedisplay();
}
//----------------------------------------------------------------------------
void
menu(int option)
{
if (option == Quit) {
exit(EXIT_SUCCESS);
}
angle = option;
}
//----------------------------------------------------------------------------
void
reshape(int width, int height)
{
glViewport(0, 0, width, height);
GLfloat left = -10.0, right = 10.0;
GLfloat bottom = -5.0, top = 15.0;
GLfloat zNear = -10.0, zFar = 10.0;
GLfloat aspect = GLfloat(width) / height;
if (aspect > 1.0) {
left *= aspect;
right *= aspect;
}
else {
bottom /= aspect;
top /= aspect;
}
mat4 projection = Ortho(left, right, bottom, top, zNear, zFar);
glUniformMatrix4fv(Projection, 1, GL_TRUE, projection);
model_view = mat4(1.0); // An Identity matrix
}
//----------------------------------------------------------------------------
void
init(void)
{
colorcube();
// Create a vertex array object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create and initialize a buffer object
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(points) + sizeof(colors),
NULL, GL_DYNAMIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(points), points);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(points), sizeof(colors),
colors);
// Load shaders and use the resulting shader program
GLuint program = InitShader("vshader82.glsl", "fshader82.glsl");
glUseProgram(program);
GLuint vPosition = glGetAttribLocation(program, "vPosition");
glEnableVertexAttribArray(vPosition);
glVertexAttribPointer(vPosition, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(0));
GLuint vColor = glGetAttribLocation(program, "vColor");
glEnableVertexAttribArray(vColor);
glVertexAttribPointer(vColor, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(sizeof(points)));
ModelView = glGetUniformLocation(program, "ModelView");
Projection = glGetUniformLocation(program, "Projection");
draw_color = glGetUniformLocation(program, "draw_color");
glEnable(GL_DEPTH_TEST);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glClearColor(1.0, 1.0, 1.0, 1.0);
}
//----------------------------------------------------------------------------
void
keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 033: // Escape Key
case 'q': case 'Q':
exit(EXIT_SUCCESS);
break;
case 'w':case 'W':
RobotPos.z += 0.2;
break;
case 's':case 'S':
RobotPos.z -= 0.2;
break;
case 'a':case 'A':
RobotPos.x -= 0.2;
break;
case 'd':case 'D':
RobotPos.x += 0.2;
break;
case 'c':case 'C':
theta[angle] += 5.0;
break;
}
glutPostRedisplay();
}
//----------------------------------------------------------------------------
int
main(int argc, char **argv)
{
RobotPos.x = 3;
RobotPos.y = 2;
RobotPos.z = 0;
std::cout << RobotPos.x << " " << RobotPos.y << " " << RobotPos.z << std::endl;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutInitContextVersion(3, 2);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutCreateWindow("robot");
glewExperimental = GL_TRUE;
glewInit();
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
glutCreateMenu(menu);
glutAddMenuEntry("torso", Torso);
glutAddMenuEntry("head1", Head1);
glutAddMenuEntry("head2", Head2);
glutAddMenuEntry("right_upper_arm", RightUpperArm);
glutAddMenuEntry("right_lower_arm", RightLowerArm);
glutAddMenuEntry("left_upper_arm", LeftUpperArm);
glutAddMenuEntry("left_lower_arm", LeftLowerArm);
glutAddMenuEntry("right_upper_leg", RightUpperLeg);
glutAddMenuEntry("right_lower_leg", RightLowerLeg);
glutAddMenuEntry("left_upper_leg", LeftUpperLeg);
glutAddMenuEntry("left_lower_leg", LeftLowerLeg);
glutAddMenuEntry("quit", Quit);
glutAttachMenu(GLUT_MIDDLE_BUTTON);
glutMainLoop();
return 0;
}
vshader:
#version 150
in vec4 vPosition;
in vec4 vColor;
out vec4 color;
uniform mat4 ModelView;
uniform mat4 Projection;
uniform vec4 draw_color;
void main()
{
//color = vColor;
color = draw_color;
gl_Position = Projection*ModelView*vPosition;
}
fshader:
#version 150
in vec4 color;
out vec4 fColor;
void main()
{
fColor = color;
}