defint a-z randomize timer 'this includes all our declarations for the non Tree related routines #include once "syn3d.bi" declare sub drawTree () declare sub generateTree () DIM SHARED pnt(4,7) as single, pntf(4, 2) as single CONST MAX_NODES = 13, MAX_BRANCHES = 13, MAX_LEAVES = 10, MAX_SEGS = 3 type pointType x as single y as single z as single end type TYPE nodeType x AS SINGLE y AS SINGLE z AS SINGLE globalNode as integer plane(MAX_SEGS - 1) as pointType connected as integer END TYPE TYPE nodeAngleType x AS SINGLE y AS SINGLE z AS SINGLE end type TYPE branchType nNodes AS INTEGER nodes(MAX_NODES) as nodeType nodeAngle(MAX_NODES) as nodeAngleType root as nodeType END TYPE type leafType x as single y as single z as single size as single end type DIM SHARED branches(MAX_BRANCHES) AS branchType, leaves(MAX_LEAVES) AS leafType, nBranches DIM SHARED rotSpd!, scaleSpd!, leafscale! DIM SHARED barkTex as gluint, leafTex as gluint DIM SHARED barkTex2 as gluint init load_texture "bark.png", barkTex load_textureAlpha "leaves.png", leafTex generateTree main sub generateTree () sag! = 20 growth! = 0 scale! = .5 leafscale! = 4 twistyness = 30 nleaves = 0 nBranches = MAX_BRANCHES totalNodes = MAX_NODES baseBranches = 1 trunkLength = 4 twigLength = 1.5 branchLengthInter! = (twigLength - trunkLength) / totalNodes trunkWidth = 1.4 twigWidth = 0 branchWidthInter! = (twigWidth - trunkWidth) / totalNodes for branch = 0 to nBranches - 1 for i = 0 to totalNodes - 1 branches(branch).nodes(i).globalNode = 0 branches(branch).nodeAngle(i).x = 0 branches(branch).nodeAngle(i).y = 0 branches(branch).nodeAngle(i).z = 0 branches(branch).nodes(i).x = 0 branches(branch).nodes(i).y = 0 branches(branch).nodes(i).z = 0 next do parentBranch = int(rnd * branch) if baseBranches > 0 then parentBranch = -1 parentNode = -1 if parentBranch > -1 then parentNode = int(rnd * branches(parentBranch).nNodes) branches(branch).root.x = branches(parentBranch).nodes(parentNode).x branches(branch).root.y = branches(parentBranch).nodes(parentNode).y branches(branch).root.z = branches(parentBranch).nodes(parentNode).z branches(branch).nodeAngle(0).x = branches(parentBranch).nodeAngle(parentNode).x branches(branch).nodeAngle(0).y = branches(parentBranch).nodeAngle(parentNode).y + rnd * 180 - 90 branches(branch).nodeAngle(0).z = branches(parentBranch).nodeAngle(parentNode).z globalNode = branches(parentBranch).nodes(parentNode).globalNode else branches(branch).root.x = 0 branches(branch).root.y = 0 branches(branch).root.z = 0 branches(branch).nodeAngle(0).x = 0 branches(branch).nodeAngle(0).y = rnd * 360 branches(branch).nodeAngle(0).z = 0 globalNode = 0 baseBranches = baseBranches - 1 end if nNodes = totalNodes - globalNode branches(branch).nNodes = nNodes if nNodes > 0 and parentNode <> 0 then exit do loop ox! = branches(branch).root.x oy! = branches(branch).root.y oz! = branches(branch).root.z for node = 0 to nNodes - 1 globalNode = globalNode + 1 rx! = branches(branch).nodeAngle(node).x + rnd * twistyness - twistyness / 2 ry! = branches(branch).nodeAngle(node).y + rnd * twistyness - twistyness / 2 rz! = branches(branch).nodeAngle(node).z + rnd * twistyness - twistyness / 2 rz! = rz! + rnd * sag! * rz! / 90 + sag! / 5 rz! = rz! - rnd * growth! * rz! / 90 - growth! / 5 rotpnt 0, (trunkLength + globalNode * branchLengthInter!) * scale!, 0, 0, 0, rz!, nx!, ny!, nz! rotpnt nx!, ny!, nz!, rx!, 0, 0, nx!, ny!, nz! rotpnt nx!, ny!, nz!, 0, ry!, 0, nx!, ny!, nz! branches(branch).nodes(node).x = ox! + nx! branches(branch).nodes(node).y = oy! + ny! branches(branch).nodes(node).z = oz! + nz! branches(branch).nodeAngle(node+1).x = rx! branches(branch).nodeAngle(node+1).y = ry! branches(branch).nodeAngle(node+1).z = rz! branches(branch).nodes(node).globalNode = globalNode branches(branch).nodes(node).connected = branches(branch).nodes(node).connected + 1 ox! = branches(branch).nodes(node).x oy! = branches(branch).nodes(node).y oz! = branches(branch).nodes(node).z for p = 0 to MAX_SEGS - 1 rotpnt 0, 0, (trunkWidth * cos(3.14159 / 2 * globalNode / totalNodes)) * scale!, 0, p * 360/MAX_SEGS, 0, nx!, ny!, nz! rotpnt nx!, ny!, nz!, 0, 0, rz!, nx!, ny!, nz! rotpnt nx!, ny!, nz!, rx!, 0, 0, nx!, ny!, nz! rotpnt nx!, ny!, nz!, 0, ry!, 0, nx!, ny!, nz! branches(branch).nodes(node).plane(p).x = ox! + nx! branches(branch).nodes(node).plane(p).y = oy! + ny! branches(branch).nodes(node).plane(p).z = oz! + nz! next next next for leaf = 0 to MAX_LEAVES try = 0 do try = try + 1 if try = 100 then exit do branch = int(rnd * nBranches) node = int(rnd * branches(branch).nNodes) globalNode = branches(branch).nodes(node).globalNode pass = 0 if globalNode > MAX_NODES / 2 and globalNode < MAX_NODES - 1 then pass = 1 for i = 0 to leaf - 1 ff = 0 if leaves(i).x = branches(branch).nodes(node).x then ff = ff + 1 if leaves(i).y = branches(branch).nodes(node).y then ff = ff + 1 if leaves(i).z = branches(branch).nodes(node).z then ff = ff + 1 if ff = 3 then pass = 0 next if pass = 1 then exit do loop leaves(leaf).x = branches(branch).nodes(node).x leaves(leaf).y = branches(branch).nodes(node).y leaves(leaf).z = branches(branch).nodes(node).z leaves(leaf).size = branches(branch).nodes(node).connected if leaves(leaf).size > 2 then leaves(leaf).size = 2 next end sub sub init () SDL_FLAGS = SDL_HWSURFACE OR SDL_OPENGL OR SDL_GL_DOUBLEBUFFER 'SDL_FLAGS = SDL_FLAGS OR SDL_FULLSCREEN if SDL_Init(SDL_INIT_EVERYTHING) <> 0 THEN end 1 selectRes video = SDL_SetVideoMode (SCR_WIDTH, SCR_HEIGHT, SCR_BITS, SDL_FLAGS) if video = 0 then SDL_Quit end 1 end if SDL_WM_SetCaption "display", "" glViewport 0, 0, SCR_WIDTH, SCR_HEIGHT glMatrixMode GL_PROJECTION glLoadIdentity FOVy = 40 aspect! = SCR_WIDTH / SCR_HEIGHT znear! = .1 zfar! = 1000 gluPerspective FOVy, aspect!, znear!, zfar! glMatrixMode GL_MODELVIEW glLoadIdentity glShadeModel GL_SMOOTH glClearColor .5, .5, .5, 1 glClearDepth 1.0 glEnable GL_DEPTH_TEST glDepthFunc GL_LEQUAL glEnable GL_COLOR_MATERIAL glHint GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST lightAmbient(0) = .2 lightAmbient(1) = .2 lightAmbient(2) = .2 lightAmbient(3) = 1 lightDiffuse(0) = 1 lightDiffuse(1) = 1 lightDiffuse(2) = .9 lightDiffuse(3) = 1 lightSpecular(0) = lightDiffuse(0) lightSpecular(1) = lightDiffuse(1) lightSpecular(2) = lightDiffuse(2) lightSpecular(3) = 1 lightEmission(0) = 0 lightEmission(1) = 0 lightEmission(2) = 0 lightEmission(3) = 1 glEnable GL_LIGHTING glLightModelfv GL_LIGHT_MODEL_AMBIENT, @lightAmbient(0) glShadeModel GL_SMOOTH lightPosition(0) = 0 lightPosition(1) = 20 lightPosition(2) = 0 glLightfv GL_LIGHT1, GL_AMBIENT, @lightAmbient(0) glLightfv GL_LIGHT1, GL_DIFFUSE, @lightDiffuse(0) glLightfv GL_LIGHT1, GL_SPECULAR, @lightSpecular(0) glLightfv GL_LIGHT1, GL_POSITION, @lightPosition(0) glEnable GL_LIGHT1 glEnable GL_COLOR_MATERIAL glColorMaterial GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE glMaterialfv GL_FRONT_AND_BACK, GL_SPECULAR, @lightSpecular(0) glMaterialfv GL_FRONT_AND_BACK, GL_EMISSION, @lightEmission(0) glMaterialf GL_FRONT_AND_BACK, GL_SHININESS, 75 lightAmbient(0) = 0 lightAmbient(1) = 0 lightAmbient(2) = 0 lightAmbient(3) = 1 lightDiffuse(0) = 1 / 2 lightDiffuse(1) = 1 / 2 lightDiffuse(2) = .9 / 2 lightDiffuse(3) = 1 lightSpecular(0) = lightDiffuse(0) lightSpecular(1) = lightDiffuse(1) lightSpecular(2) = lightDiffuse(2) lightSpecular(3) = 1 glLightfv GL_LIGHT2, GL_AMBIENT, @lightAmbient(0) glLightfv GL_LIGHT2, GL_DIFFUSE, @lightDiffuse(0) glLightfv GL_LIGHT2, GL_SPECULAR, @lightSpecular(0) glEnable GL_LIGHT1 glEnable GL_LIGHTING glCullFace GL_BACK glEnable GL_CULL_FACE glEnable GL_TEXTURE_2D glHint GL_LINE_SMOOTH_HINT, GL_NICEST if linesmoothing then glEnable GL_LINE_SMOOTH 'glLineWidth 2 'glBlendFunc GL_SRC_ALPHA, GL_ONE glBlendFunc GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA glAlphaFunc GL_GREATER, .5 glEnable GL_BLEND glEnable GL_ALPHA_TEST glEnable GL_RESCALE_NORMAL yheight = 5 xres = SCR_WIDTH yres = SCR_HEIGHT xcen = xres / 2 ycen = yres / 2 xzratio! = xres / 1.6 yzratio! = yres / 1.6 camx = 0 camy = 0 'camz = 15 rad = 3.141592 / 180 zback = 50 rotSpd! = .05 scaleSpd! = .01 camrx = 20 glLoadIdentity end sub sub main () fpsr = 1 waitticks = ticks + 1000 do checkinputs drawview SDL_GL_SwapBuffers SDL_PumpEvents tickspassed = ticks ticks = SDL_GetTicks tickspassed = ticks - tickspassed fpsr = (fpsr + tickspassed / 20) / 2 fp = fp + 1 if ticks > nextticks then nextticks = ticks + 1000 fps = fp fp = 0 end if locate 1,1:print fps 'body.yangle = body.yangle + 1 'if body.yangle >= 360 then body.yangle = body.yangle - 360 loop end sub sub checkinputs () keys = SDL_GetKeyState(null) if keys[SDLK_ESCAPE] then deinit while SDL_PollEvent(@event) if event.type = SDL_EXIT then deInit wend if keys[SDLK_LEFT] then camry -= rotSpd! if keys[SDLK_RIGHT] then camry += rotSpd! if keys[SDLK_DOWN] then camrx += rotSpd! if keys[SDLK_UP] then camrx -= rotSpd! if keys[SDLK_KP_PLUS] then zback -= scaleSpd! if keys[SDLK_KP_MINUS] then zback += scaleSpd! if keys[SDLK_RETURN] and waitTicks < ticks then generateTree waitTicks = ticks + 150 end if end sub sub drawTree () glBindTexture GL_TEXTURE_2D, barkTex glColor3f 1, 1, 1 for pass = 0 to 1 if pass = 0 then glBegin GL_TRIANGLES if pass = 1 then glBegin GL_QUADS for branch = 0 to nBranches - 1 nNodes = branches(branch).nNodes for node = 0 to nNodes - 1 for p = 0 to MAX_SEGS - 1 n = p + 1 if n = MAX_SEGS then n = 0 pntf(0,0) = branches(branch).nodes(node).plane(n).x pntf(0,1) = branches(branch).nodes(node).plane(n).y pntf(0,2) = branches(branch).nodes(node).plane(n).z n = p pntf(3,0) = branches(branch).nodes(node).plane(n).x pntf(3,1) = branches(branch).nodes(node).plane(n).y pntf(3,2) = branches(branch).nodes(node).plane(n).z nn = node - 1 if nn > -1 then n = p + 1 if n = MAX_SEGS then n = 0 pntf(1,0) = branches(branch).nodes(nn).plane(n).x pntf(1,1) = branches(branch).nodes(nn).plane(n).y pntf(1,2) = branches(branch).nodes(nn).plane(n).z n = p pntf(2,0) = branches(branch).nodes(nn).plane(n).x pntf(2,1) = branches(branch).nodes(nn).plane(n).y pntf(2,2) = branches(branch).nodes(nn).plane(n).z refs = 4 else pntf(1,0) = branches(branch).root.x pntf(1,1) = branches(branch).root.y pntf(1,2) = branches(branch).root.z refs = 3 end if cross2 pntf(0, 0), pntf(0, 1), pntf(0, 2), pntf(1, 0), pntf(1, 1), pntf(1, 2), pntf(3, 0), pntf(3, 1), pntf(3, 2), nx!, ny!, nz! glNormal3f nx!, ny!, nz! if refs = 3 and pass = 0 then 'triangle glTexCoord2f 0, 0 glVertex3f pntf(0,0), pntf(0,1), pntf(0,2) glTexCoord2f .5, 1 glVertex3f pntf(1,0), pntf(1,1), pntf(1,2) glTexCoord2f 1, 0 glVertex3f pntf(3,0), pntf(3,1), pntf(3,2) elseif refs = 4 and pass = 1 then 'quad glTexCoord2f 0, 0 glVertex3f pntf(0,0), pntf(0, 1), pntf(0,2) glTexCoord2f 0, 1 glVertex3f pntf(1,0), pntf(1, 1), pntf(1,2) glTexCoord2f 1, 1 glVertex3f pntf(2,0), pntf(2, 1), pntf(2,2) glTexCoord2f 1, 0 glVertex3f pntf(3,0), pntf(3, 1), pntf(3,2) end if next next next glEnd next 'draw the leaf planes: pnt(0,0) = .5 pnt(0,1) = -.5 pnt(1,0) = .5 pnt(1,1) = .5 pnt(2,0) = -.5 pnt(2,1) = .5 pnt(3,0) = -.5 pnt(3,1) = -.5 glDisable GL_LIGHTING glBindTexture GL_TEXTURE_2D, leafTex glColor4f 1, 1, 1, .8 for leaf = 0 to MAX_LEAVES glPushMatrix glTranslatef leaves(leaf).x, leaves(leaf).y, leaves(leaf).z glRotatef camrz, 0, 0, -1 glRotatef camry, 0, 1, 0 glRotatef camrx, -1, 0, 0 for p = 0 to 3 pntf(p, 0) = pnt(p,0) * leaves(leaf).size * leafscale! pntf(p, 1) = pnt(p,1) * leaves(leaf).size * leafscale! pntf(p, 2) = 0 next glBegin GL_QUADS glTexCoord2f 0, 0 glVertex3f pntf(0,0), pntf(0, 1), pntf(0,2) glTexCoord2f 0, 1 glVertex3f pntf(1,0), pntf(1, 1), pntf(1,2) glTexCoord2f 1, 1 glVertex3f pntf(2,0), pntf(2, 1), pntf(2,2) glTexCoord2f 1, 0 glVertex3f pntf(3,0), pntf(3, 1), pntf(3,2) glEnd glPopMatrix next glEnable GL_LIGHTING end sub sub drawview () dim dataset as objectinfo ptr glPolygonMode GL_FRONT_AND_BACK, GL_FILL glClear GL_COLOR_BUFFER_BIT OR GL_DEPTH_BUFFER_BIT glLoadIdentity glTranslatef 0, -yheight, -zback glRotatef camrx, 1, 0, 0 glRotatef camry, 0, -1, 0 glRotatef camrz, 0, 0, 1 glLightfv GL_LIGHT1, GL_POSITION, @lightPosition(0) glTranslatef -camx, -camy, -camz glPushMatrix 'draw something drawTree glDisable GL_LIGHTING glDisable GL_TEXTURE_2D glBegin GL_POINTS glColor3f 1, 1, 1 for x = -10 to 10 for z = -10 to 10 glVertex3f x, 0, z next next glEnd glEnable GL_LIGHTING glEnable GL_TEXTURE_2D glPopMatrix glFlush end sub