Stochastic 3D OpenGL Cutted Fractal Tree with Python

I got it! The OpenGL 3D fractal tree and a bonus: keyboard controls! The code is for sure not very well designed, I’m just an OpenGL noob.

 

from OpenGL.GL import *
from OpenGL.GLU import *
from pygame.locals import *
import pygame, math, random

maxdepth=7
width=800
height=800
# Generation of random numbers
randomcounter=0
randomnumbers=[]
print "Randomizing..."
for elements in range(0,(4**maxdepth)*8):
        randomnumbers.append(random.randint(10,30))
print "...done."
# Pygame init
print "Initializing..."
pygame.init()
pygame.display.set_caption("Stochastic 3D OpenGL Cutted Fractal Tree")
screen=pygame.display.set_mode((width,height),OPENGL|DOUBLEBUF|HWSURFACE)
# OpenGL init
glViewport(0,0,width,height)
glClearColor(0.,0.,0.,0.)
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0,width/height,1.0,500.0);
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
def drawTree(x1, y1,z1,angle,rotation, depth, r,g,b,randomcounter,randomnumbers):
    if depth:
        # Brown to green gradient
        g=g+7;
        if g>255:
            g=7
        x2 = x1 + math.cos(math.radians(angle)) * randomnumbers[randomcounter]/10.0 # X random component
        randomcounter=randomcounter+1
        y2 = y1 + math.sin(math.radians(angle)) * randomnumbers[randomcounter]/10.0 # Y random component
        randomcounter=randomcounter+1
        z2 = z1 + math.sin(math.radians(rotation)) * randomnumbers[randomcounter]/10.0 # Y random component
        randomcounter=randomcounter+1        
        # Base cutting function
        if y2>0:
            glBegin(GL_LINES)
            glColor4f(r/255.0,g/255.0,b/255.0,1.0)
            glVertex3f(x1,y1,z1)
            glVertex3f(x2,y2,z2)
            glEnd()
            randomcounter=drawTree(x2, y2,z2, angle - randomnumbers[randomcounter],0, depth - 1,r,g,b,randomcounter,randomnumbers) # First branch recursive call
            randomcounter=randomcounter+1  
            randomcounter=drawTree(x2, y2,z2, angle + randomnumbers[randomcounter],0, depth - 1,r,g,b,randomcounter,randomnumbers) # Second branch recursive call with random angle
            randomcounter=randomcounter+1  
            randomcounter=drawTree(x2, y2,z2, angle - randomnumbers[randomcounter],rotation+randomnumbers[randomcounter], depth - 1,r,g,b,randomcounter,randomnumbers) # 3th branch recursive call with random angle
            randomcounter=randomcounter+1
            randomcounter=drawTree(x2, y2,z2, angle + randomnumbers[randomcounter],rotation-randomnumbers[randomcounter], depth - 1,r,g,b,randomcounter,randomnumbers) # 4th branch recursive call with random angle
	    randomcounter=randomcounter+1    
    return randomcounter
ev = pygame.event.poll()
print "Rendering..."
rotateh=0
rotatev=0
radius=50.0
while ev.type!=pygame.QUIT: 
    ev = pygame.event.poll()
    keys=pygame.key.get_pressed()
    if keys[K_LEFT]:
        rotateh=rotateh+0.05
    if keys[K_RIGHT]:
        rotateh=rotateh-0.05
    if keys[K_UP]:
        rotatev=rotatev+0.05
    if keys[K_DOWN]:
        rotatev=rotatev-0.05
    if keys[K_w]:
        radius=radius-0.50
    if keys[K_s]:
        radius=radius+0.50
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glTranslatef(0.0,-5.0,0.0)  
    gluLookAt((radius*math.sin(rotateh)) +0.0,(radius*math.sin(rotatev))+ 0.0, (radius*math.cos(rotateh) + (radius*math.cos(rotatev)) -100.0) , 0, 0, -100, 0, 1, 0)
    drawTree(0.0, 0.0, -100,90,0, maxdepth,100,43,0,0,randomnumbers)
    pygame.display.flip()
print "Exit!"
pygame.quit()

Source

Updated to add 360º camera movement.

Updated to add mouse control.


hdirection="stop"
vdirection="stop"
zoomdirection="stop"
while ev.type!=pygame.QUIT: 
    ev = pygame.event.poll()
    # Mouse control
    buttonpress=pygame.mouse.get_pressed()
    rel = pygame.mouse.get_rel()
    # Left - Right movement
    if rel[0]>0  and buttonpress[0]:
	    rotateh=rotateh+0.05
	    hdirection="right"
    if rel[0]<0  and buttonpress[0]:
	    rotateh=rotateh-0.05
	    hdirection="left"
    if not buttonpress[0]:
	    hdirection="stop"
    if rel[0]==0 and buttonpress[0] and hdirection is "left":
	    rotateh=rotateh-0.05
    if rel[0]==0 and buttonpress[0] and hdirection is "right":
	    rotateh=rotateh+0.05
    # Up - Down movement
    if rel[1]>0  and buttonpress[0]:
	    rotateh=rotateh+0.05
	    vdirection="up"
    if rel[1]<0  and buttonpress[0]:
	    rotateh=rotateh-0.05
	    vdirection="down"
    if not buttonpress[0]:
	    vdirection="stop"
    if rel[1]==0 and buttonpress[0] and vdirection is "up":
	    rotatev=rotatev-0.05
    if rel[1]==0 and buttonpress[0] and vdirection is "down":
	    rotatev=rotatev+0.05
    # Zoom In - Out movment
    if rel[1]>0  and buttonpress[2]:
	    radius=radius+0.50
	    zoomdirection="out"
    if rel[1]<0  and buttonpress[2]:
	    radius=radius-0.50
	    zoomdirection="in"
    if not buttonpress[2]:
	    zoomdirection="stop"
    if rel[1]==0 and buttonpress[2] and zoomdirection is "in":
	    radius=radius-0.50
    if rel[1]==0 and buttonpress[2] and zoomdirection is "out":
	    radius=radius+0.50
Posted in OpenGL, Programming, Python Tagged with: , , ,

Leave a Reply

Your email address will not be published. Required fields are marked *

*