真实感图形绘制

【实验目的】

1. 学习了解真实感图形绘制相关函数。

2. 学习了解真实感图形绘制流程。

【实验原理】

【实验题目】

1. 练习OpenGL中加光照:给chap10-1.cpp中的函数加注释并运行结果。

#include <windows.h>

#include <gl/glut.h>

// 设置材质和光源属性

void Initial(void)

{

    // 定义材质属性

    GLfloat mat_ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f };

    GLfloat mat_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };

    GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };

    GLfloat mat_shininess[] = { 50.0f };

    

    // 定义光源属性

    GLfloat light0_diffuse[] = { 0.0f, 0.0f, 1.0f, 1.0f };  // 漫反射的蓝色点光源

    GLfloat light0_position[] = { 1.0f, 1.0f, 1.0f, 0.0f };

    

    GLfloat light1_ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f };

    GLfloat light1_diffuse[] = { 1.0f, 0.0f, 0.0f, 1.0f };  // 红色聚光光源

    GLfloat light1_specular[] = { 1.0f, 0.6f, 0.6f, 1.0f };

    GLfloat light1_position[] = { -3.0f, -3.0f, 3.0f, 1.0f };

    GLfloat spot_direction[] = { 1.0f, 1.0f, -1.0f };

    // 设置材质属性

    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);

    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);

    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);

    // 设置光源属性,light0为漫反射的蓝色点光源

    glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);

    glLightfv(GL_LIGHT0, GL_POSITION, light0_position);

//light1为红色聚光光源

    glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);

    glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);

    glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular);

    glLightfv(GL_LIGHT1, GL_POSITION, light1_position);

    glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 30.0);

    glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, spot_direction);

    // 启用光照和深度测试

    glEnable(GL_LIGHTING);

    glEnable(GL_LIGHT0);

    glEnable(GL_LIGHT1);

    glEnable(GL_DEPTH_TEST);

    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

}

// 窗口大小变化时的回调函数

void ChangeSize(GLsizei w, GLsizei h)

{

    if (h == 0) h = 1;

    glViewport(0, 0, w, h);

    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

    if (w <= h)

        glOrtho(-5.5f, 5.5f, -5.5f * h / w, 5.5f * h / w, -10.0f, 10.0f);

    else

        glOrtho(-5.5f * w / h, 5.5f * w / h, -5.5f, 5.5f, -10.0f, 10.0f);

    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

}

// 渲染函数

void Display(void)

{

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();

    glTranslated(-3.0f, -3.0f, 3.0f);

    glPopMatrix();

    glutSolidSphere(2.0f, 50, 50);

    glFlush();

}

// 主函数

void main(int argc, char* argv[])

{

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

    glutCreateWindow("多光源球");

    glutDisplayFunc(Display);

    glutReshapeFunc(ChangeSize);

    Initial();

  1. 制作旋转飞机模型,学习示例程序chap10-2.cpp,为函数加注释并运行结果。

#include <GL/glut.h>

void Cube() //正方体

{

glBegin(GL_QUAD_STRIP);//填充凸多边形

glVertex3f(0.0f, 0.0f, 0.0f);

glVertex3f(0.0f, 1.0f, 0.0f);

glVertex3f(1.0f, 0.0f, 0.0f);

glVertex3f(1.0f, 1.0f, 0.0f);

glVertex3f(1.0f, 0.0f, -1.0f);

glVertex3f(1.0f, 1.0f, -1.0f);

glVertex3f(0.0f, 0.0f, -1.0f);

glVertex3f(0.0f, 1.0f, -1.0f);

glVertex3f(0.0f, 0.0f, 0.0f);

glVertex3f(0.0f, 1.0f, 0.0f);

glEnd();

glBegin(GL_QUAD_STRIP);

glVertex3f(0.0f, 0.0f, 0.0f);

glVertex3f(1.0f, 0.0f, 0.0f);

glVertex3f(0.0f, 0.0f, -1.0f);

glVertex3f(1.0f, 0.0f, -1.0f);

glVertex3f(0.0f, 1.0f, 0.0f);

glVertex3f(1.0f, 1.0f, 0.0f);

glVertex3f(0.0f, 1.0f, -1.0f);

glVertex3f(1.0f, 1.0f, -1.0f);

glEnd();

}

void Circle() //圆面

{

glBegin(GL_TRIANGLE_FAN);//扇形连续填充三角形串

glVertex3f(0.0f, 0.0f, 0.0f);

int i = 0;

for (i = 0; i <= 375; i += 15)

{

float p = i * 3.14 / 180;

glVertex3f(sin(p), cos(p), 0.0f);

}

glEnd();

}

void Cylinder() //圆柱

{

glBegin(GL_QUAD_STRIP);//连续填充四边形串

int i = 0;

for (i = 0; i <= 375; i += 15)

{

float p = i * 3.14 / 180;

glVertex3f(sin(p), cos(p), 1.0f);

glVertex3f(sin(p), cos(p), 0.0f);

}

glEnd();

Circle();

glTranslatef(0, 0, 1);

Circle();

}

void Cone() //圆锥

{

glBegin(GL_QUAD_STRIP);//连续填充四边形串

int i = 0;

for (i = 0; i <= 390; i += 15)

{

float p = i * 3.14 / 180;

glVertex3f(0, 0, 1.0f);

glVertex3f(sin(p), cos(p), 0.0f);

}

glEnd();

Circle();

}

//函数中,通过使用不同的变换和颜色设置,绘制了飞机的各个部分,包括螺旋桨、机身、圆柱体和圆锥体等。

void AirPlane(float x, float y, float z) {

static float i = 0, f = 0;

i += 0.1;

f += 0.01;

if (i > 360)

i = 0;

if (f > 360)

f = 0;

glPushMatrix();

    glTranslatef(x, y, z); // 平移飞机位置

    glRotatef(f, 1, 1, 1); // 绕着飞机中心旋转

    glPushMatrix(); // 保存当前模型视图矩阵

    glColor3f(0.5, 1.5, 0.5); // 设置颜色

    glRotatef(i, 0, 1, 0); // 绕y轴旋转

    glTranslatef(0, 0, 0.5); // 平移位置

    glScalef(0.1, 0.05, 1); // 缩放

    Cube(); // 绘制螺旋桨

    glPopMatrix(); // 恢复之前保存的模型视图矩阵

    glTranslatef(0, -0.1, 0); // 平移位置

    glScalef(0.1, 0.1, 0.1); // 缩放

    Cube(); // 绘制机身

    glScalef(10, 10, 10); // 恢复缩放

    // 绘制圆柱体

    glColor3f(1, 0, 1); // 设置颜色

    glTranslatef(0.04, -0.05, -0.9); // 平移位置

    glScalef(0.1, 0.1, 1.5); // 缩放

    Cylinder();

    // 绘制圆锥体

    glColor3f(0, 1, 0); // 设置颜色

    glScalef(1, 1, 0.2); // 缩放

    Cone();

    // 绘制尾部

    glColor3f(0, 1, 1); // 设置颜色

    glTranslatef(0, 0.7, -4.5); // 平移位置

    glScalef(0.2, 2, 1); // 缩放

    Cube();

    // 绘制翅膀

    glTranslatef(-13, 0.3, 0); // 平移位置

    glScalef(27, 0.1, 1); // 缩放

    Cube();

}

//renderScene函数中进行场景的绘制和渲染

void renderScene(void) {

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity(); // 重置模型视图矩阵

    AirPlane(0, 0, -3); // 绘制飞机

    glutSwapBuffers(); // 交换缓冲区

}

//changeSize函数用于处理窗口大小改变时的操作

void changeSize(int w, int h) {

    if (h == 0)

        h = 1;

    float ratio = 1.0 * w / h;

    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

    glViewport(0, 0, w, h);

    gluPerspective(45, ratio, 1, 1000);

    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

    gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, -1.0, 0.0f, 1.0f, 0.0f);

}

int main(int argc, char* argv[]) {

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);

    glutInitWindowPosition(100, 100);

    glutInitWindowSize(320, 320);

    glutCreateWindow("Hello OpenGL");

    glutDisplayFunc(renderScene);

    glutIdleFunc(renderScene);

    glutReshapeFunc(changeSize);

    glEnable(GL_DEPTH_TEST);

    glutMainLoop();

    return 0;

}

2. 编程实现:

1)设计并画出一个花盆(二维或三维);

2)让其做自由落体运动,并实现在地面上的弹跳效果,并逐渐停止,用键盘切换左右运动方向。

#include <GL/glut.h>

#include <math.h>

float potHeight = -5.0; // 花瓶的高度

float potPosX = 0.0; // 花瓶的初始水平位置

float potPosY = 7.0; // 花瓶的初始垂直位置

float potVelocityY = 0.0; // 花瓶的初始垂直速度

float gravity = -0.01; // 重力加速度

float damping = 0.7; // 弹跳时的速度损耗系数

float potSize = 1.0; // 花瓶的大小

void init(void) {

    glClearColor(1.0, 1.0, 1.0, 0.0);

    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

    glOrtho(-10.0, 10.0, -10.0, 10.0, -10.0, 10.0);

    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

}

void update(int value) {

    // 更新花瓶的位置和速度

    potPosY += potVelocityY;

    potVelocityY += gravity;

    // 处理花瓶触地时的弹跳效果

    if (potPosY < potHeight) {

        potPosY = potHeight; // 限制花瓶的高度不低于地面

        if (fabs(potVelocityY) > 0.01) { // 当速度绝对值大于0.5时进行反弹

            potVelocityY = -potVelocityY * damping;

        }

        else {

            potVelocityY = 0.0; // 速度较低时,不再反弹

        }

    }

    glutPostRedisplay();

    glutTimerFunc(16, update, 0); // 设置下一帧的更新

}

void drawFlowerPot(void) {

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glColor3f(0.8, 0.6, 0.4); // 设置花瓶的颜色为棕色

    glPushMatrix();

    glTranslatef(potPosX, potPosY, 0.0);

    glBegin(GL_QUADS);

    glVertex2f(-2.0, 0.0); // 花瓶的底部

    glVertex2f(2.0, 0.0); // 花瓶的底部

    glVertex2f(1.0, 4.0); // 花瓶的右侧

    glVertex2f(-1.0, 4.0); // 花瓶的左侧

    glEnd();

    glPopMatrix();

    glutSwapBuffers();

}

void handleKeypress(unsigned char key, int x, int y) {

    switch (key) {

    case 'a':

        potPosX -= 0.5; // 按下a键,花瓶向左移动

        break;

    case 'd':

        potPosX += 0.5; // 按下d键,花瓶向右移动

        break;

    }

}

int main(int argc, char** argv) {

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

    glutInitWindowSize(500, 500);

    glutCreateWindow("Flower Pot");

    init();

    glutDisplayFunc(drawFlowerPot);

    glutTimerFunc(16, update, 0); // 设置定时器用于更新花瓶的位置和速度

    glutKeyboardFunc(handleKeypress); // 捕获键盘输入

    glutMainLoop();

    return 0;

}

  • 17
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值