【OpenGL】绘制2D机器人并实现二维变换的综合运用
1.绘制目标
绘制2D机器人并实现二维变换的综合运用
2.核心代码
2.1 绘制矩形
void _init()
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}
/// <summary>
/// 绘制矩形
/// </summary>
/// <param name="x">左上角点的x坐标</param>
/// <param name="y">左上角点的y坐标</param>
/// <param name="height">矩形的高度</param>
/// <param name="width">矩形的宽度</param>
/// <param name="_R">颜色R</param>
/// <param name="_G">颜色G</param>
/// <param name="_B">颜色B</param>
void drawRectangle(double x, double y, double height, double width, double _R, double _G, double _B)
{
glColor3f(_R, _G, _B);
glBegin(GL_TRIANGLE_STRIP);
glVertex2f(x, y);
glVertex2f(x, y - height);
glVertex2f(x + width, y);
glVertex2f(x + width, y - height);
glEnd();
}
2.2 绘制机器人的躯体
/// <summary>
/// 绘制机器人的躯体
/// </summary>
/// <param name="base_x">左上角点的x坐标</param>
/// <param name="base_y">左上角点的y坐标</param>
/// <param name="height">矩形的高度</param>
/// <param name="width">矩形的宽度</param>
/// <param name="stickLength">长度</param>
/// <param name="_R">颜色R</param>
/// <param name="_G">颜色G</param>
/// <param name="_B">颜色B</param>
void drawRobotBodyPart(double base_x, double base_y, double height, double width, double stickLength, double _R, double _G, double _B)
{
drawRectangle(base_x, base_y, height, width, _R, _G, _B);
double bodyStart_height = stickLength;
double bodyStart_width = sqrt(width / 40);
double bodyStart_x = base_x + width / 2 - bodyStart_width / 2;
double bodyStart_y = base_y;
drawRectangle(bodyStart_x, bodyStart_y + bodyStart_height, bodyStart_height, bodyStart_width, _R, _G, _B);
}
2.3 绘制机器人的手臂
/// <summary>
/// 绘制机器人的手臂
/// </summary>
/// <param name="base_x">左上角点的x坐标</param>
/// <param name="base_y">左上角点的y坐标</param>
/// <param name="height">矩形的高度</param>
/// <param name="width">矩形的宽度</param>
/// <param name="stickLength">长度</param>
/// <param name="_R">颜色R</param>
/// <param name="_G">颜色G</param>
/// <param name="_B">颜色B</param>
void drawRobotHand(double base_x, double base_y, double height, double width, double stickLength, double _R, double _G, double _B)
{
glPushMatrix();
glRotated(5, 0, 0, 1);
glTranslated(-width, -height - 2.5 * stickLength, 0);
drawRobotBodyPart(base_x, base_y, height, width, stickLength * 0.8, _R, _G, _B);
glPopMatrix();
drawRobotBodyPart(base_x, base_y, height, width, stickLength, _R, _G, _B);
}
2.4 绘制机器人的脚
/// <summary>
/// 绘制机器人的脚
/// </summary>
/// <param name="base_x">左上角点的x坐标</param>
/// <param name="base_y">左上角点的y坐标</param>
/// <param name="height">矩形的高度</param>
/// <param name="width">矩形的宽度</param>
/// <param name="stickLength">长度</param>
/// <param name="_R">颜色R</param>
/// <param name="_G">颜色G</param>
/// <param name="_B">颜色B</param>
void drawRobotLeg(double base_x, double base_y, double height, double width, double stickLength, double _R, double _G, double _B)
{
drawRobotBodyPart(base_x, base_y, height, width, stickLength, _R, _G, _B);
drawRobotBodyPart(base_x, base_y - height - stickLength * 0.8, height, width, stickLength, _R, _G, _B);
}
2.5 绘制圆面
/// <summary>
/// 绘制圆面
/// </summary>
/// <param name="r">圆面半径</param>
/// <param name="circle_x">圆面x坐标</param>
/// <param name="circle_y">圆面y坐标</param>
/// <param name="_R">颜色R</param>
/// <param name="_G">颜色G</param>
/// <param name="_B">颜色B</param>
void DrawCirclePointGpBlackSet(double r, double circle_x, double circle_y, double _R, double _G, double _B)
{
glColor3f(_R, _G, _B);
glBegin(GL_TRIANGLE_FAN);
for (double i = -r; i <= r; i += 0.001)
{
double x = i;
double y = sqrt(r * r - x * x);
glVertex2f(x + circle_x, y + circle_y);
}
for (double i = r; i >= -r; i -= 0.001)
{
double x = i;
double y = sqrt(r * r - x * x);
glVertex2f(x + circle_x, -y + circle_y);
}
for (double i = -r; i <= r; i += 0.001)
{
double x = i;
double y = sqrt(r * r - x * x);
glVertex2f(x + circle_x, y + circle_y);
}
glEnd();
}
2.6 绘制圆弧
/// <summary>
/// 绘制圆弧
/// </summary>
/// <param name="r">圆面半径</param>
/// <param name="circle_x">圆面x坐标</param>
/// <param name="circle_y">圆面y坐标</param>
/// <param name="_R">颜色R</param>
/// <param name="_G">颜色G</param>
/// <param name="_B">颜色B</param>
void DrawArcPointGpSet(double r, double circle_x, double circle_y, double _R, double _G, double _B)
{
glColor3f(_R, _G, _B);
glBegin(GL_LINE_STRIP);
for (double i = r; i >= -r; i -= 0.001)
{
double x = i;
double y = sqrt(r * r - x * x);
glVertex2f(x + circle_x, -y + circle_y);
}
glEnd();
}
2.7 绘制脸蛋
/// <summary>
/// 绘制脸蛋
/// </summary>
/// <param name="face_x">脸蛋的x坐标</param>
/// <param name="face_y">脸蛋的y坐标</param>
/// <param name="face_r">脸蛋的半径坐标</param>
void DrawFace(double face_x, double face_y, double face_r)
{
glPushMatrix();
// 黄色的脸蛋
DrawCirclePointGpBlackSet(face_r, face_x, face_y, 255, 215, 0);
// 黑色的眼睛
DrawCirclePointGpBlackSet(face_r / 6, face_x - face_r / 3, face_y + face_r / 10, 0, 0, 0);
DrawCirclePointGpBlackSet(face_r / 6, face_x + face_r / 3, face_y + face_r / 10, 0, 0, 0);
// 红色嘴巴
DrawArcPointGpSet(face_r / 3, face_x, face_y - face_r / 3, 255, 0, 0);
glPopMatrix();
}
2.8 键盘响应
void KeyBoards(int key, int x, int y)
{
switch (key)
{
case GLUT_KEY_UP:
glMatrixMode(GL_MODELVIEW);
glTranslated(xDir, ++yDir, zDir);
glutPostRedisplay();
break;
case GLUT_KEY_LEFT:
glMatrixMode(GL_MODELVIEW);
glTranslated(--xDir, yDir, zDir);
glutPostRedisplay();
break;
case GLUT_KEY_DOWN:
glMatrixMode(GL_MODELVIEW);
glTranslated(xDir, --yDir, zDir);
glutPostRedisplay();
break;
case GLUT_KEY_RIGHT:
glMatrixMode(GL_MODELVIEW);
glTranslated(++xDir, yDir, zDir);
glutPostRedisplay();
break;
case GLUT_KEY_INSERT:
glMatrixMode(GL_MODELVIEW);
glRotatef(++angle, 0, 0, 1);
glutPostRedisplay();
break;
case GLUT_KEY_END:
glMatrixMode(GL_MODELVIEW);
glRotatef(--angle, 0, 0, 1);
glutPostRedisplay();
break;
}
}
2.9 绘制2D机器人
void DrawRobot()
{
glPushMatrix();
glRotated(70, 0, 0, 1);
glTranslated(0, -1.2, 0);
drawRobotHand(3, 0, 1.8, 0.8, 0.5, 0.5, 0, 1);
glPopMatrix();
glPushMatrix();
glRotated(-70, 0, 0, 1);
glTranslated(-7, -1, 0);
drawRobotHand(3, 0, 1.8, 0.8, 0.5, 0.5, 0, 1);
glPopMatrix();
drawRobotLeg(-1.5, -2.3, 2, 1, 0.5, 1, 0, 0);
drawRobotLeg(0.5, -2.3, 2, 1, 0.5, 1, 0, 0);
drawRobotBodyPart(-2, 4, 6, 4, 0.5, 0, 0, 1);
DrawFace(0, 5.7, 1.5);
}
3.全部代码
#define GLEW_STATIC
#define FREEGLUT_STATIC
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <GL/glext.h>
#include <math.h>
GLdouble xDir = 0.0;
GLdouble yDir = 0.0;
GLdouble zDir = 0.0;
GLfloat angle = 0.0;
void _init()
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}
/// <summary>
/// 绘制矩形
/// </summary>
/// <param name="x">左上角点的x坐标</param>
/// <param name="y">左上角点的y坐标</param>
/// <param name="height">矩形的高度</param>
/// <param name="width">矩形的宽度</param>
/// <param name="_R">颜色R</param>
/// <param name="_G">颜色G</param>
/// <param name="_B">颜色B</param>
void drawRectangle(double x, double y, double height, double width, double _R, double _G, double _B)
{
glColor3f(_R, _G, _B);
glBegin(GL_TRIANGLE_STRIP);
glVertex2f(x, y);
glVertex2f(x, y - height);
glVertex2f(x + width, y);
glVertex2f(x + width, y - height);
glEnd();
}
/// <summary>
/// 绘制机器人的躯体
/// </summary>
/// <param name="base_x">左上角点的x坐标</param>
/// <param name="base_y">左上角点的y坐标</param>
/// <param name="height">矩形的高度</param>
/// <param name="width">矩形的宽度</param>
/// <param name="stickLength">长度</param>
/// <param name="_R">颜色R</param>
/// <param name="_G">颜色G</param>
/// <param name="_B">颜色B</param>
void drawRobotBodyPart(double base_x, double base_y, double height, double width, double stickLength, double _R, double _G, double _B)
{
drawRectangle(base_x, base_y, height, width, _R, _G, _B);
double bodyStart_height = stickLength;
double bodyStart_width = sqrt(width / 40);
double bodyStart_x = base_x + width / 2 - bodyStart_width / 2;
double bodyStart_y = base_y;
drawRectangle(bodyStart_x, bodyStart_y + bodyStart_height, bodyStart_height, bodyStart_width, _R, _G, _B);
}
/// <summary>
/// 绘制机器人的手臂
/// </summary>
/// <param name="base_x">左上角点的x坐标</param>
/// <param name="base_y">左上角点的y坐标</param>
/// <param name="height">矩形的高度</param>
/// <param name="width">矩形的宽度</param>
/// <param name="stickLength">长度</param>
/// <param name="_R">颜色R</param>
/// <param name="_G">颜色G</param>
/// <param name="_B">颜色B</param>
void drawRobotHand(double base_x, double base_y, double height, double width, double stickLength, double _R, double _G, double _B)
{
glPushMatrix();
glRotated(5, 0, 0, 1);
glTranslated(-width, -height - 2.5 * stickLength, 0);
drawRobotBodyPart(base_x, base_y, height, width, stickLength * 0.8, _R, _G, _B);
glPopMatrix();
drawRobotBodyPart(base_x, base_y, height, width, stickLength, _R, _G, _B);
}
/// <summary>
/// 绘制机器人的脚
/// </summary>
/// <param name="base_x">左上角点的x坐标</param>
/// <param name="base_y">左上角点的y坐标</param>
/// <param name="height">矩形的高度</param>
/// <param name="width">矩形的宽度</param>
/// <param name="stickLength">长度</param>
/// <param name="_R">颜色R</param>
/// <param name="_G">颜色G</param>
/// <param name="_B">颜色B</param>
void drawRobotLeg(double base_x, double base_y, double height, double width, double stickLength, double _R, double _G, double _B)
{
drawRobotBodyPart(base_x, base_y, height, width, stickLength, _R, _G, _B);
drawRobotBodyPart(base_x, base_y - height - stickLength * 0.8, height, width, stickLength, _R, _G, _B);
}
/// <summary>
/// 绘制圆面
/// </summary>
/// <param name="r">圆面半径</param>
/// <param name="circle_x">圆面x坐标</param>
/// <param name="circle_y">圆面y坐标</param>
/// <param name="_R">颜色R</param>
/// <param name="_G">颜色G</param>
/// <param name="_B">颜色B</param>
void DrawCirclePointGpBlackSet(double r, double circle_x, double circle_y, double _R, double _G, double _B)
{
glColor3f(_R, _G, _B);
glBegin(GL_TRIANGLE_FAN);
for (double i = -r; i <= r; i += 0.001)
{
double x = i;
double y = sqrt(r * r - x * x);
glVertex2f(x + circle_x, y + circle_y);
}
for (double i = r; i >= -r; i -= 0.001)
{
double x = i;
double y = sqrt(r * r - x * x);
glVertex2f(x + circle_x, -y + circle_y);
}
for (double i = -r; i <= r; i += 0.001)
{
double x = i;
double y = sqrt(r * r - x * x);
glVertex2f(x + circle_x, y + circle_y);
}
glEnd();
}
/// <summary>
/// 绘制圆弧
/// </summary>
/// <param name="r">圆面半径</param>
/// <param name="circle_x">圆面x坐标</param>
/// <param name="circle_y">圆面y坐标</param>
/// <param name="_R">颜色R</param>
/// <param name="_G">颜色G</param>
/// <param name="_B">颜色B</param>
void DrawArcPointGpSet(double r, double circle_x, double circle_y, double _R, double _G, double _B)
{
glColor3f(_R, _G, _B);
glBegin(GL_LINE_STRIP);
for (double i = r; i >= -r; i -= 0.001)
{
double x = i;
double y = sqrt(r * r - x * x);
glVertex2f(x + circle_x, -y + circle_y);
}
glEnd();
}
/// <summary>
/// 绘制脸蛋
/// </summary>
/// <param name="face_x">脸蛋的x坐标</param>
/// <param name="face_y">脸蛋的y坐标</param>
/// <param name="face_r">脸蛋的半径坐标</param>
void DrawFace(double face_x, double face_y, double face_r)
{
glPushMatrix();
// 黄色的脸蛋
DrawCirclePointGpBlackSet(face_r, face_x, face_y, 255, 215, 0);
// 黑色的眼睛
DrawCirclePointGpBlackSet(face_r / 6, face_x - face_r / 3, face_y + face_r / 10, 0, 0, 0);
DrawCirclePointGpBlackSet(face_r / 6, face_x + face_r / 3, face_y + face_r / 10, 0, 0, 0);
// 红色嘴巴
DrawArcPointGpSet(face_r / 3, face_x, face_y - face_r / 3, 255, 0, 0);
glPopMatrix();
}
void KeyBoards(int key, int x, int y)
{
switch (key)
{
case GLUT_KEY_UP:
glMatrixMode(GL_MODELVIEW);
glTranslated(xDir, ++yDir, zDir);
glutPostRedisplay();
break;
case GLUT_KEY_LEFT:
glMatrixMode(GL_MODELVIEW);
glTranslated(--xDir, yDir, zDir);
glutPostRedisplay();
break;
case GLUT_KEY_DOWN:
glMatrixMode(GL_MODELVIEW);
glTranslated(xDir, --yDir, zDir);
glutPostRedisplay();
break;
case GLUT_KEY_RIGHT:
glMatrixMode(GL_MODELVIEW);
glTranslated(++xDir, yDir, zDir);
glutPostRedisplay();
break;
case GLUT_KEY_INSERT:
glMatrixMode(GL_MODELVIEW);
glRotatef(++angle, 0, 0, 1);
glutPostRedisplay();
break;
case GLUT_KEY_END:
glMatrixMode(GL_MODELVIEW);
glRotatef(--angle, 0, 0, 1);
glutPostRedisplay();
break;
}
}
void DrawRobot()
{
glPushMatrix();
glRotated(70, 0, 0, 1);
glTranslated(0, -1.2, 0);
drawRobotHand(3, 0, 1.8, 0.8, 0.5, 0.5, 0, 1);
glPopMatrix();
glPushMatrix();
glRotated(-70, 0, 0, 1);
glTranslated(-7, -1, 0);
drawRobotHand(3, 0, 1.8, 0.8, 0.5, 0.5, 0, 1);
glPopMatrix();
drawRobotLeg(-1.5, -2.3, 2, 1, 0.5, 1, 0, 0);
drawRobotLeg(0.5, -2.3, 2, 1, 0.5, 1, 0, 0);
drawRobotBodyPart(-2, 4, 6, 4, 0.5, 0, 0, 1);
DrawFace(0, 5.7, 1.5);
}
void display() {
glClear(GL_COLOR_BUFFER_BIT);
//DrawFace(0, 0, 3);
DrawRobot();
glutSwapBuffers();
}
void reshape(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-8.f, 8.f, -8.f, 8.f);
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitContextVersion(3, 3);
glutInitContextProfile(GLUT_COMPATIBILITY_PROFILE);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowPosition(0, 0); // 左上角相对位置
glutInitWindowSize(600, 600); // 窗口大小
glutCreateWindow("OpenGL");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glewExperimental = GL_TRUE;
glewInit();
_init();
glutSpecialFunc(&KeyBoards); //注册键盘事件(特殊字符)
glutDisplayFunc(&display); //回调函数
glutMainLoop();
return 0;
}
4.运行结果