Анимация с помощью OpenGl(Вращение шестиугольников)
Красивая реализация вращения узора, базой дизайна которого служит
шестиугольник.
Платформы: Widows, Linux
Автор: Alexander Pritchard
/' ' Recursive Vector Revolution From a Parent Origin ' Copyright (c) 2008 Alexander Pritchard (TheAdventMaster@gmail.com) ' All Rights Reserved ' Contact: TheAdventMaster@gmail.com ' ' Use of the FreeBASIC Graphics Library, GFXlib 2, ' Copyright (c) Angelo Mottola (a.mottola@libero.it) under terms and ' conditions of the GNU LGPL - GNU LESSER GENERAL PUBLIC LICENSE: ' Copyright (C) 1991, 1999 Free Software Foundation, Inc. ' 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ' ' Free for free public use and distribution unless requested otherwise. You ' may not use this program or its contents in any commercial application ' without permission from the author. Doing so without permission may lead ' to a request to remove this program and its contents from your application. ' ' This program is distributed in the hope that it will be useful, but WITHOUT ' ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ' FOR A PARTICULAR PURPOSE. '/ ' </unnecessary licensing> #INCLUDE Once "gl\gl.bi" #INCLUDE Once "fbgfx.bi" #DEFINE false 0 #DEFINE true (Not false) #DEFINE pi (Atn(1)*4) '' i am careful... #DEFINE toRadians(that) ((that)*(pi/180)) #DEFINE toDegrees(that) ((that)*(180/pi)) '' I hate (partially) recoding my vector class for every example I make... Type Vec2 As Vec2 Ptr origin As Single x, y Declare Function getAngle() As Single Declare Sub incAngle( Byval degrees As Single ) Declare Sub setAngle( Byval degrees As Single ) Declare Function getMagnitude() As Single Declare Function ox() As Single Declare Function oy() As Single End Type Function Vec2.ox() As Single If( origin <> 0 ) Then Return x + origin->ox() Else Return x End If End Function Function Vec2.oy() As Single If( origin <> 0 ) Then Return y + origin->oy() Else Return y End If End Function Sub Vec2.incAngle( Byval degrees As Single ) setAngle( getAngle() + degrees ) End Sub Sub Vec2.setAngle( Byval degrees As Single ) '' keep degrees in range If( degrees < 0 ) Then degrees = -degrees If( degrees >= 360 ) Then degrees = degrees Mod 360 End If degrees = 360 - degrees Else If( degrees >= 360 ) Then degrees = degrees Mod 360 End If End If '' record current magnitude then set angle Dim As Single curMagnitude = getMagnitude() x = Cos( toRadians(degrees) ) * curMagnitude y = -sin( toRadians(degrees) ) * curMagnitude End Sub Function Vec2.getAngle() As Single '' get the radians to degrees of our angle Dim As Single retVal = toDegrees( -atan2( y, x ) ) + 360 '' keep the angle in bounds If( retVal < 360 ) Then Return retVal Else Return retVal - 360 End If End Function Function Vec2.getMagnitude() As Single '' only calculate magnitude if at least one value is != 0 If( x <> 0 ) Then Return Sqr( (x * x) + (y * y) ) Else If( y <> 0 ) Then Return Sqr( (x * x) + (y * y) ) Else Return 0 End If End If End Function '' '' ''' ''' ''' ''' ''' '''' '''' '''' CODE THAT SORTA DOES STUFF STARTS BELOW! '''' '''' ''' ''' ''' ''' '' '' Randomize Timer() '''' GL Technical Specs '' render child polygons? (potentially really neat effect) Const As Integer RENDER_CHILD_POLYGONS = true '' render parent's children polygon? (which can get annoying) '' only in effect when RENDER_CHILD_POLYGONS is on Const As Integer RENDER_PARENT_CHILD_POLYGON = false '''' technical specs '' number of branches Const As Integer BRANCH_COUNT = 4 '' number of children each node has Const As Integer CHILD_COUNT = 6 '' start direction Const As Integer START_DIRECTION = -1 '''' main setup (modifiers are important, too) '' RADIUS of each object Const As Single RADIUS = 30 '' speed of rotation in degrees per second Const As Single ROTATION_SPEED = 20 '' distance a child is from their parent Const As Single CHILD_DISTANCE = 200 '''' modifiers '' RADIUS multiplier from one branch to the next Const As Single RADIUS_CHANGE = .5 '' rotation speed multiplier from one branch to the next Const As Single ROTATION_SPEED_CHANGE = .8314 '' distance change from one branch to the next Const As Single CHILD_DISTANCE_CHANGE = .5 '''' parent node info '' position... will visibly rotate if <> 0 Const As Integer OFFSET_X = 0 Const As Integer OFFSET_Y = 0 '''' (almost) pretty stuff '' coloring scheme: 0 = random, 1 = white to black, 2 = black to white, 3 custom color Const As Integer COLORING_SCHEME = 3 '' ALPHA value for rendering the objects Const As Single ALPHA = .99f '' clear color Const As Single CLEAR_COLOR_R = 0 Const As Single CLEAR_COLOR_G = 0 Const As Single CLEAR_COLOR_B = 0 Const As Single CLEAR_COLOR_A = 1 '' whether we should clear the screen at all Const As Integer CLEAR_SCREEN = true '''' custom color data if we chose to use it '' we edit RGBA individually here. it's a lot easier than doing otherwise. Const As Uinteger CUSTOM_COLOR_R = 1f Const As Uinteger CUSTOM_COLOR_G = .51f Const As Uinteger CUSTOM_COLOR_B = 0f '' color change for the RGB values Const As Single CUSTOM_COLOR_R_CHANGE = 1 Const As Single CUSTOM_COLOR_G_CHANGE = .8 Const As Single CUSTOM_COLOR_B_CHANGE = 1 Const As Single CUSTOM_COLOR_A_CHANGE = .75 Type Vec2Spiral As Vec2Spiral Ptr Ptr child As Integer numChild As Vec2 us As Integer direction As Single childColorR As Single childColorG As Single childColorB As Single childColorA As Single usColorR As Single usColorG As Single usColorB As Single usColorA '' used for child creation and updating As Single usRotSpeed '' used for child creation (see modifiers above) As Single usRadius As Single usDistance End Type Declare Sub deleteTree( Byref that As Vec2Spiral ) Declare Sub createTree( Byref that As Vec2Spiral, Byval curLevel As Integer ) Declare Sub stepTree( Byref that As Vec2Spiral, Byval stepVal As Single ) Declare Sub renderTree( Byref that As Vec2Spiral, Byval curLevel As Integer ) Screenres 640, 480, 32, , fb.GFX_OPENGL glMatrixMode(GL_PROJECTION) glLoadIdentity() glViewport(0, 0, 640, 480) glOrtho( 0, 640, 480, 0, -1f, 1f ) glMatrixMode(GL_MODELVIEW) glLoadIdentity glClear( GL_COLOR_BUFFER_BIT ) If( ALPHA <> 0 ) Then If( ALPHA <> 1f ) Then glEnable(GL_BLEND) glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) End If End If For doVar As Integer = 0 To 1 glColor3f( CLEAR_COLOR_R, CLEAR_COLOR_G, CLEAR_COLOR_B ) glBegin(GL_QUADS) glVertex2f(0, 0) glVertex2f(640, 0) glVertex2f(640, 480) glVertex2f(0, 480) glEnd() Flip() Next '' create our start node Dim As Vec2Spiral startNode startNode.us.origin = New Vec2 startNode.us.x = OFFSET_X startNode.us.y = OFFSET_Y startNode.us.origin->x = 320 startNode.us.origin->y = 240 startNode.direction = -START_DIRECTION Select Case As Const COLORING_SCHEME Case 0 startNode.usColorR = Rnd() * 1f startNode.usColorG = Rnd() * 1f startNode.usColorB = Rnd() * 1f startNode.usColorA = ALPHA Case 1 startNode.usColorR = 1f startNode.usColorG = 1f startNode.usColorB = 1f startNode.usColorA = ALPHA Case 2 startNode.usColorR = 0f startNode.usColorG = 0f startNode.usColorB = 0f startNode.usColorA = ALPHA Case 3 startNode.usColorR = CUSTOM_COLOR_R startNode.usColorG = CUSTOM_COLOR_G startNode.usColorB = CUSTOM_COLOR_B startNode.usColorA = ALPHA End Select startNode.usRadius = RADIUS startNode.usRotSpeed = ROTATION_SPEED startNode.usDistance = CHILD_DISTANCE '' create an entire set of nodes underneath it createTree( startNode, 0 ) '' start time Dim As Single cur = Timer() Dim As Single last = cur Do '' Yuck. Very vague. This code is below... Recursive shiz. stepTree( startNode, cur - last ) If( CLEAR_SCREEN = true ) Then glColor4f( CLEAR_COLOR_R, CLEAR_COLOR_G, CLEAR_COLOR_B, CLEAR_COLOR_A ) glBegin(GL_QUADS) glVertex2f(0, 0) glVertex2f(640, 0) glVertex2f(640, 480) glVertex2f(0, 480) glEnd() End If renderTree( startNode, 0 ) Flip() Do Sleep(1, 1) Loop Until (Timer() - last) >= (1/60) last = cur cur = Timer() Loop Until Multikey(1) Sub deleteTree( Byref that As Vec2Spiral ) If( that.child <> 0 ) Then For doVar As Integer = 0 To that.numChild - 1 deleteTree( *that.child[doVar] ) Next End If '' loop through all our mems deletes it For doVar As Integer = 0 To that.numChild - 1 Delete(that.child[doVar]) that.child[doVar] = 0 Next Deallocate(that.child) that.child = 0 End Sub Sub createTree( Byref that As Vec2Spiral, Byval curLevel As Integer ) '' reverse rotation direction for every branch Static As Integer curDirection = -START_DIRECTION Static As Integer recursionLevel = 0 If( curLevel <> recursionLevel ) Then curDirection = -curDirection End If '' we're before our max recursion level... create branches If( curLevel < BRANCH_COUNT ) Then '' create our child list that.child = Callocate( Sizeof(Vec2Spiral Ptr) * CHILD_COUNT ) that.numChild = CHILD_COUNT '' set color for fun :-) Select Case As Const COLORING_SCHEME Case 0 that.childColorR = Rnd() * 1f that.childColorG = Rnd() * 1f that.childColorB = Rnd() * 1f that.childColorA = ALPHA Case 1 that.childColorR = (1f/BRANCH_COUNT) * (curLevel+1) that.childColorG = (1f/BRANCH_COUNT) * (curLevel+1) that.childColorB = (1f/BRANCH_COUNT) * (curLevel+1) that.childColorA = ALPHA Case 2 that.childColorR = 1f - ((1f/BRANCH_COUNT) * (curLevel+1)) that.childColorG = 1f - ((1f/BRANCH_COUNT) * (curLevel+1)) that.childColorB = 1f - ((1f/BRANCH_COUNT) * (curLevel+1)) that.childColorA = ALPHA Case 3 that.childColorR = CUSTOM_COLOR_R * (CUSTOM_COLOR_R_CHANGE ^ (curLevel+1)) that.childColorG = CUSTOM_COLOR_G * (CUSTOM_COLOR_G_CHANGE ^ (curLevel+1)) that.childColorB = CUSTOM_COLOR_B * (CUSTOM_COLOR_B_CHANGE ^ (curLevel+1)) that.childColorA = ALPHA * (CUSTOM_COLOR_A_CHANGE ^ (curLevel+1)) End Select For doVar As Integer = 0 To CHILD_COUNT - 1 '' create child at given index that.child[doVar] = New Vec2Spiral '''' apply modifier data '' RADIUS that.child[doVar]->usRadius = that.usRadius * RADIUS_CHANGE '' rotation speed that.child[doVar]->usRotSpeed = that.usRotSpeed * ROTATION_SPEED_CHANGE '' distance that.child[doVar]->usDistance = that.usDistance * CHILD_DISTANCE_CHANGE '''' init child data '' direction that.child[doVar]->direction = curDirection '' origin that.child[doVar]->us.origin = @that.us '' position (polar) that.child[doVar]->us.x = that.child[doVar]->usDistance that.child[doVar]->us.setAngle( (360/CHILD_COUNT) * doVar ) '' color (see that.childColor = above) that.child[doVar]->usColorR = that.childColorR that.child[doVar]->usColorG = that.childColorG that.child[doVar]->usColorB = that.childColorB that.child[doVar]->usColorA = that.childColorA '' create child tree createTree( (*that.child[doVar]), curLevel + 1 ) curDirection = -curDirection Next End If End Sub Sub stepTree( Byref that As Vec2Spiral, Byval stepVal As Single ) If( that.child <> 0 ) Then For doVar As Integer = 0 To that.numChild - 1 stepTree( *that.child[doVar], stepVal ) Next End If that.us.incAngle( (that.usRotSpeed * stepVal) * that.direction ) End Sub Sub renderTree( Byref that As Vec2Spiral, Byval curLevel As Integer ) Dim As Integer renderChild = true If( that.child <> 0 ) Then For doVar As Integer = 0 To that.numChild - 1 renderTree( *that.child[doVar], curLevel + 1 ) Next If( RENDER_PARENT_CHILD_POLYGON = false ) Then If( curLevel = 0 ) Then renderChild = false End If End If If( RENDER_CHILD_POLYGONS = true ) Then If( renderChild = true ) Then '' render us through our children (live on through your kids???) glColor4f( that.childColorR, that.childColorG, that.childColorB, that.childColorA ) glBegin(GL_POLYGON) For doVar As Integer = 0 To that.numChild - 1 glVertex2f( that.child[doVar]->us.ox(), that.child[doVar]->us.oy() ) Next glEnd() End If End If Else '' render us glColor4f( that.usColorR, that.usColorG, that.usColorB, that.usColorA ) glBegin(GL_POLYGON) For doVar As Single = 0f To 360f Step (360f/16f) glVertex2f( that.us.ox() + (Cos( toRadians(doVar) ) * that.usRadius), that.us.oY() + (-sin( toRadians(doVar) ) * that.usRadius) ) Next glEnd() End If End Sub