OpenGL绘制三叉树(真树,非数据结构)

一、概述

高级计算机三维建模第四次小实习,基于给定基础代码,理解分形思想,将二叉树改成三叉树。基础代码结果如下:
在这里插入图片描述

二、绘制过程

很简单,只要在分形绘制过程中多个叉就行,随便将画笔旋转个方向即可。截止到第六次实习,实习内容都很简单,因为都不需要完全理解每一步的思想和实现方法,只需要找到应该添加代码的地方,添加几行代码达到效果就行,哎。。。没办法,我也很想从头到尾完完全全搞懂每一步,可身不由己啊,下次一定。
添加代码的部位就是在void FractalTree()函数中,代码如下(添加的代码为注释部分):

void FractalTree(int level)
{
    long savedseed;

    if (level == Level)
    {
        glPushMatrix();
        glRotatef(60+randf()*120, 0, 1, 0);
        glCallList(STEMANDLEAVES);
        glPopMatrix();
    }
    else
    {
        glCallList(STEM);

        glPushMatrix();
        glTranslatef(0, 1, 0);
        glScalef(0.7, 0.7, 0.7);

        savedseed = rand();
        glPushMatrix();
        glRotatef(0+ randf()*90, 0, 1, 0);
        glRotatef(30 + randf()*30, 0, 0, 1);
        FractalTree(level + 1);
        glPopMatrix();

        srand(savedseed);
        savedseed = rand();
        glPushMatrix();
        glRotatef(180 + randf()*90, 0, 1, 0);
        glRotatef(30 + randf()*30, 0, 0, 1);
        FractalTree(level + 1);
        glPopMatrix();

        /*srand(savedseed);
        savedseed = rand();
        glPushMatrix();
        glRotatef(90 + randf()*90, 0, 1, 0);
        glRotatef(30 + randf()*30, 0, 0, 1);
        FractalTree(level + 1);
        glPopMatrix();*/

        glPopMatrix();
    }
}

添加后运行结果为:
在这里插入图片描述在这里插入图片描述
是三叉树没错,每条树枝上最后也都有叶子,那就到这吧。

三、完整代码

#include <windows.h>
#include <GL/freeglut.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define TREE 6
#define STEM 1
#define LEAF 2
#define LEAF_MAT 3
#define TREE_MAT 4
#define STEMANDLEAVES 5

const double PI=3.14159265;
int Rebuild = 1;
int Level   = 6;
double g_r = 8, g_theta = PI/2.0, g_phai = PI/2.0;
float treePos[3] = {0, -2, 4};

static void resize(int w, int h)
{
    glViewport(0,0,(GLsizei)w,(GLsizei)h) ;
    glMatrixMode(GL_PROJECTION) ;
    glLoadIdentity() ;
    gluPerspective(60.0,(GLfloat)w/(GLfloat)h,0.2,30.0) ;
    glMatrixMode(GL_MODELVIEW) ;
    glLoadIdentity() ;
}

inline float randf()
{
    return (rand()/(float)RAND_MAX);
}

void FractalTree(int level)
{
    long savedseed;

    if (level == Level)
    {
        glPushMatrix();
        glRotatef(60+randf()*120, 0, 1, 0);
        glCallList(STEMANDLEAVES);
        glPopMatrix();
    }
    else
    {
        glCallList(STEM);

        glPushMatrix();
        glTranslatef(0, 1, 0);
        glScalef(0.7, 0.7, 0.7);

        savedseed = rand();
        glPushMatrix();
        glRotatef(0+ randf()*90, 0, 1, 0);
        glRotatef(30 + randf()*30, 0, 0, 1);
        FractalTree(level + 1);
        glPopMatrix();

        srand(savedseed);
        savedseed = rand();
        glPushMatrix();
        glRotatef(180 + randf()*90, 0, 1, 0);
        glRotatef(30 + randf()*30, 0, 0, 1);
        FractalTree(level + 1);
        glPopMatrix();

        srand(savedseed);
        savedseed = rand();
        glPushMatrix();
        glRotatef(90 + randf()*90, 0, 1, 0);
        glRotatef(30 + randf()*30, 0, 0, 1);
        FractalTree(level + 1);
        glPopMatrix();

        glPopMatrix();
    }
}

void CreateTreeLists(void)
{
    GLUquadricObj *cylquad = gluNewQuadric();
    int i;

    glNewList(STEM, GL_COMPILE);
    glCallList(TREE_MAT);
    glPushMatrix();
    glRotatef(-90, 1, 0, 0);
    gluCylinder(cylquad, 0.1, 0.08, 1, 10, 2 );
    glPopMatrix();
    glEndList();

    glNewList(LEAF, GL_COMPILE);
    glBegin(GL_TRIANGLES);
    glNormal3f(-0.1, 0, 0.25);
    glVertex3f(0, 0, 0);
    glVertex3f(0.5, 0.5, 0.2);
    glVertex3f(0, 1.0, 0);
    glNormal3f(0.2, 0, 0.5);
    glVertex3f(0, 0, 0);
    glVertex3f(0, 1.0, 0);
    glVertex3f(-0.5, 0.5, 0.2);
    glEnd();
    glEndList();

    glNewList(STEMANDLEAVES, GL_COMPILE);
    glPushMatrix();
    glPushAttrib(GL_LIGHTING_BIT);
    glCallList(STEM);
    glCallList(LEAF_MAT);
    for(i = 0; i < 3; i++)
    {
        glTranslatef(0, 0.333, 0);
        glRotatef(90, 0, 1, 0);
        glPushMatrix();
        glRotatef(0, 0, 1, 0);
        glRotatef(50, 1, 0, 0);
        glCallList(LEAF);
        glPopMatrix();
        glPushMatrix();
        glRotatef(180, 0, 1, 0);
        glRotatef(60, 1, 0, 0);
        glCallList(LEAF);
        glPopMatrix();
    }
    glPopAttrib();
    glPopMatrix();
    glEndList();

    gluDeleteQuadric(cylquad);
}

void SetupMaterials(void)
{
    GLfloat tree_ambuse[] =   { 0.4, 0.25, 0.1, 1.0 };
    GLfloat tree_specular[] = { 0.0, 0.0, 0.0, 1.0 };
    GLfloat tree_shininess[] = { 10 };

    GLfloat leaf_ambuse[] =   { 0.0, 0.8, 0.0, 1.0 };
    GLfloat leaf_specular[] = { 0.0, 0.8, 0.0, 1.0 };
    GLfloat leaf_shininess[] = { 10 };

    glNewList(TREE_MAT, GL_COMPILE);
    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, tree_ambuse);
    glMaterialfv(GL_FRONT, GL_SPECULAR, tree_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, tree_shininess);
    glEndList();

    glNewList(LEAF_MAT, GL_COMPILE);
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, leaf_ambuse);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, leaf_specular);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, leaf_shininess);
    glEndList();
}

static void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity() ;
    glTranslatef(treePos[0], treePos[1], treePos[2]);
    gluLookAt(g_r*sin(g_phai)*cos(g_theta),
              g_r*cos(g_phai),
              g_r*sin(g_phai)*sin(g_theta), 0,0,0, 0,
              sin(g_phai)>=0?1:-1,0);

    if(Rebuild)
    {
        glNewList(TREE, GL_COMPILE);
        FractalTree(0);
        glEndList();
        Rebuild = 0;
    }
    glCallList(TREE);

    glutSwapBuffers();
}

static void key(unsigned char key, int x, int y)
{
    switch (key)
    {
    case 27 :
        exit(0);
        break;
    case '=':
        if(Level<8) Level++;
        Rebuild = 1;
        break;
    case '-':
        if(Level>0) Level--;
        Rebuild = 1;
        break;
    case 'r':
        Rebuild = 1;
        break;
    case 'w':
        g_phai += PI/180.0;
        break;
    case 's':
        g_phai -= PI/180.0;
        break;
    case 'a':
        g_theta += PI/180.0;
        break;
    case 'd':
        g_theta -= PI/180.0;
        break;
    case 'q':
        g_r += 0.1;
        break;
    case 'e':
        g_r -= 0.1;
        break;
    }
    glutPostRedisplay();
}

static void idle(void)
{
    glutPostRedisplay();
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitWindowSize(800, 600);
    glutInitWindowPosition(10,10);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);

    glutCreateWindow("Shapes");

    glutReshapeFunc(resize);
    glutDisplayFunc(display);
    glutKeyboardFunc(key);
    glutIdleFunc(idle);

    glClearColor(0.2,0.4,1.0,1);
    GLfloat light_position[] = { -15.0, 15.0, 0, 0.0 };
    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
    glDisable(GL_CULL_FACE);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_NORMALIZE);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);

    glShadeModel(GL_SMOOTH);
    SetupMaterials();
    CreateTreeLists();

    glutMainLoop();

    return 0;
}

  • 15
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: C语言是一种计算机编程语言,可以使用它来实现屏幕飘雪的效果,这在制作冬季主题的计算机界面时很常见。 圣诞是圣诞节庆祝活动中常见的装饰物品之一,通常是一棵用彩灯和其他装饰品装饰的人工或真树。 圣诞老人是圣诞节传统文化中的一个角色,传说他会穿着红色的衣服和白色的胡子,驾着驯鹿拉的雪橇,给孩子们送礼物。 圣诞音乐是一种特殊的音乐类型,通常与圣诞节庆祝活动相关,包括圣诞颂歌、圣诞卡罗尔等,常用于增强节日气氛。 ### 回答2: C语言是一种高级编程语言,可以用来编写各种应用程序。在C语言中,我们可以使用一些函数和库来实现一些有趣的效果,比如屏幕飘雪。 屏幕飘雪是指在计算机屏幕上显示出雪花飘落的效果。我们可以使用C语言中的图形库,比如graphics.h,来绘制雪花的图案和动画效果,通过控制雪花的位置和速度,实现屏幕飘雪的效果。 圣诞是圣诞节的象征之一,代表着家庭和谐、幸福和团聚。在C语言中,我们可以使用字符和循环语句来打印出一个圣诞的形状,其中最底下的一排代表干,上面的几排代表枝和叶子,可以使用不同的字符来表示不同的部分,比如“*”表示叶子,“|”表示干,通过合理的排列和循环控制,就可以打印出一个漂亮的圣诞。 圣诞老人是圣诞节的象征之一,传说他会在圣诞夜来到孩子们的家里,给他们送礼物。在C语言中,我们可以使用图形库或者字符来绘制圣诞老人的图案,比如使用圆和直线来绘制头、身体和腿部,使用圆来表示脸部,通过合理控制形状和颜色,可以绘制出一个可爱的圣诞老人形象。 圣诞音乐是圣诞节的重要组成部分,给人们带来了欢乐和温馨的氛围。在C语言中,我们可以使用音乐库或者简单的音频播放函数来播放圣诞音乐。通过引入音频文件或者直接使用C语言提供的音乐函数,我们可以在程序中添加适当的代码来播放圣诞音乐,让人们在编程的同时享受到美妙的音乐。 ### 回答3: C语言是一种高级编程语言,可以用来创建各种应用程序。在使用C语言编写程序时,我们可以实现屏幕飘雪效果。通过在屏幕上绘制雪花的图案,并让它们以某种方式移动,我们可以模拟下雪的场景。这种效果常在圣诞节期间应用,可以增添节日气氛。 圣诞是圣诞节的象征之一,它象征着平安、团圆和希望。我们可以使用C语言编写程序来绘制一个圣诞的图案。通过绘制的技巧,我们可以用字符组成的形状,并添加彩灯的效果,使得看起来更加美丽。 圣诞老人是圣诞节的象征之一,他是给孩子们送礼物的好心人。我们可以使用C语言编写程序来模拟圣诞老人的动作。通过使用C语言的动画绘制技术,我们可以让圣诞老人在屏幕上移动和交互,给人们带来欢乐和惊喜。 圣诞音乐是圣诞节庆祝活动中的重要组成部分。我们可以使用C语言编写程序来播放圣诞音乐。通过利用C语言的音频处理库,我们可以将音乐文件解码,然后输出到音频设备,从而实现音乐的播放。可以选择一些经典的圣诞歌曲,如《铃儿响叮当》、《圣诞老人进城》等,让人们在欢庆节日的同时,聆听美妙的音乐。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值