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