【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)

这篇具有很好参考价值的文章主要介绍了【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

实 验 报 告

一、实验目的

  1. 掌握三维图形的显示原理和方法,掌握三维观察的原理和方法;
  2. 掌握OpenGL中矩阵堆栈函数的使用,会使用堆栈函数进行复杂场景的组装。
  3. 掌握OpenGL中三维观察变换常用的函数的使用方法,了解三维模型的贴图方法;
  4. 掌握自由曲线的生成方法,熟练掌握B样条曲线的生成原理、方法和特点。

二、实验内容与实验步骤

太阳系:

使用线框球体绘制函数实现球体绘制。当按下键盘“D”或“d”时,行星将实现自转;按下键盘“Y”或“y”时,行星将绕太阳公转。实现以下两个内容:

(1)给行星加上卫星;

(2)实现自动旋转功能,即卫星绕行星自动旋转、行星自动自传同时绕太阳公转。

(3)(选做)程序例子2是一个粘贴了纹理图像的自转的地球的例子(位图文件见实验任务附件ear.bmp),理解其中的纹理图像装载和使用方法,自制贴图图片,仿照这个程序编写九大行星运行的3D动画。

B样条曲线绘制:

在OpenGL 中实现动态输入任意多个控制点(控制点个数大于等于4),采用三次参数样条曲线,按照分段拼接的方式生成逼近任意多个控制点组成的多边形的光滑曲线。并按照给定的控制点个数绘制B样条曲线。

基函数递归公式为:

【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)

取,

【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)

将上式带入B样条定义式得:

其中一段3次参数B样条曲线由四个控制点P0、P1、P2和P3生成,调和矩阵为中间的4*4矩阵,在编写程序时尽量考虑减少无用的运算,尽量提高运算的效率。

要求生成曲线的过程按照下面的交互方式输入:

(1)在控制点输入状态下,点击左键,增加一个控制点,并绘制上一个控制点到当前控制点的连线。

(2)点击左键增加一个控制点,点击右键按照已选择的控制点生成B样条曲线。

(3)设置一种控制键的处理可以清除屏幕上的图形,重新进行控制点输入状态。

三、实验环境

  1. 操作系统:macOS Big Sur Version 11.6
  2. 调试软件:Xcode Version 13.0
  3. 上机地点:信息楼Bxxx
  4. 机器台号:xx

四、实验过程与分析

地球公转&自转:

首先单实现地球绕太阳的公转和自转。使用线框球体绘制函数实现球体绘制。当按下键盘“D”或“d”时,行星将实现自转;按下键盘“Y”或“y”时,行星将绕太阳公转。

太阳系:

坐标变换过程:

        太阳:不变,在中心即可。

        地球:用循环改变SolarAngle的值,调用glRotatef()函数实现公转;

                用循环改变OwnAxisAngle的值,调用glRotatef()实现自转;

                调用glTranslatef()函数将其平移至公转轨道,并随时间在轨道上改变位置。

        月球:类似地球的坐标变换过程。

【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)

函数作用:

 【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)

以上函数的功能分别是:加载贴图;控制台显示提示;绘制太阳;初始化;绘制图形;调整图形;键盘与鼠标的事件;主函数。

具体实现见代码中的注释:

load_texture()函数:

int load_texture(const char* file_name, int width, int height, int depth, GLenum colour_type, GLenum filter_type)
{
    
    GLubyte* raw_bitmap;
    FILE* file;
    
    //if ((file = fopen_s(file_name, "rb")) == NULL)
    if ((file = fopen(file_name, "rb")) == NULL)
    {
        return 1;
    }
    raw_bitmap = (GLubyte*)malloc(width * height * depth * (sizeof(GLubyte)));
    
    if (raw_bitmap == NULL)
    {
        fclose(file);
        return 2;
    }
    
    fread(raw_bitmap, width * height * depth, 1, file);
    fclose(file);
    
    //  设置过滤类型
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter_type);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter_type);
    
    //  设置纹理环境
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    
    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, colour_type,
                      GL_UNSIGNED_BYTE, raw_bitmap);
    
    free(raw_bitmap);
    glDisable(GL_TEXTURE_2D);
    return 0;
}

Load_texture()函数:

void LoadTextures(GLuint texture_id, int MaxNrOfTextures)
{
    // 第一种纹理
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //控制所读取数据的对齐方式
    glGenTextures(MaxNrOfTextures, &texture_id); // 生成纹理的数量-MaxNrOfTextures 存储纹理索引-texture_id
    glBindTexture(GL_TEXTURE_2D, 1); //将一个命名的纹理绑定到一个纹理目标上
    if (load_texture("/Users/kqp12_27/Desktop/Xcode-OpenGL/Mouse copy 12/Mouse/ear.bmp", 512, 128, 3, GL_BGR_EXT, GL_NEAREST)) //读取此bmp文件
    {
        exit(1);
    }
    
    // 第二种纹理
    glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
    glGenTextures(MaxNrOfTextures, &texture_id);
    glBindTexture(GL_TEXTURE_2D, 2);
    if (load_texture("/Users/kqp12_27/Desktop/一些课📖/计图实验/实验三/太阳系/moon copy.bmp",88,63, 3, GL_BGR_EXT, GL_NEAREST))
    {
        exit(1);
    }
    
    // 第三种纹理
    glPixelStorei(GL_UNPACK_ALIGNMENT, 3);
    glGenTextures(MaxNrOfTextures, &texture_id);
    glBindTexture(GL_TEXTURE_2D, 3);
    if (load_texture("/Users/kqp12_27/Desktop/一些课📖/计图实验/实验三/太阳系/sun.bmp",500, 400, 3, GL_BGR_EXT, GL_NEAREST))
    {
        exit(1);
    }
    
}

init()函数:

void init(void)
{
    //地球
    Planet1.size = 0.4f;
    Planet1.sections = 16.0f;
    Planet1.posX = 0.0f;
    Planet1.posY = 0.0f;
    Planet1.posZ = 1.4f;
    Planet1.OwnAxisAngle = 0.0f;
    Planet1.SolarAngle = 60.0f;
    Planet1.TextureID = 1;
    
    //月球
    Planet2.size = 0.2f;
    Planet2.sections = 16.0f;
    Planet2.posX = 0.0f;
    Planet2.posY = 0.0f;
    Planet2.posZ = 1.4f;
    Planet2.OwnAxisAngle = 0.0f;
    Planet2.SolarAngle = 60.0f;
    Planet2.TextureID = 2;
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_FLAT);

    LoadTextures(texture_id1, 1);
    
    glEnable(GL_TEXTURE_2D);
    
    glClearDepth(1.0f);                                                    // 设置深度缓存
    glDepthFunc(GL_LEQUAL);                                                // 选择深度测试方式
    glEnable(GL_DEPTH_TEST);                                            // 开启深度测试
    glShadeModel(GL_SMOOTH);                                            // 阴暗处理采用平滑方式
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);                    // 最精细的透视计算
    
    return;
}

display()函数:

void display(void)
{
    
    // 地球公转
    Planet1.SolarAngle += 1.0f * ROTATION_SPEED;
    if (Planet1.SolarAngle >= 360) { Planet1.SolarAngle -= 360; }
    
    // 地球自转
    Planet1.OwnAxisAngle += 0.5f;
    if (Planet1.OwnAxisAngle >= 360) { Planet1.OwnAxisAngle -= 360; }
    
    // 月球公转
    Planet2.SolarAngle += 7.0f * ROTATION_SPEED;
    if (Planet2.SolarAngle >= 360) { Planet2.SolarAngle -= 360; }
    
    // 月球自转
    Planet2.OwnAxisAngle += 1.0f;
    if (Planet2.OwnAxisAngle >= 360) { Planet2.OwnAxisAngle -= 360; }

    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);                    // 清除颜色和深度缓存
    glColor3f(1.0, 0.0, 0.0);
    glColor3f(1.0, 1.0, 1.0);
    glColor3f(0.7f, 0.7f, 0.7f);
    glBegin(GL_LINE_LOOP);
    
    // 绘制轨道
    for (int l = 0; l < 360; l++)
    {
        glVertex3f((float)cos(l * ((float)3.14159 / (float)180)) * Planet1.posZ, 0.0f, (float)sin(l * ((float)3.14159 / (float)180)) * Planet1.posZ);
        
    }
    glEnd();
    
    glPushMatrix();
    
    // 地球
    // 坐标变换,使地球在公转轨道上转
    glRotatef(Planet1.SolarAngle, 0, -1, 0); //旋转
    glTranslatef(Planet1.posX, Planet1.posY, Planet1.posZ); //平移
    glRotatef(Planet1.OwnAxisAngle, 0, -1, 0);
    
    glBindTexture(GL_TEXTURE_2D, 1); //设置纹理
    
    GLUquadricObj* q = gluNewQuadric();
    gluQuadricDrawStyle(q, GLU_FILL);
    gluQuadricNormals(q, GLU_SMOOTH);
    gluQuadricTexture(q, GL_TRUE);
    gluSphere(q, Planet1.size, 50, 40); //画球
    gluDeleteQuadric(q);
    glBindTexture(GL_TEXTURE_2D, 0);


    // 月球
    glRotatef(Planet2.SolarAngle, 0, 1, 0);
    glTranslatef(0.5*Planet2.posX, 0.5*Planet2.posY, 0.5*Planet2.posZ);
    glRotatef(Planet2.OwnAxisAngle, 0, -1, 0);
    glRotatef(90.0, 1.0, 0.0, 0.0);
    glBindTexture(GL_TEXTURE_2D, 2);
    GLUquadricObj* q2 = gluNewQuadric();
    gluQuadricDrawStyle(q2, GLU_FILL);
    gluQuadricNormals(q2, GLU_SMOOTH);
    gluQuadricTexture(q2, GL_TRUE);
    gluSphere(q2, Planet2.size, 50, 40);
    gluDeleteQuadric(q2);
  
    glPopMatrix();
    
    
    glLoadIdentity();
    draw_sun(); //绘制太阳
    gluLookAt(R * cos(b / 180 * 3.1415926) * sin(a / 180 * 3.1415926), R * sin(b / 180 * 3.1415926), R * cos(b / 180 * 3.1415926) * cos(a / 180 * 3.1415926), 0.0, 0.0, 0.0, cos((90 - b) / 180 * 3.1415926) * sin((a + 180) / 180 * 3.1415926), sin((90 - b) / 180 * 3.1415926), cos((90 - b) / 180 * 3.1415926) * cos((a + 180) / 180 * 3.1415926)); //观察角度
    
    glutSwapBuffers();
}

调试:

问题一:开始时两个星球都绕着太阳转。

解决办法:在第一次变换后不立刻进行出栈操作,而是在第一次变换的基础上再添加一次变换,这样可以让月球绕地球转。

问题二:初始化时两个星球的纹理一样,没法分别设置纹理。

解决办法:通过对glBindTexture函数的添加操作,添加了纹理对象,解决了问题。

【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)

【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)

B样条曲线绘制:

流程图:

【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)

主要思想:

动态输入任意多个控制点(控制点个数大于等于4),采用三次参数样条曲线,按照分段拼接的方式生成逼近任意多个控制点组成的多边形的光滑曲线。并按照给定的控制点个数绘制B样条曲线。

调试:

问题一:点击鼠标右键时偶尔会卡住。

解决办法:鼠标事件里出现了问题,修改后可以正常运行了。

代码:

void Bspline(Point a, Point b, Point c, Point d) {
    glPointSize(2);
    glColor3d(0, 0, 0);
    glBegin(GL_LINE_STRIP);
    for (int i = 0; i <= 1000; i++)
    {
        double t = 0.001 * i;
        double r[4];
        r[0] = -t * t * t + 3 * t * t - 3 * t + 1;
        r[1] = 3 * t * t * t - 6 * t * t + 4;
        r[2] = -3 * t * t * t + 3 * t * t + 3 * t + 1;
        r[3] = t * t * t;
        double x = 0, y = 0;
        
        x += r[0] * a.x + r[1] * b.x + r[2] * c.x + r[3] * d.x;
        y += r[0] * a.y +r[1] * b.y + r[2] * c.y + r[3] * d.y;
        x /= 6.0;
        y /= 6.0;
        glVertex2d(x,y);
    }
    glEnd();
}

void Display()
{
    glClear(GL_COLOR_BUFFER_BIT);
    //画点
    glPointSize(7);
    glColor3d(0, 0, 1);
    glBegin(GL_POINTS);
    for (int i = 0; i < p.size(); i++)
        glVertex2d(p[i].x, p[i].y);
    glEnd();
    //画线
    glLineWidth(2);
    glColor3d(1, 0, 1);
    glBegin(GL_LINE_STRIP);
    for (int i = 0; i < p.size(); i++)
        glVertex2d(p[i].x, p[i].y);
    glEnd();

    if (sta == 1 && p.size() >= 3)
        for (int i = 0; i < p.size() - 3; i++)
            Bspline(p[i], p[i + 1], p[i + 2], p[i + 3]);

    glFlush();
}



void Mouse(int button, int state, int x, int y)
{
    if (sta == 0 && button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
    {
        Point t;
        t.x = x; t.y = y;
        p.push_back(t);
        glutPostRedisplay();
    }
    if (sta == 0 && button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
        sta = 1;
        glutPostRedisplay();
    }
    
}

void Keyboard(unsigned char key, int x, int y)
{
    if (key == 'd')
    {
        glClearColor(1, 1, 1, 0);
        glClear(GL_COLOR_BUFFER_BIT);
        p.clear();
        sta = 0;
        glutPostRedisplay();
    }
}

五、 实验结果总结

地球公转&自转:(视频见附件地球.mov

【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)

 太阳系:(视频见附件太阳系.mov

【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)

【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)

 太阳系(选):(视频见附件太阳系(选).mov)【这其实是我从git上偷了一个 555】

【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)

【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)

B样条曲线:

【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)

2个控制点重合:

        效果:曲线在该点附近与两点间形成的直线基本重合,在该点则有一定的距离和弧度。

【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)

(只有一个位置是2个控制点重合)

应用:

  1. 用于绘制基本重合于连接相邻两点线段,但在拐点处的曲率于控制点的位置有关的线段;
  2. 用于在局部绘制出类似“圆角”的形状。

3个控制点重合:

        效果:曲线在该点附近与两点间形成的直线基本重合,曲线也与该点重合。

【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)

(只有一个位置是3个控制点重合)

应用:

  1. 绘制与直接连接的线段相同的线段;
  2. 在局部绘制类似“尖角”的形状。

【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)

(所有位置都是3个控制点重合)

六、 附录

  1. 其他解决方案/设想:无。
  2. 参考资料:
    1. 教材、PPT
    2. B-Spline样条曲线及其性质_BRAND-NEO的博客-CSDN博客_准均匀b样条曲线
    3. OpenGL学习笔记 之三 (简单示例 太阳月亮地球)_weixin_38167262的博客-CSDN博客
    4. 用上周的作业:画一个太阳、地球、月亮的运动模型来剖析OpenGL中变换乃至整个绘制的秘密_Luo Xiao C的博客-CSDN博客
  3. 回答思考题

Q:在OpenGL中提供给了哪几类函数能修改矩阵工作栈的数据?

AOpengl中常用两个变换堆栈,一个是glMatrixMode(GL_MODELVIEW),它一开始时候栈顶是一个单位矩阵,一般堆栈大小是32个矩阵。一个是glMatrixMode(GL_PROJECTION),正交或者透视投影,一开始时候没有栈顶单位矩阵所以需要glLoadIdentity()单位矩阵到栈顶,投影堆栈大小一般是2个,要2个目的是一个程序中既可以实现透视投影,也可以切换到正交投影(例如绘制文本)。 如果glPushMatrix()太多大于堆栈容量那么会报错,如果glPopMatrix()小于等于一个那么也会报错 。glMatrixMode(GL_TEXTURE)是纹理堆栈,也有相应的变换矩阵。

QOpenGL中提供了哪几种二次曲面模型?怎样调用使用?

A圆面、扇形、圆柱、圆锥、球等。创建二次曲面声明类型的指针GLUquadricObj*。利用上述指针,利用二次曲面模型的类,如gluCylinde(GLUquadric* quad, GLdouble base, GLdouble top,GLdouble height,GLint slices,,GLint stacks)圆柱,设置相应的参数来创建该二次曲面的对象,设置二次曲面的绘制风格,设置法线风格,设置二次曲面的绘制方向,设置纹理,调用二次曲面的绘制函数。

QB样条曲线对比Bezier曲线的算法有哪些好处?

AB样条方法是在保留Bezier方法的优点,同时克服其由于整体表示带来不具有局部性质的缺点,及解决在描述复杂形状时带来的连接问题下提出来的,当控制点个数多时控制多边形对曲线的控制不会减弱;可以对曲线进行局部修改。

完整代码:

项目一:(太阳系)

#define GL_SILENCE_DEPRECATION


//include\gl
#include <stdlib.h>
#include <iostream>

#include <GLUT/glut.h>
#include <math.h>

#define ROTATION_SPEED    0.1

static int year = 0, day = 0;

GLuint texture_id1;


int start = 0;

int ori_x;
int ori_y;



struct Planet
{
    float size, sections, posX, posY, posZ, SolarAngle, OwnAxisAngle;
    int TextureID;
};

struct Planet Planet1;
struct Planet Planet2;
struct Planet Planet3;

float R = 8;

float a = 0;
float b = 0;


int load_texture(const char* file_name, int width, int height, int depth, GLenum colour_type, GLenum filter_type)
{
    
    GLubyte* raw_bitmap;
    FILE* file;
    
    //if ((file = fopen_s(file_name, "rb")) == NULL)
    if ((file = fopen(file_name, "rb")) == NULL)
    {
        return 1;
    }
    raw_bitmap = (GLubyte*)malloc(width * height * depth * (sizeof(GLubyte)));
    
    if (raw_bitmap == NULL)
    {
        fclose(file);
        return 2;
    }
    
    fread(raw_bitmap, width * height * depth, 1, file);
    fclose(file);
    
    //  设置过滤类型
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter_type);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter_type);
    
    //  设置纹理环境
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    
    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, colour_type,
                      GL_UNSIGNED_BYTE, raw_bitmap);
    
    free(raw_bitmap);
    glDisable(GL_TEXTURE_2D);
    return 0;
}

void LoadTextures(GLuint texture_id, int MaxNrOfTextures)
{
    // 第一种纹理
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //控制所读取数据的对齐方式
    glGenTextures(MaxNrOfTextures, &texture_id); // 生成纹理的数量-MaxNrOfTextures 存储纹理索引-texture_id
    glBindTexture(GL_TEXTURE_2D, 1); //将一个命名的纹理绑定到一个纹理目标上
    if (load_texture("/Users/kqp12_27/Desktop/Xcode-OpenGL/Mouse copy 12/Mouse/ear.bmp", 512, 128, 3, GL_BGR_EXT, GL_NEAREST)) //读取此bmp文件
    {
        exit(1);
    }
    
    // 第二种纹理
    glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
    glGenTextures(MaxNrOfTextures, &texture_id);
    glBindTexture(GL_TEXTURE_2D, 2);
    if (load_texture("/Users/kqp12_27/Desktop/一些课📖/计图实验/实验三/太阳系/moon copy.bmp",88,63, 3, GL_BGR_EXT, GL_NEAREST))
    {
        exit(1);
    }
    
    // 第三种纹理
    glPixelStorei(GL_UNPACK_ALIGNMENT, 3);
    glGenTextures(MaxNrOfTextures, &texture_id);
    glBindTexture(GL_TEXTURE_2D, 3);
    if (load_texture("/Users/kqp12_27/Desktop/一些课📖/计图实验/实验三/太阳系/sun.bmp",500, 400, 3, GL_BGR_EXT, GL_NEAREST))
    {
        exit(1);
    }
    
}

void draw_sun(){

    glBindTexture(GL_TEXTURE_2D, 3);
    GLUquadricObj* q3 = gluNewQuadric();
    
    gluQuadricDrawStyle(q3, GLU_FILL);
    gluQuadricNormals(q3, GLU_SMOOTH);
    gluQuadricTexture(q3, GL_TRUE);
    
    gluSphere(q3, 0.1002, 50,40);
    gluDeleteQuadric(q3);
    
    
}
void init(void)
{
    //地球
    Planet1.size = 0.4f;
    Planet1.sections = 16.0f;
    Planet1.posX = 0.0f;
    Planet1.posY = 0.0f;
    Planet1.posZ = 1.4f;
    Planet1.OwnAxisAngle = 0.0f;
    Planet1.SolarAngle = 60.0f;
    Planet1.TextureID = 1;
    
    //月球
    Planet2.size = 0.2f;
    Planet2.sections = 16.0f;
    Planet2.posX = 0.0f;
    Planet2.posY = 0.0f;
    Planet2.posZ = 1.4f;
    Planet2.OwnAxisAngle = 0.0f;
    Planet2.SolarAngle = 60.0f;
    Planet2.TextureID = 2;
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_FLAT);

    LoadTextures(texture_id1, 1);
    
    glEnable(GL_TEXTURE_2D);
    
    glClearDepth(1.0f);                                                    // 设置深度缓存
    glDepthFunc(GL_LEQUAL);                                                // 选择深度测试方式
    glEnable(GL_DEPTH_TEST);                                            // 开启深度测试
    glShadeModel(GL_SMOOTH);                                            // 阴暗处理采用平滑方式
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);                    // 最精细的透视计算
    
    return;
}
void display(void)
{
    
    // 地球公转
    Planet1.SolarAngle += 1.0f * ROTATION_SPEED;
    if (Planet1.SolarAngle >= 360) { Planet1.SolarAngle -= 360; }
    
    // 地球自转
    Planet1.OwnAxisAngle += 0.5f;
    if (Planet1.OwnAxisAngle >= 360) { Planet1.OwnAxisAngle -= 360; }
    
    // 月球公转
    Planet2.SolarAngle += 7.0f * ROTATION_SPEED;
    if (Planet2.SolarAngle >= 360) { Planet2.SolarAngle -= 360; }
    
    // 月球自转
    Planet2.OwnAxisAngle += 1.0f;
    if (Planet2.OwnAxisAngle >= 360) { Planet2.OwnAxisAngle -= 360; }

    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);                    // 清除颜色和深度缓存
    glColor3f(1.0, 0.0, 0.0);
    glColor3f(1.0, 1.0, 1.0);
    glColor3f(0.7f, 0.7f, 0.7f);
    glBegin(GL_LINE_LOOP);
    
    // 绘制轨道
    for (int l = 0; l < 360; l++)
    {
        glVertex3f((float)cos(l * ((float)3.14159 / (float)180)) * Planet1.posZ, 0.0f, (float)sin(l * ((float)3.14159 / (float)180)) * Planet1.posZ);
        
    }
    glEnd();
    
    glPushMatrix();
    
    // 地球
    // 坐标变换,使地球在公转轨道上转
    glRotatef(Planet1.SolarAngle, 0, -1, 0); //旋转
    glTranslatef(Planet1.posX, Planet1.posY, Planet1.posZ); //平移
    glRotatef(Planet1.OwnAxisAngle, 0, -1, 0);
    
    glBindTexture(GL_TEXTURE_2D, 1); //设置纹理
    
    GLUquadricObj* q = gluNewQuadric();
    gluQuadricDrawStyle(q, GLU_FILL);
    gluQuadricNormals(q, GLU_SMOOTH);
    gluQuadricTexture(q, GL_TRUE);
    gluSphere(q, Planet1.size, 50, 40); //画球
    gluDeleteQuadric(q);
    glBindTexture(GL_TEXTURE_2D, 0);


    // 月球
    glRotatef(Planet2.SolarAngle, 0, 1, 0);
    glTranslatef(0.5*Planet2.posX, 0.5*Planet2.posY, 0.5*Planet2.posZ);
    glRotatef(Planet2.OwnAxisAngle, 0, -1, 0);
    glRotatef(90.0, 1.0, 0.0, 0.0);
    glBindTexture(GL_TEXTURE_2D, 2);
    GLUquadricObj* q2 = gluNewQuadric();
    gluQuadricDrawStyle(q2, GLU_FILL);
    gluQuadricNormals(q2, GLU_SMOOTH);
    gluQuadricTexture(q2, GL_TRUE);
    gluSphere(q2, Planet2.size, 50, 40);
    gluDeleteQuadric(q2);
  
    glPopMatrix();
    
    
    glLoadIdentity();
    draw_sun(); //绘制太阳
    gluLookAt(R * cos(b / 180 * 3.1415926) * sin(a / 180 * 3.1415926), R * sin(b / 180 * 3.1415926), R * cos(b / 180 * 3.1415926) * cos(a / 180 * 3.1415926), 0.0, 0.0, 0.0, cos((90 - b) / 180 * 3.1415926) * sin((a + 180) / 180 * 3.1415926), sin((90 - b) / 180 * 3.1415926), cos((90 - b) / 180 * 3.1415926) * cos((a + 180) / 180 * 3.1415926)); //观察角度
    
    glutSwapBuffers();
}

void reshape(int w, int h)
{
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, (GLfloat)w / (GLfloat)h, 0.1, 20.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    
}

void keyboard(unsigned char key, int x, int y)
{
    switch (key) {
            
        case 'w':
            R -= 0.1;
            break;
        case 's':
            R += 0.1;
            break;
        case 27:
            exit(0);
            break;
        default:
            break;
    }
}

void processMouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
    {
        start = 1;
        ori_x = x;
        ori_y = y;
        
    }
    if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
    {
        start = 0;
        
        
    }
    
}

void onMouseMove(int x, int y)
{
    if (start == 1)
    {
        a -= (x - ori_x) / 2;
        b += (y - ori_y) / 2;
        
        ori_x = x;
        ori_y = y;
        
    }
    
    
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(1000, 600);
    glutInitWindowPosition(100, 100);
    glutCreateWindow(argv[0]);
    init();
    
    glutDisplayFunc(display);
    glutIdleFunc(display);
    draw_sun();
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);
    glutMouseFunc(processMouse);
    glutMotionFunc(onMouseMove);
    
    
    glutMainLoop();
    return 0;
}

项目一(选)(git上偷的太阳系):

#define GL_SILENCE_DEPRECATION
#include<stdio.h>
#include<stdlib.h>
#include <GLUT/glut.h>
#include<math.h>
#include<time.h>

#define PI 3.14
float angleMoon=0.0, angleEarth=0.0,angleAstroid=0.0,
angleMars=0.0,
angleMercury=0.0,
angleVenus=0.0,
angleJupiter=0.0,
angleSaturn=0.0,
angleUranus=30.0,
angleNeptune=60.0;
GLfloat sx=0.2,sy=0.2,sz=0.2;
int planet1;
GLfloat black[]={0.0f,0.0f,0.0f,1.0f};
GLfloat white[]={1.0f,1.0f,1.0f,1.0f};
GLfloat blue[]={0.0f,0.0f,0.9f,1.0f};
GLfloat er[]={0.0f,5.0f,0.9f,1.0f};
GLfloat yellow[]={0.7f,0.2f,0.0f,1.0f};
GLfloat qAmb[]={0.1,0.1,0.1,1.0};
GLfloat qDif[]={1.0,1.0,1.0,1.0};
GLfloat qSpec[]={.50,.50,.50,.10};
GLfloat qPos[]={0,0,0,0.1};
GLfloat sc[8]={0.295 , 0.40,0.50, 0.60,0.80,1.0,1.05,1.13};
double ang=2*PI/300;
double angular=2*PI/50;


void initLighting()
{
    //glMaterialfv(GL_FRONT,GL_AMBIENT,yellow);
    //glMaterialfv(GL_FRONT,GL_SPECULAR,yellow);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT7);
    
    glLightfv(GL_LIGHT7,GL_AMBIENT,qAmb);
    glLightfv(GL_LIGHT7,GL_DIFFUSE,qDif);
    glLightfv(GL_LIGHT7,GL_SPECULAR,qSpec);
    //glMaterialfv(GL_FRONT,GL_DIFFUSE,yellow);
}
void myinit()
{
    glClearColor(0.0,0.0,0.0,0.0); //backgroundcolor is green
    //gluOrtho2D(0,699,0,699);
    glPointSize(1.0);
    glLineWidth(2.0);
    
}

void background()
{
    glBegin(GL_QUADS);
    glColor3f(0.0,0.00,0.00);
    glVertex3f(-01.00,01.00,1);
    glColor3f(.20,0.0,0.70);
    glVertex3f(01.00,1.00,1);
    glColor3f(0,0.0,0.0);
    glVertex3f(1.00,-1.00,1);
    glColor3f(.70,.10,.20);
    glVertex3f(-1.00,-1.00,1);
    glEnd();
}

void orbit()
{
    glColor3f(0.5,0.5,0.5);
    
    
    int i=0;
    for(i=0;i<8;i++){
        glPushMatrix();
        if(i==5)
        {glRotatef(45,1.0,0.0,0.0);}
        else
        {glRotatef(63,1.0,0.0,0.0);}
        glScalef(sc[i],sc[i],sc[i]);
        glBegin(GL_POINTS);
        double ang1=0.0;
        int i=0;
        for(i=0;i<300;i++)
        {glVertex2d(cos(ang1),sin(ang1));
            ang1+=ang;  }
        glEnd();
        glPopMatrix();
    }
}

void draw(void)
{
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    background();
    orbit();
    glLoadIdentity();
    glPushMatrix();
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_COLOR_MATERIAL);
    glPushMatrix();
    glColor3f(0.7,0.5,0.0);
    glScalef(sx,sy,sz);
    glLightfv(GL_LIGHT7,GL_POSITION,qPos);
    glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,yellow);
    glutSolidSphere(1,50,50);
    glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,black);
    glPopMatrix();
    
    glScalef(0.2,0.2,0.2);
    glPushMatrix();
    glRotatef(angleMercury,0.0,1.0,-0.5);
    glTranslatef(1.5,0.0,0.0);
    glColor3f(1.0,0.9,0.0);
    glScalef(0.08,0.08,0.08);
    glutSolidSphere(1,50,50);
    glPopMatrix();
    
    glPushMatrix();
    glRotatef(angleVenus,0.0,1.0,-0.5);
    glTranslatef(2.0,0.0,0.0);
    glColor3f(0.9,0.1,0.0);
    glScalef(0.1,0.1,0.1);
    glutSolidSphere(1,50,50);
    glPopMatrix();
    
    glPushMatrix();
    glRotatef(angleEarth,0.0,1.0,-0.5);
    glTranslatef(2.5,0.0,0.0);
    glColor3f(0.0,0.1,0.7);
    glScalef(0.23,0.23,0.23);
    glutSolidSphere(1,50,50);
    glPushMatrix();
    glRotatef(angleMoon,0.0,0.1,0.05);
    glTranslatef(1.3,0.0,0.0);
    glColor3f(1.0,1.0,1.0);
    glScalef(0.5,0.5,0.5);
    glutSolidSphere(0.5,50,50);
    glPopMatrix();//moon made
    glPopMatrix();//earth made
    
    glPushMatrix();
    glRotatef(angleMars,0.0,1.0,-0.5);
    glTranslatef(-3.0,0.0,0.0);
    glColor3f(0.05,0.05,0.01);
    glScalef(0.17,0.17,0.17);
    glutSolidSphere(1,50,50);
    glPopMatrix();
    
    glPushMatrix();
    glColor3f(3.30,3.30,3.30);
    glRotatef(63,1.0,0.0,0.0);
    int j=0,i=0,div=90;float siz=2;
    float scl[4]={3.3,3.4,3.35,3.2};
    for(j=0;j<4;j++)
    {glPushMatrix();siz-=0.3;
        glPointSize(siz);
        glScalef(scl[j],scl[j],scl[j]);
        glBegin(GL_POINTS);
        double ang1=0.0 -angleAstroid,a=(2*PI)/div;
        for(i=0;i<div;i++)
        {glVertex2d(cos(ang1),sin(ang1));
            ang1+=a;  }
        div+=10;
        glEnd();
        glPopMatrix();
    }
    glPopMatrix();//astroid made
    
    glPushMatrix();
    glRotatef(angleJupiter,0.0,1.0,-0.5);
    glTranslatef(-4.0,0.0,0.0);
    glColor3f(0.4,0.2,0.0);
    glScalef(0.5,0.5,0.5);
    glutSolidSphere(1,50,50);
    glPushMatrix();
    glRotatef(angleMoon,1.0,-0.5,0.0);
    glTranslatef(0.0,0,1.1);
    glColor3f(1.0,1.0,1.0);
    glScalef(0.1,0.1,0.1);
    glutSolidSphere(0.5,50,50);
    glPopMatrix();//moon made
    glPopMatrix();
    
    glPushMatrix();
    glRotatef(angleSaturn,0.0,1.0,-1.0);
    glTranslatef(-5.0,0.0,0.0);
    glColor3f(0.9,0.0,0.0);
    glScalef(0.4,0.4,0.4);
    glutSolidSphere(1,50,50);
    glPushMatrix();
    glRotatef(45,1.0,0.0,0.0);
    glPointSize(3);
    glColor3f(5.0,3.0,1.0);
    glScalef(1.2,1.2,1.2);
    glBegin(GL_POINTS);
    double ang1=0.0;
    i=0;
    for(i=0;i<50;i++)
    {glVertex2d(cos(ang1),sin(ang1));
        ang1+=angular;  }
    glEnd();
    
    glPointSize(2);
    glPopMatrix();//ring made
    glPopMatrix();
    
    glPushMatrix();
    glRotatef(angleUranus,0.0,1.0,-0.5);
    glTranslatef(5.2,0.0,0.0);
    glColor3f(0.0,0.5,0.9);
    glScalef(0.23,0.23,0.23);
    glutSolidSphere(1,50,50);
    glPopMatrix();
    
    glPushMatrix();
    glRotatef(angleNeptune,0.0,1.0,-0.5);
    glTranslatef(-5.7,0.0,0.0);
    glColor3f(0.0,0.0,0.9);
    glScalef(0.2,0.2,0.2);
    glutSolidSphere(1,50,50);
    glPopMatrix();
    
    
    glPopMatrix();
    glFlush();
}


void update(int value){
    
    if((angleMoon>=0 && angleMoon<180) )
    {sx-=0.0003;sy-=0.0003;sz-=0.0003;}
    else{sx+=0.0003;sy+=0.0003;sz+=0.0003;}
    
    
    angleMoon+=2;
    if(angleMoon>360){
        angleMoon-=360;}
    angleEarth+=0.7;
    if(angleEarth>360){
        angleEarth-=360;}
    angleMercury+=2;
    if(angleMercury>360){
        angleMercury-=360;}
    angleVenus+=0.9;
    if(angleVenus>360){
        angleVenus-=360;}
    angleMars+=0.5;
    if(angleMars>360){
        angleMars-=360;}
    angleJupiter+=0.2;
    if(angleJupiter>360){
        angleJupiter-=360;}
    angleSaturn+=0.1;
    if(angleSaturn>360){
        angleSaturn-=360;}
    
    
    angleUranus+=0.05;
    if(angleUranus>360){
        angleUranus-=360;}
    
    
    angleNeptune+=0.02;
    if(angleNeptune>360){
        angleNeptune-=360;}
    
    
    angleAstroid+=0.002;
    if(angleAstroid>360){
        angleAstroid-=360;}
    
    
    glutPostRedisplay();
    glutTimerFunc(20,update,0);
}

int main(int argc, char **argv)
{
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
    glutInitWindowPosition(0,0);
    glutInitWindowSize(700,700);
    glutCreateWindow("Solar System");
    initLighting();
    myinit();
    glutDisplayFunc(draw);
    glutTimerFunc(25,update,0);
    glutMainLoop();
    return 0;
}

项目二(B样条):

#define GL_SILENCE_DEPRECATION
#include<vector>
#include<GLUT/glut.h>
using namespace std;

int sta = 0;//状态显示
struct Point
{
    int x;
    int y;
};


vector<Point> p;

void Bspline(Point a, Point b, Point c, Point d) {
    glPointSize(2);
    glColor3d(0, 0, 0);
    glBegin(GL_LINE_STRIP);
    for (int i = 0; i <= 1000; i++)
    {
        double t = 0.001 * i;
        double r[4];
        r[0] = -t * t * t + 3 * t * t - 3 * t + 1;
        r[1] = 3 * t * t * t - 6 * t * t + 4;
        r[2] = -3 * t * t * t + 3 * t * t + 3 * t + 1;
        r[3] = t * t * t;
        double x = 0, y = 0;
        
        x += r[0] * a.x + r[1] * b.x + r[2] * c.x + r[3] * d.x;
        y += r[0] * a.y +r[1] * b.y + r[2] * c.y + r[3] * d.y;
        x /= 6.0;
        y /= 6.0;
        glVertex2d(x,y);
    }
    glEnd();
}

void Display()
{
    glClear(GL_COLOR_BUFFER_BIT);
    //画点
    glPointSize(7);
    glColor3d(0, 0, 1);
    glBegin(GL_POINTS);
    for (int i = 0; i < p.size(); i++)
        glVertex2d(p[i].x, p[i].y);
    glEnd();
    //画线
    glLineWidth(2);
    glColor3d(1, 0, 1);
    glBegin(GL_LINE_STRIP);
    for (int i = 0; i < p.size(); i++)
        glVertex2d(p[i].x, p[i].y);
    glEnd();

    if (sta == 1 && p.size() >= 3)
        for (int i = 0; i < p.size() - 3; i++)
            Bspline(p[i], p[i + 1], p[i + 2], p[i + 3]);

    glFlush();
}



void Mouse(int button, int state, int x, int y)
{
    if (sta == 0 && button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
    {
        Point t;
        t.x = x; t.y = y;
        p.push_back(t);
        glutPostRedisplay();
    }
    if (sta == 0 && button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
        sta = 1;
        glutPostRedisplay();
    }
    
}

void Keyboard(unsigned char key, int x, int y)
{
    if (key == 'd')
    {
        glClearColor(1, 1, 1, 0);
        glClear(GL_COLOR_BUFFER_BIT);
        p.clear();
        sta = 0;
        glutPostRedisplay();
    }
}

void Reshape(int w, int h)
{
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, w, h, 0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(600, 600);
    glutCreateWindow("B样条曲线");
    glClearColor(1, 1, 1, 0);
    glutDisplayFunc(Display);
    glutReshapeFunc(Reshape);
    glutMouseFunc(Mouse);
    glutKeyboardFunc(Keyboard);

    glutMainLoop();
    return 0;
}

​​​​​​​


有用的话点点赞捏!!文章来源地址https://www.toymoban.com/news/detail-498632.html

到了这里,关于【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 计算机组成原理实验二 存储系统预习报告

    掌握静态随机存储器 RAM  工作特性及数据的读写方法。 基于信号时序图,了解读写静态随机存储器的原理。 1、阅读实验指导书,然后回答问题。 实验所用的静态存储器由一片 6116( 2K*8bit  )构成(位于MEM 单元),6116 有三个控制线:CS 表示( 片选线  ) ,   OE 表示

    2023年04月15日
    浏览(56)
  • 合肥工业大学计算机组成原理实验报告

    ✅作者简介:CSDN内容合伙人、信息安全专业在校大学生🏆 🔥系列专栏 :本科生课设-计算机组成原理实验 📃新人博主 :欢迎点赞收藏关注,会回访! 💬舞台再大,你不上台,永远是个观众。平台再好,你不参与,永远是局外人。能力再大,你不行动,只能看别人成功!

    2024年02月04日
    浏览(47)
  • 计算机图形学实验四 OpenGL的鼠标交互绘制

    一、实验目的 1.掌握OpenGL的鼠标按钮响应函数。 2.掌握OpenGL的鼠标移动响应函数。 3.进一步巩固OpenGL的基本图元绘制基础。 二、实验内容 1.鼠标画草图——实现鼠标点到哪,线就画到哪。 思路: 1)在主程序注册鼠标响应和鼠标移动子函数: glutMouseFunc(mymouse); glutMotionFunc(mym

    2023年04月20日
    浏览(113)
  • 【计算机体系结构】Cache性能分析实验报告

    原文档下载: https://download.csdn.net/download/weixin_56213139/87384692 一、 实验目的 (1)加深对Cache基本概念、基本组织结构以及工作原理的理解。 (2)掌握Cache容量、相关度、块大小对Cache性能的影响 (3)掌握降低Cache不命中率的各种方法以及它们对提高Cache性能的好处 (4)理解

    2024年02月03日
    浏览(50)
  • 哈工大 计算机系统 二进制炸弹实验报告

    实验报告 实 验(三) 题     目  Binary Bomb          二进制炸弹   专       业      计算机学院          学    号               班    级                学       生              指 导 教 师                实 验 地 点        实 验 日 期     

    2023年04月15日
    浏览(45)
  • 计算机图形学实验——利用MFC对话框实现多边形绘制与填充(扫描线填充算法)附源码

    内容概括: 利用基于对话框的MFC项目 实现鼠标点击绘制多边形 实现扫描线算法填充多边形 源码见Yushan-Ji/ComputerGraphics: ECNU2023秋 计算机图形学课程实验代码 (github.com) 通过鼠标交互输入多边形 对各种多边形进行填充,包括边界自交的情况 利用 OnLButtonDown 和 OnRButtonDown 函数,

    2024年02月04日
    浏览(70)
  • Unity实现简易太阳系

    开发环境 :Unity 2022.3.5f1c1 + Visual Studio 2022 太阳系相关星体 :太阳、八大行星、月球 模拟星系 :太阳系、地月系 功能 :支持行星以太阳为中心,任意轴进行公转,此处演示同一平面。 a1-a8为公转轴,可以任意修改,InitStarPosition()将会修正星体初始位置;MoveAroundSun脚本挂在

    2024年02月07日
    浏览(42)
  • Unity实现简单太阳系

    网上的贴图资源较为散乱,此处提供一个太阳系贴图的网站,图片还是相当精美的:https://www.solarsystemscope.com/textures/ 1、保存相应资源并导入成material: 问就是英文不好0.0(实践下来没有影响就完事了) 2、特别注意导入太阳material时,为了更逼真,我为其设置了 自发光 的属

    2023年04月09日
    浏览(34)
  • 【计算机图形学】二维图形裁剪算法

    Cohen-Sutherland算法 Cohen-Sutherland是最早最流行的算法。 核心思想:通过 编码测试 来减少计算交点的次数。(编码算法) 1. 区域码: 线段端点以区域赋值以四位二进制码。 编码顺序:四位从右到左分别为:左边界、右边界、下边界、上边界。 编码值:落在相应位置为1,否则

    2024年02月02日
    浏览(58)
  • OpenGL太阳系行星系统简单实现

    使用OpenGL(glfw, glad)模拟太阳系(地球、月球、太阳)系统,涉及三维图形变换、坐标系统,光照模型(待添加)、键盘鼠标事件处理等内容,在main函数中封装了绝大部分的OpenGL接口,极大的减少了代码量,操作简便。 Shader.h Camera.h与Texture.h封装着色器、摄像机与纹理类,其

    2024年02月04日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包