From 2c01bd6cfd78f2cbb562144b39358b55d5e5c07d Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 20 Jun 2003 19:31:06 +0000 Subject: [PATCH] Fractal demo (John Fay) git-svn-id: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@92 7f0cb862-5218-0410-a997-914c9d46530a --- progs/demos/Fractals/Fractals.dsp | 101 ++++++++ progs/demos/Fractals/fractals.c | 282 +++++++++++++++++++++++ progs/demos/Fractals/fractals.dat | 10 + progs/demos/Fractals_random/Fractals_random.dsp | 101 ++++++++ progs/demos/Fractals_random/fractals.dat | 10 + progs/demos/Fractals_random/fractals_random.c | 264 +++++++++++++++++++++ 6 files changed, 768 insertions(+) create mode 100644 progs/demos/Fractals/Fractals.dsp create mode 100644 progs/demos/Fractals/fractals.c create mode 100644 progs/demos/Fractals/fractals.dat create mode 100644 progs/demos/Fractals_random/Fractals_random.dsp create mode 100644 progs/demos/Fractals_random/fractals.dat create mode 100644 progs/demos/Fractals_random/fractals_random.c diff --git a/progs/demos/Fractals/Fractals.dsp b/progs/demos/Fractals/Fractals.dsp new file mode 100644 index 0000000..c919eb4 --- /dev/null +++ b/progs/demos/Fractals/Fractals.dsp @@ -0,0 +1,101 @@ +# Microsoft Developer Studio Project File - Name="Fractals" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=Fractals - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Fractals.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Fractals.mak" CFG="Fractals - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Fractals - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Fractals - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Fractals - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "FREEGLUT_STATIC" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /libpath:"../../../freeglut_static___Win32_Release" + +!ELSEIF "$(CFG)" == "Fractals - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Fractals___Win32_Debug" +# PROP BASE Intermediate_Dir "Fractals___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Fractals___Win32_Debug" +# PROP Intermediate_Dir "Fractals___Win32_Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "FREEGLUT_STATIC" /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"../../../freeglut_static___Win32_Debug" + +!ENDIF + +# Begin Target + +# Name "Fractals - Win32 Release" +# Name "Fractals - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\fractals.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/progs/demos/Fractals/fractals.c b/progs/demos/Fractals/fractals.c new file mode 100644 index 0000000..027e31d --- /dev/null +++ b/progs/demos/Fractals/fractals.c @@ -0,0 +1,282 @@ +/* fractals.c */ +/* + * Program to draw a fractal by Michael Barnsley's deterministic algorithm. + * Algorithm: + * (1) Define the affine transformations (of the form r(i+1) = A r(i) + b ) + * (2) Find the stationary point for each transformation + * (3) To draw: + * - If you are at the lowest level, draw lines connecting all the stationary points + * - If not, call the draw function recursively with each affine transformation applied + */ + +/* + * User Commands: + * +,- - increment/decrement number of levels + * PgUp, PgDn - increase/decrease scaling + * Arrow keys - translate viewing section + * r - reset view + * Escape - quit + */ + +#include +#include +#include +#include + +typedef struct +{ + double a00, a01, a10, a11 ; /* Transformation matrix */ + double b0, b1 ; /* Constant vector added on */ + double statx, staty ; /* Coordinates of the stationary point */ +} +AffineTrans ; + +/* Number of levels to draw the fractal */ +static int num_levels = 0 ; + +/* The definition of the fractal */ +static int num_trans ; +static AffineTrans *affine ; + +/* the window title */ +char window_title [ 80 ] ; + +/* The amount the view is translated and scaled */ +float xwin = 0.0, ywin = 0.0 ; +float scale_factor = 1.0 ; + +static void draw_level ( int num, double m00, double m01, double m10, double m11, double n0, double n1 ) +{ + /* Draw a fractal transformed by "M", "N" as passed in */ + int i ; + + if ( num == 0 ) + { + double x0 = m00 * affine[0].statx + m01 * affine[0].staty + n0 ; + double y0 = m10 * affine[0].statx + m11 * affine[0].staty + n1 ; + + for ( i = 1; i < num_trans; i++ ) + { + double x1 = m00 * affine[i].statx + m01 * affine[i].staty + n0 ; + double y1 = m10 * affine[i].statx + m11 * affine[i].staty + n1 ; + + glVertex2f ( x0, y0 ) ; + glVertex2f ( x1, y1 ) ; + + x0 = x1 ; + y0 = y1 ; + } + } + else + { + /* Map each affine transformation in the fractal through the one passed in and call "draw_level" */ + + for ( i = 0; i < num_trans; i++ ) + { + draw_level ( num-1, m00*affine[i].a00+m01*affine[i].a10, m00*affine[i].a01+m01*affine[i].a11, + m10*affine[i].a00+m11*affine[i].a10, m10*affine[i].a01+m11*affine[i].a11, + m00*affine[i].b0 +m01*affine[i].b1 + n0, m10*affine[i].b0 +m11*affine[i].b1 + n1 ) ; + } + } +} + +static void +Display(void) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* the curve */ + glPushMatrix(); + glScalef(2.5, 2.5, 2.5); + + glColor4f(0.0, 0.0, 0.0, 1.0); + glBegin ( GL_LINES ) ; + draw_level ( num_levels, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 ); + glEnd () ; + + glPopMatrix(); + glutSwapBuffers(); +} + +static void +Reshape(int width, int height) +{ + float ar; + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + ar = (float) width / (float) height; + glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + xwin = -1.0 ; + ywin = 0.0 ; + glTranslatef(xwin, ywin, -5.0); +} + +static void +Key(unsigned char key, int x, int y) +{ + switch (key) { + case 27: /* Escape key */ + glutLeaveMainLoop (); + break; + + case '+' : + ++num_levels ; + break ; + + case '-' : + if (num_levels > 0) + --num_levels; + break ; + + case 'r' : case 'R' : + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + xwin = -1.0 ; + ywin = 0.0 ; + glTranslatef(xwin, ywin, -5.0); + + break ; + } + + glutPostRedisplay(); +} + +static void +Special(int key, int x, int y) +{ + switch (key) { + case GLUT_KEY_UP : + glMatrixMode(GL_MODELVIEW); + ywin += 0.1 * scale_factor ; + glTranslatef(0.0, 0.1 * scale_factor, 0.0); + break ; + + case GLUT_KEY_DOWN : + glMatrixMode(GL_MODELVIEW); + ywin -= 0.1 * scale_factor ; + glTranslatef(0.0, -0.1 * scale_factor, 0.0); + break ; + + case GLUT_KEY_LEFT : + glMatrixMode(GL_MODELVIEW); + xwin -= 0.1 * scale_factor ; + glTranslatef(-0.1 * scale_factor, 0.0, 0.0); + break ; + + case GLUT_KEY_RIGHT : + glMatrixMode(GL_MODELVIEW); + xwin += 0.1 * scale_factor ; + glTranslatef(0.1 * scale_factor, 0.0, 0.0); + break ; + + case GLUT_KEY_PAGE_UP : + glMatrixMode(GL_MODELVIEW); + glTranslatef ( -xwin, -ywin, 0.0 ) ; + glScalef(1.25, 1.25, 1.25); + glTranslatef ( xwin, ywin, 0.0 ) ; + scale_factor *= 0.8 ; + break ; + + case GLUT_KEY_PAGE_DOWN : + glMatrixMode(GL_MODELVIEW); + glTranslatef ( -xwin, -ywin, 0.0 ) ; + glScalef(0.8, 0.8, 0.8); + glTranslatef ( xwin, ywin, 0.0 ) ; + scale_factor *= 1.25 ; + break ; + } + + glutPostRedisplay(); +} + +void readConfigFile ( char *fnme ) +{ + FILE *fptr = fopen ( fnme, "rt" ) ; + int i ; + char inputline [ 256 ] ; + + /* Read a header line */ + fgets ( inputline, 256, fptr ) ; + + /* Read a comment line */ + fgets ( inputline, 256, fptr ) ; + + /* Read the window title */ + fgets ( inputline, 256, fptr ) ; + sscanf ( inputline, "%s", window_title ) ; + + /* Read a comment line */ + fgets ( inputline, 256, fptr ) ; + + /* Read the number of affine transformations */ + fgets ( inputline, 256, fptr ) ; + sscanf ( inputline, "%d", &num_trans ) ; + + affine = (AffineTrans *)malloc ( num_trans * sizeof(AffineTrans) ) ; + + /* Read a comment line */ + fgets ( inputline, 256, fptr ) ; + + for ( i = 0; i < num_trans; i++ ) + { + double m00, m01, m10, m11 ; /* Matrix "I" minus "A" */ + double determ ; /* Determinant of this matrix */ + + /* Read an affine transformation definition */ + fgets ( inputline, 256, fptr ) ; + sscanf ( inputline, "%lf %lf %lf %lf %lf %lf", &affine[i].a00, &affine[i].a01, + &affine[i].a10, &affine[i].a11, &affine[i].b0, &affine[i].b1 ) ; + + /* Calculate the stationary point */ + + m00 = 1.0 - affine[i].a00 ; + m01 = - affine[i].a01 ; + m10 = - affine[i].a10 ; + m11 = 1.0 - affine[i].a11 ; + + determ = m00 * m11 - m01 * m10 ; + + if ( fabs ( determ ) > 1.e-6 ) + { + affine[i].statx = ( m11 * affine[i].b0 - m01 * affine[i].b1 ) / determ ; + affine[i].staty = ( -m10 * affine[i].b0 + m00 * affine[i].b1 ) / determ ; + } + else + affine[i].statx = affine[i].staty = 0.0 ; + } +} + +int +main(int argc, char *argv[]) +{ + int fractal_window ; + + if ( argc > 1 ) + readConfigFile ( argv[1] ) ; + else + readConfigFile ( "fractals.dat" ) ; + + glutInit(&argc, argv); + glutInitWindowSize(500, 250); + glutInitWindowPosition ( 140, 140 ) ; + + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); + + fractal_window = glutCreateWindow( window_title ); + + glClearColor(1.0, 1.0, 1.0, 1.0); + + glutReshapeFunc(Reshape); + glutKeyboardFunc(Key); + glutSpecialFunc(Special); + glutDisplayFunc(Display); + + glutMainLoop(); + + printf ( "Back from the 'freeglut' main loop\n" ) ; + + return 0; /* ANSI C requires main to return int. */ +} diff --git a/progs/demos/Fractals/fractals.dat b/progs/demos/Fractals/fractals.dat new file mode 100644 index 0000000..6a32de6 --- /dev/null +++ b/progs/demos/Fractals/fractals.dat @@ -0,0 +1,10 @@ +Koch Snowflake Fractal +Title of window +"Koch Snowflake" +Number of transformations +4 + A00 A01 A10 A11 B0 B1 +0.33333 0.0 0.0 0.33333 0.0 0.0 +0.16667 -.28868 0.28868 0.16667 0.33333 0.0 +0.16667 0.28868 -.28868 0.16667 0.5 0.28868 +0.33333 0.0 0.0 0.33333 0.66667 0.0 diff --git a/progs/demos/Fractals_random/Fractals_random.dsp b/progs/demos/Fractals_random/Fractals_random.dsp new file mode 100644 index 0000000..b8b3290 --- /dev/null +++ b/progs/demos/Fractals_random/Fractals_random.dsp @@ -0,0 +1,101 @@ +# Microsoft Developer Studio Project File - Name="Fractals_random" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=Fractals_random - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Fractals_random.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Fractals_random.mak" CFG="Fractals_random - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Fractals_random - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Fractals_random - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Fractals_random - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "Fractals_random - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "FREEGLUT_STATIC" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"C:\openGL\freeglut\freeglut_static___Win32_Debug" + +!ENDIF + +# Begin Target + +# Name "Fractals_random - Win32 Release" +# Name "Fractals_random - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\fractals_random.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/progs/demos/Fractals_random/fractals.dat b/progs/demos/Fractals_random/fractals.dat new file mode 100644 index 0000000..6a32de6 --- /dev/null +++ b/progs/demos/Fractals_random/fractals.dat @@ -0,0 +1,10 @@ +Koch Snowflake Fractal +Title of window +"Koch Snowflake" +Number of transformations +4 + A00 A01 A10 A11 B0 B1 +0.33333 0.0 0.0 0.33333 0.0 0.0 +0.16667 -.28868 0.28868 0.16667 0.33333 0.0 +0.16667 0.28868 -.28868 0.16667 0.5 0.28868 +0.33333 0.0 0.0 0.33333 0.66667 0.0 diff --git a/progs/demos/Fractals_random/fractals_random.c b/progs/demos/Fractals_random/fractals_random.c new file mode 100644 index 0000000..a935adc --- /dev/null +++ b/progs/demos/Fractals_random/fractals_random.c @@ -0,0 +1,264 @@ +/* fractals_random.c */ +/* This demo shows a single-buffering "freeglut" example. */ + +/* + * Program to draw a fractal by Michael Barnsley's stochastic algorithm. + * Algorithm: + * (1) Define the affine transformations (of the form r(i+1) = A r(i) + b ) + * (2) Find the stationary point for the first transformation + * (3) To draw: + * - Pick a random integer between 1 and the number of transformations (inclusive) + * - Send the current point through the transformation to create the new current point + * - Plot the new current point + */ + +/* + * User Commands: + * PgUp, PgDn - increase/decrease scaling + * Arrow keys - translate viewing section + * r - reset view + * Escape - quit + */ + +#include +#include +#include +#include + +typedef struct +{ + double a00, a01, a10, a11 ; /* Transformation matrix */ + double b0, b1 ; /* Constant vector added on */ + double statx, staty ; /* Coordinates of the stationary point */ +} +AffineTrans ; + +/* Number of levels to draw the fractal */ +static int num_levels = 0 ; + +/* The definition of the fractal */ +static int num_trans ; +static AffineTrans *affine ; + +/* the window title */ +char window_title [ 80 ] ; + +/* The amount the view is translated */ +float xwin = 0.0, ywin = 0.0 ; +float scale_factor = 1.0 ; + +/* The current point */ +float current_x = 0.0, current_y = 0.0 ; + +static void draw_level ( int num, double m00, double m01, double m10, double m11, double n0, double n1 ) +{ + /* Draw a fractal transformed by "M", "N" as passed in */ + int i ; + + for ( i = 0; i < 10; i++ ) + { + int random = rand () * num_trans / RAND_MAX ; + float new_x = affine[random].a00 * current_x + affine[random].a01 * current_y + affine[random].b0 ; + float new_y = affine[random].a10 * current_x + affine[random].a11 * current_y + affine[random].b1 ; + + glVertex2f ( new_x, new_y ) ; + current_x = new_x ; + current_y = new_y ; + } +} + +static void +Display(void) +{ + /* the curve */ + glPushMatrix(); + glScalef(2.5, 2.5, 2.5); + + glColor4f(0.0, 0.0, 0.0, 1.0); + glBegin ( GL_POINTS ) ; + draw_level ( num_levels, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 ); + glEnd () ; + + glPopMatrix(); + glutPostRedisplay(); /* Needed so that this function will be called again */ +} + +static void +Reshape(int width, int height) +{ + float ar; + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + ar = (float) width / (float) height; + glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + xwin = -1.0 ; + ywin = 0.0 ; + glTranslatef(xwin, ywin, -5.0); +} + +static void +Key(unsigned char key, int x, int y) +{ + switch (key) { + case 27: /* Escape key */ + glutLeaveMainLoop (); + break; + + case 'r' : case 'R' : + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + xwin = -1.0 ; + ywin = 0.0 ; + glTranslatef(xwin, ywin, -5.0); + + break ; + } + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glutPostRedisplay(); +} + +static void +Special(int key, int x, int y) +{ + switch (key) { + case GLUT_KEY_UP : + glMatrixMode(GL_MODELVIEW); + ywin += 0.1 * scale_factor ; + glTranslatef(0.0, 0.1 * scale_factor, 0.0); + break ; + + case GLUT_KEY_DOWN : + glMatrixMode(GL_MODELVIEW); + ywin -= 0.1 * scale_factor ; + glTranslatef(0.0, -0.1 * scale_factor, 0.0); + break ; + + case GLUT_KEY_LEFT : + glMatrixMode(GL_MODELVIEW); + xwin -= 0.1 * scale_factor ; + glTranslatef(-0.1 * scale_factor, 0.0, 0.0); + break ; + + case GLUT_KEY_RIGHT : + glMatrixMode(GL_MODELVIEW); + xwin += 0.1 * scale_factor ; + glTranslatef(0.1 * scale_factor, 0.0, 0.0); + break ; + + case GLUT_KEY_PAGE_UP : + glMatrixMode(GL_MODELVIEW); + glTranslatef ( -xwin, -ywin, 0.0 ) ; + glScalef(1.25, 1.25, 1.25); + glTranslatef ( xwin, ywin, 0.0 ) ; + scale_factor *= 0.8 ; + break ; + + case GLUT_KEY_PAGE_DOWN : + glMatrixMode(GL_MODELVIEW); + glTranslatef ( -xwin, -ywin, 0.0 ) ; + glScalef(0.8, 0.8, 0.8); + glTranslatef ( xwin, ywin, 0.0 ) ; + scale_factor *= 1.25 ; + break ; + } + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glutPostRedisplay(); +} + +void readConfigFile ( char *fnme ) +{ + FILE *fptr = fopen ( fnme, "rt" ) ; + int i ; + char inputline [ 256 ] ; + + /* Read a header line */ + fgets ( inputline, 256, fptr ) ; + + /* Read a comment line */ + fgets ( inputline, 256, fptr ) ; + + /* Read the window title */ + fgets ( inputline, 256, fptr ) ; + sscanf ( inputline, "%s", window_title ) ; + + /* Read a comment line */ + fgets ( inputline, 256, fptr ) ; + + /* Read the number of affine transformations */ + fgets ( inputline, 256, fptr ) ; + sscanf ( inputline, "%d", &num_trans ) ; + + affine = (AffineTrans *)malloc ( num_trans * sizeof(AffineTrans) ) ; + + /* Read a comment line */ + fgets ( inputline, 256, fptr ) ; + + for ( i = 0; i < num_trans; i++ ) + { + double m00, m01, m10, m11 ; /* Matrix "I" minus "A" */ + double determ ; /* Determinant of this matrix */ + + /* Read an affine transformation definition */ + fgets ( inputline, 256, fptr ) ; + sscanf ( inputline, "%lf %lf %lf %lf %lf %lf", &affine[i].a00, &affine[i].a01, + &affine[i].a10, &affine[i].a11, &affine[i].b0, &affine[i].b1 ) ; + + /* Calculate the stationary point */ + + m00 = 1.0 - affine[i].a00 ; + m01 = - affine[i].a01 ; + m10 = - affine[i].a10 ; + m11 = 1.0 - affine[i].a11 ; + + determ = m00 * m11 - m01 * m10 ; + + if ( fabs ( determ ) > 1.e-6 ) + { + affine[i].statx = ( m11 * affine[i].b0 - m01 * affine[i].b1 ) / determ ; + affine[i].staty = ( -m10 * affine[i].b0 + m00 * affine[i].b1 ) / determ ; + } + else + affine[i].statx = affine[i].staty = 0.0 ; + } +} + +int +main(int argc, char *argv[]) +{ + int fractal_window ; + + if ( argc > 1 ) + readConfigFile ( argv[1] ) ; + else + readConfigFile ( "fractals.dat" ) ; + + glutInit(&argc, argv); + glutInitWindowSize(500, 250); + glutInitWindowPosition ( 140, 140 ) ; + + glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH); + + fractal_window = glutCreateWindow( window_title ); + + glClearColor(1.0, 1.0, 1.0, 1.0); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glutReshapeFunc(Reshape); + glutKeyboardFunc(Key); + glutSpecialFunc(Special); + glutDisplayFunc(Display); + + glutMainLoop(); + + printf ( "Back from the 'freeglut' main loop\n" ) ; + + return 0; /* ANSI C requires main to return int. */ +} -- 1.7.10.4