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

本文介绍了一种使用OpenGL进行三维建模的方法,重点在于将二叉树分形模型转换为三叉树的过程。通过在给定代码的基础上添加特定的旋转和平移操作,实现了从二叉树到三叉树的转变,并展示了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述

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

二、绘制过程

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值