|
Trouver une ressource
Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !
ATTRACTEURS DE FAMILLES DE CONTRACTIONS EN ÉCRAN DE VEILLE
Information sur la source
Description
Bonjour à tous, c'est mon tout premier programme en C posté ici, donc un peu d'indulgence ;-) Il s'agit d'un programme de démonstration OpenGl/GLUT qui affiche une famille d'IFS (Iterated Function System) d'une manière que l'auteur (moi!) espère harmonieuse. Ce sont des ensembles fractaux, colorés et animés dans le temps. Le programme essaie d'adapter la qualité (complexité) de l'image aux performances de la machine, ainsi que la densité de l'image pour qu'elle reste à peu près uniforme. Au démarrage l'image est peu détaillée, elle va progressivement le devenir au fur et à mesure que le programme détecte que les performances de la machine sont suffisantes pour suivre (en général au bout d'une quinzaine de secondes). Il ne faut pas demander plus de frames par secondes que la fréquence de l'écran en mode DoubleBuffered (sinon le programme va croire que la machine rame et diminuer la qualité). Le source a été pensé pour pouvoir aussi être compilé en tant qu'écran de veille (uniquement sous Windows): il suffit de définir #define SCREENSAVER pour que ça le compile en écran de veille (il faudra aussi changer l'extension du fichier compilé en .scr, et faire un clic droit dessus pour l'installer sous Windows). En mode normal (pas SCREENSAVER) ou en mode configuration de l'écran de veille il faut appuyer sur ESCAPE pour afficher/cacher le menu. Les paramètres peuvent être enregistrés dans un fichier ini du même nom que le programme, et automatiquement chargés au démarrage (si le fichier existe). Il y a encore deux options de compilation supplémentaire: USE_TEXTURE et USE_MULTIPLE_TEXTURES, la seconde nécessite la première. Avec USE_TEXTURE il est possibe de faire un motion blur plus "smooth" utilisant une texture. La seconde nécessite OpenGl 1.1 au moins, et utilise 2 textures pour le motion blur et le blending par couches, afin de permettre un filtrage des couleurs plus riche. À réserver aux cartes graphiques récentes... Noter que pour pouvoir compiler il faut que vous ayez installé GLUT. Par exemple comme expliqué ici sous dev-cpp: http://people.bath.ac.uk/ab8lam/computing/DevCpp.htm. Ou encore pour d'autres compilateurs: http://www.math.u-psud.fr/~feuvrier/enseignement/2007/M2/site005.html En théorie le source compile tant sous Windows que sous Linux (à condition de mettre les bonnes lib, comme indiqué dans les liens). J'ai mis le .exe (renommé en .ex_) et le .scr (l'écran de veille compilé) dans le zip au cas où... Si vous avez des commentaires, n'hésitez pas!
Source
- #define USE_COS_TABLE
- #define USE_TEXTURE
- #define USE_MULTIPLE_TEXTURES
- //#define SCREENSAVER
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <math.h>
- #include <time.h>
- #include "glut_import.h"
- #include "menu.h"
-
- /*********************************************************************
- * CONSTANTS *
- *********************************************************************/
-
- #define FPS_COUNTER_TRIGGER 15
- #define FPS_COUNTER_SMOOTH 0.3
-
- #define PROXY_SIZE 32
- #define PROXY_QUALITY 5
-
- #define MIN_COLOR (10./256.)
- #define MIN_POINT_COUNT 300
-
- #define INI_FILENAME "AFC.ini"
-
- #ifdef USE_MULTIPLE_TEXTURES
- # ifndef USE_TEXTURE
- # error You cannot specify USE_MULTIPLE_TEXTURES without specifying USE_TEXTURE
- # endif
- # define INVALID_TEXTURE_INDEX 0xFFFFFFFF
- #endif
-
- /*********************************************************************
- * PLATFORM *
- *********************************************************************/
-
- #ifdef __WIN32__
- # ifdef SCREENSAVER
- # define SCREENSAVER_MODE_SHOW 0x1
- # define SCREENSAVER_MODE_CONFIGURE 0x2
- # define SCREENSAVER_MODE_PREVIEW 0x4
- # define MAX_SCREENSAVER_MOUSE_OFFSET 10
- # endif
- # include <windows.h>
- # define SLEEP(_DELAY) Sleep(_DELAY)
- # define TIME_GRANULARITY 12
- #else
- # ifdef SCREENSAVER
- # error Usage of SCREENSAVER reserved for Windows
- # endif
- # include <unistd.h>
- # define SLEEP(_DELAY) usleep(1000*_DELAY)
- # define TIME_GRANULARITY 6
- #endif
-
- /*********************************************************************
- * COSINE TABLE SUPPORT *
- *********************************************************************/
-
- #ifdef USE_COS_TABLE
- # define COS_TABLE_QUALITY 0x1000
- float CosTable[COS_TABLE_QUALITY];
- void initCos(void){
- int i;
- for (i=0;i<COS_TABLE_QUALITY;i++)
- CosTable[i]=cos(PI*i/COS_TABLE_QUALITY);
- }
- float cosTable(float x){
- int n;
- if (x<0)
- x=-x;
- n=((int) roundf(COS_TABLE_QUALITY*x/PI)) % (2*COS_TABLE_QUALITY);
- if (n<COS_TABLE_QUALITY)
- return CosTable[n];
- else
- return CosTable[2*COS_TABLE_QUALITY-1-n];
- }
- # define COS(_X) cosTable((_X))
- # define SIN(_X) cosTable((_X)-0.5*PI)
- #else
- # define COS(_X) cos((_X))
- # define SIN(_X) sin((_X))
- #endif
-
- /*********************************************************************
- * MACROS *
- *********************************************************************/
-
- #define ASSERT(_X,_S) if (!(_X)) {printf("%s\n",_S);exit(-1);}
- #define MEMCHECK(_X) if (!(_X)) {printf("Memory allocation failed\n");exit(-1);}
-
- /*********************************************************************
- * TYPES *
- *********************************************************************/
-
- typedef struct{
- int Count,Degree;
- float *Matrix;
- } transformation;
-
- #ifdef USE_TEXTURE
- typedef struct{
- # ifdef USE_MULTIPLE_TEXTURES
- unsigned int Index;
- # endif
- int ImageWidth,ImageHeight,Width,Height;
- } texture;
- #endif
-
- #pragma pack(push,1)
- #pragma pack(1)
- typedef struct{
- unsigned char R,G,B,A;
- float X,Y,Z;
- } point;
- #pragma pack(pop)
-
- /*********************************************************************
- * APPLICATION DATA *
- *********************************************************************/
-
- struct {
- struct {
- int Index,Width,Height,FullScreen,DesiredFullScreen,DoubleBuffered,DesiredDoubleBuffered,MultiSample,DesiredMultiSample,ChangeMode;
- #ifdef SCREENSAVER
- int ScreenSaverMode,MouseX,MouseY;
- #endif
- #ifdef USE_TEXTURE
- texture TextureMotion;
- # ifdef USE_MULTIPLE_TEXTURES
- texture TextureAccum;
- # endif
- #endif
- } Window;
- struct {
- int Tick,PeriodStart,PeriodLength,TickTime;
- float Elasticity,Map,FPS,DesiredFPS;
- } Time;
- struct {
- transformation T1,T2;
- int MinDegree,MaxDegree;
- } Transformations;
- struct {
- int Count,DesiredCount,Rounded;
- float Size;
- point *Data;
- } Points;
- struct {
- float Alpha,SpaceFrequency,TimeFrequency;
- } ColorMap;
- struct {
- int BlendMethod,LimitCPUUsage,MotionBlur,Accumulation;
- float Luminance,Sharpness,Attenuation;
- } Display;
- struct {
- float Density;
- char sFrame[64],sTime[64],sFPS[64],sPointCount[64],sDensity[64],sPointSize[64],sAlpha[64],sCycle[64],sAttractor1[64],sAttractor2[64];
- } Statistics;
- menu *MainMenu;
- } ApplicationData={
- {-1,1,1,0,0,1,1,0,0,0
- #ifdef SCREENSAVER
- ,0,-1,-1
- #endif
- #ifdef USE_TEXTURE
- # ifdef USE_MULTIPLE_TEXTURES
- ,{INVALID_TEXTURE_INDEX,0,0,0,0},{INVALID_TEXTURE_INDEX,0,0,0,0}
- # else
- ,{0,0,0,0}
- # endif
- #endif
- },
- {0,0,5000,0,5,0,50,40},
- {{0,0,NULL},{0,0,NULL},0,20},
- {0,2*MIN_POINT_COUNT,1,1,NULL},
- {0,1,1},
- {0,0,0,0,1,1,0.1},
- {0,"","","","","","","","","",""}
- };
-
- /*********************************************************************
- * FUNCTIONS *
- *********************************************************************/
-
- void evolveWindow(void);
- void evolveAlloc(void);
- void evolveTime(void);
- void evolvePoints(void);
- void evolveProxy(void);
- void evolveColorMap(void);
- void evolve(void);
-
- void displayFunc(void);
- void reshapeFunc(int,int);
- void idleFunc(void);
- void keyboardFunc(unsigned char,int,int);
- void specialFunc(int,int,int);
- void mouseFunc(int,int,int,int);
- #ifdef SCREENSAVER
- void passiveMotionFunc(int,int);
- #endif
-
- void readIniFile(void);
- void writeIniFile(void);
-
- void fullScreenChange(int);
- void fullScreenParamChange(int);
- void doubleBufferedChange(int);
- void multiSampleChange(int);
- #ifdef USE_TEXTURE
- void motionBlurChange(int);
- #endif
- void desiredFPSChange(int);
- void limitCPUUsageChange(int);
- void resetExecute(void);
- void saveExecute(void);
- void quitExecute(void);
-
- void roundedPointsChange(int);
- void blendMethodChange(int);
- void luminanceChange(float);
- void sharpnessChange(float);
- void attenuationChange(float);
- void spaceFrequencyChange(float);
- void timeFrequencyChange(float);
-
- void periodChange(float);
- void elasticityChange(float);
- void minDegreeChange(int);
- void maxDegreeChange(int);
-
- /*********************************************************************
- * MENU DESIGN *
- *********************************************************************/
-
- SEPARATOR(Separator);
-
- CHECKBOX(CheckBoxFullScreen,"Fullscreen (F)",0,fullScreenChange);
- static char *ListBoxResolution_Items[6]={"default","320x240","640x480","800x600","1024x768","1280x1024"};
- LISTBOX(ListBoxResolution,"Fullscreen resolution :",0,ListBoxResolution_Items,fullScreenParamChange);
- static char *ListBoxBPP_Items[4]={"default","16","24","32"};
- LISTBOX(ListBoxBPP,"Fullscreen color depth (BPP) :",0,ListBoxBPP_Items,fullScreenParamChange);
- static char *ListBoxFrequency_Items[11]={"default","50","60","65","70","72","75","80","85","90","100"};
- LISTBOX(ListBoxFrequency,"Fullscreen refresh rate (Hz) :",0,ListBoxFrequency_Items,fullScreenParamChange);
- CHECKBOX(CheckBoxDoubleBuffered,"Double buffered (D)",1,doubleBufferedChange);
- CHECKBOX(CheckBoxMultiSample,"Multi sample (M)",0,multiSampleChange);
- #ifdef USE_TEXTURE
- # ifdef USE_MULTIPLE_TEXTURES
- static char *ListBoxMotionBlur_Items[7]={"Single buffer","Double buffer","Triple buffer (2x filter)",
- "Triple buffer (3x filter)","Triple buffer (4x filter)","Triple buffer (5x filter)",
- "Triple buffer (6x filter)"};
- LISTBOX(ListBoxMotionBlur,"Motion blur",1,ListBoxMotionBlur_Items,motionBlurChange);
- # else
- CHECKBOX(CheckBoxMotionBlur,"High quality motion blur",1,motionBlurChange);
- # endif
- #endif
- ITRACKBAR(FTrackBarDesiredFPS,"Requested frame rate: %d",5,120,40,1,desiredFPSChange);
- CHECKBOX(CheckBoxLimitCPUUsage,"Limit CPU usage",0,limitCPUUsageChange);
- #ifdef SCREENSAVER
- STATICTEXT(StaticTextReset,"Reset settings (R)",1,resetExecute);
- STATICTEXT(StaticTextSave,"Save settings and exit (S)",1,saveExecute);
- STATICTEXT(StaticTextQuit,"Cancel (Q)",1,quitExecute);
- # ifdef USE_TEXTURE
- static menuitem *MenuPageAFC_Items[14]={
- # else
- static menuitem *MenuPageAFC_Items[13]={
- # endif
- #else
- STATICTEXT(StaticTextSave,"Save settings (S)",1,saveExecute);
- STATICTEXT(StaticTextReset,"Reset settings",1,resetExecute);
- STATICTEXT(StaticTextQuit,"Quit (Q)",1,quitExecute);
- # ifdef USE_TEXTURE
- static menuitem *MenuPageAFC_Items[15]={
- # else
- static menuitem *MenuPageAFC_Items[14]={
- # endif
- #endif
- &CheckBoxFullScreen,
- &ListBoxResolution,
- &ListBoxBPP,
- &ListBoxFrequency,
- &Separator,
- &CheckBoxDoubleBuffered,
- &CheckBoxMultiSample,
- #ifdef USE_TEXTURE
- # ifdef USE_MULTIPLE_TEXTURES
- &ListBoxMotionBlur,
- # else
- &CheckBoxMotionBlur,
- # endif
- #endif
- &FTrackBarDesiredFPS,
- &CheckBoxLimitCPUUsage,
- &Separator,
- #ifdef SCREENSAVER
- &StaticTextReset,
- &StaticTextSave,
- &StaticTextQuit
- #else
- &StaticTextSave,
- &StaticTextReset,
- &Separator,
- &StaticTextQuit
- #endif
- };
- MENUPAGE(MenuPageAFC,"AFC Version 1.0",MenuPageAFC_Items);
-
- CHECKBOX(CheckBoxRoundedPoints,"Rounded points",1,roundedPointsChange);
- static char *ListBoxBlendMethod_Items[3]={"Logarithmic","Linear","Maximum"};
- LISTBOX(ListBoxBlendMethod,"Blend color method :",0,ListBoxBlendMethod_Items,blendMethodChange);
- FTRACKBAR(FTrackBarLuminance,"Luminance : %.0f%%",0,200,100,1,luminanceChange);
- FTRACKBAR(FTrackBarSharpness,"Sharpness : %.0f%%",0,200,100,1,sharpnessChange);
- FTRACKBAR(FTrackBarAttenuation,"Attenuation : %.1f%%",0.1,100,10,0.1,attenuationChange);
- FTRACKBAR(FTrackBarSpaceFrequency,"Colormap space frequency : %.2f",0,50,1,0.02,spaceFrequencyChange);
- FTRACKBAR(FTrackBarTimeFrequency,"Colormap time frequency : %.2f",0,20,1,0.02,timeFrequencyChange);
- static menuitem *MenuPageDisplay_Items[9]={
- &CheckBoxRoundedPoints,
- &ListBoxBlendMethod,
- &Separator,
- &FTrackBarLuminance,
- &FTrackBarSharpness,
- &FTrackBarAttenuation,
- &Separator,
- &FTrackBarSpaceFrequency,
- &FTrackBarTimeFrequency
- };
- MENUPAGE(MenuPageDisplay,"DISPLAY",MenuPageDisplay_Items);
-
- FTRACKBAR(FTrackBarPeriod,"Cycle length : %.1f sec",0.5,20,5,0.1,periodChange);
- FTRACKBAR(FTrackBarElasticity,"Cycle elasticity : %.1f",0.1,30,5,0.1,elasticityChange);
- ITRACKBAR(ITrackBarMinDegree,"Min attractor degree : %d",3,15,6,1,minDegreeChange);
- ITRACKBAR(ITrackBarMaxDegree,"Max attractor degree : %d",3,15,6,1,maxDegreeChange);
- static menuitem *MenuPageAttractor_Items[4]={&FTrackBarPeriod,&FTrackBarElasticity,&ITrackBarMinDegree,&ITrackBarMaxDegree};
- MENUPAGE(MenuPageAttractor,"ATTRACTOR",MenuPageAttractor_Items);
-
- STATICTEXT(StaticTextFrame,ApplicationData.Statistics.sFrame,0,NULL);
- STATICTEXT(StaticTextTime,ApplicationData.Statistics.sTime,0,NULL);
- STATICTEXT(StaticTextFPS,ApplicationData.Statistics.sFPS,0,NULL);
- STATICTEXT(StaticTextPointCount,ApplicationData.Statistics.sPointCount,0,NULL);
- STATICTEXT(StaticTextDensity,ApplicationData.Statistics.sDensity,0,NULL);
- STATICTEXT(StaticTextPointSize,ApplicationData.Statistics.sPointSize,0,NULL);
- STATICTEXT(StaticTextAlpha,ApplicationData.Statistics.sAlpha,0,NULL);
- STATICTEXT(StaticTextCycle,ApplicationData.Statistics.sCycle,0,NULL);
- STATICTEXT(StaticTextAttractor1,ApplicationData.Statistics.sAttractor1,0,NULL);
- STATICTEXT(StaticTextAttractor2,ApplicationData.Statistics.sAttractor2,0,NULL);
- static menuitem *MenuPageStatistics_Items[12]={
- &StaticTextFrame,
- &StaticTextTime,
- &StaticTextFPS,
- &Separator,
- &StaticTextPointCount,
- &StaticTextDensity,
- &StaticTextPointSize,
- &StaticTextAlpha,
- &Separator,
- &StaticTextCycle,
- &StaticTextAttractor1,
- &StaticTextAttractor2
- };
- MENUPAGE(MenuPageStatistics," STATISTICS ",MenuPageStatistics_Items);
-
- static menupage *MainMenu_Pages[4]={&MenuPageAFC,&MenuPageDisplay,&MenuPageAttractor,&MenuPageStatistics};
- MENU(MainMenu,MainMenu_Pages);
-
- /*********************************************************************
- * UTILITIES *
- *********************************************************************/
-
- int pgcd(int x,int y){
- if (y)
- return pgcd(y,x%y);
- else
- return x;
- }
-
- int ppcm(int x,int y){
- return (x*y)/pgcd(x,y);
- }
-
- int nextPowerOfTwo(int x){
- int u=1;
- while (u<x)
- u*=2;//<<=1;
- return u;
- }
-
- float mapExp(float x,float t){
- if (x<0.5)
- return 0.5*pow(2*x,t);
- else
- return 1-0.5*pow(2-2*x,t);
- }
-
- /*********************************************************************
- * TEXTURE UTILITIES *
- *********************************************************************/
-
- #ifdef USE_TEXTURE
- void copyTexture(texture *T){
- # ifdef USE_MULTIPLE_TEXTURES
- if (T->Index==INVALID_TEXTURE_INDEX)
- glGenTextures(1,&T->Index);
- glBindTexture(GL_TEXTURE_2D,T->Index);
- # endif
- if (ApplicationData.Window.Width!=T->ImageWidth || ApplicationData.Window.Height!=T->ImageHeight){
- T->ImageWidth=ApplicationData.Window.Width;
- T->ImageHeight=ApplicationData.Window.Height;
- T->Width=nextPowerOfTwo(T->ImageWidth);
- T->Height=nextPowerOfTwo(T->ImageHeight);
- glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,T->Width,T->Height,0,GL_RGB,GL_UNSIGNED_BYTE,NULL);
- }
- glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,T->ImageWidth,T->ImageHeight);
- }
-
- int paintTexture(texture *T,int Mode){
- # ifdef USE_MULTIPLE_TEXTURES
- if (T->Index!=INVALID_TEXTURE_INDEX && T->Width && T->Height){
- # else
- if (T->Width && T->Height){
- # endif
- float u=(float) T->ImageWidth/T->Width,v=(float) T->ImageHeight/T->Height;
- glPushAttrib(GL_ALL_ATTRIB_BITS);
- glPushMatrix();
- # ifdef USE_MULTIPLE_TEXTURES
- glBindTexture(GL_TEXTURE_2D,T->Index);
- # endif
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
- glEnable(GL_TEXTURE_2D);
- glBegin(GL_QUADS);
- glTexCoord2f(0,0);
- glVertex2f(-1,-1);
- glTexCoord2f(0,v);
- glVertex2f(-1,1);
- glTexCoord2f(u,v);
- glVertex2f(1,1);
- glTexCoord2f(u,0);
- glVertex2f(1,-1);
- glEnd();
- glDisable(GL_TEXTURE_2D);
- glPopMatrix();
- glPopAttrib();
- return 1;
- }
- return 0;
- }
-
- void deleteTexture(texture *T){
- # ifdef USE_MULTIPLE_TEXTURES
- if (T->Index!=INVALID_TEXTURE_INDEX){
- glDeleteTextures(1,&T->Index);
- T->Index=INVALID_TEXTURE_INDEX;
- # endif
- T->Width=0;
- T->Height=0;
- T->ImageWidth=0;
- T->ImageHeight=0;
- # ifdef USE_MULTIPLE_TEXTURES
- }
- # endif
- }
- #endif
-
- /*********************************************************************
- * AFFINE TRANSFORMATIONS *
- *********************************************************************/
-
- void allocTransformation(transformation *t){
- int i,*T;
- if (ApplicationData.Transformations.MaxDegree==ApplicationData.Transformations.MinDegree)
- t->Degree=ApplicationData.Transformations.MinDegree;
- else
- t->Degree=ApplicationData.Transformations.MinDegree+(rand() % (1+ApplicationData.Transformations.MaxDegree-ApplicationData.Transformations.MinDegree));
- t->Count=t->Degree-(rand() % (t->Degree/2));
- if (t->Count==t->Degree)
- t->Count--;
- MEMCHECK(T=(int *) calloc(t->Degree,sizeof(int)));
- MEMCHECK(t->Matrix=(float *) malloc(6*t->Count*sizeof(float)));
- for (i=0;i<t->Count;i++){
- float o=2*PI*(rand() % t->Degree)/t->Degree,u=(rand() % 2)-0.5,v=-0.5;
- int k=-1,j=1+(rand() % (t->Degree-i));
- t->Matrix[6*i]=u*cos(o);
- t->Matrix[6*i+1]=-v*sin(o);
- t->Matrix[6*i+3]=u*sin(o);
- t->Matrix[6*i+4]=v*cos(o);
- while (j){
- k++;
- if (!T[k])
- j--;
- }
- T[k]=1;
- o=PI*(1.+2*k)/t->Degree;
- t->Matrix[6*i+2]=0.5*cos(o);
- t->Matrix[6*i+5]=0.5*sin(o);
- }
- free(T);
- }
-
- void freeTransformation(transformation *t){
- free(t->Matrix);
- t->Count=0;
- }
-
- void applyTransformation(transformation *t,int r,float *x,float *y){
- float u=t->Matrix[6*r]*(*x)+t->Matrix[6*r+1]*(*y)+t->Matrix[6*r+2];
- *y=t->Matrix[6*r+3]*(*x)+t->Matrix[6*r+4]*(*y)+t->Matrix[6*r+5];
- *x=u;
- }
-
- /*********************************************************************
- * WINDOW *
- *********************************************************************/
-
- void createWindow(void){
- if (ApplicationData.Window.Index==-1){
- int m=GLUT_RGBA;
- char s[64]="";
- if (ApplicationData.Window.DesiredDoubleBuffered)
- m|=GLUT_DOUBLE;
- ApplicationData.Window.DoubleBuffered=ApplicationData.Window.DesiredDoubleBuffered;
- if (ApplicationData.Window.DesiredMultiSample)
- m|=GLUT_MULTISAMPLE;
- ApplicationData.Window.MultiSample=ApplicationData.Window.DesiredMultiSample;
- glutInitDisplayMode(m);
- if (ApplicationData.Window.DesiredFullScreen){
- if (ListBoxResolution.Data.ListBox->ItemIndex)
- strcat(s,ListBoxResolution.Data.ListBox->Items[ListBoxResolution.Data.ListBox->ItemIndex]);
- if (ListBoxBPP.Data.ListBox->ItemIndex){
- strcat(s,":");
- strcat(s,ListBoxBPP.Data.ListBox->Items[ListBoxBPP.Data.ListBox->ItemIndex]);
- }
- if (ListBoxFrequency.Data.ListBox->ItemIndex){
- strcat(s,"@");
- strcat(s,ListBoxFrequency.Data.ListBox->Items[ListBoxFrequency.Data.ListBox->ItemIndex]);
- }
- if (*s){
- glutGameModeString(s);
- if (!glutGameModeGet(GLUT_GAME_MODE_POSSIBLE)){
- printf("Unsupported display mode (%s). Fullscreen has been canceled.\n",s);
- ApplicationData.Window.DesiredFullScreen=0;
- }
- }
- }
- CheckBoxFullScreen.Data.CheckBox->Checked=ApplicationData.Window.DesiredFullScreen;
- if (ApplicationData.Window.DesiredFullScreen)
- ApplicationData.Window.Index=glutEnterGameMode();
- else {
- glutInitWindowSize(640,480);
- glutInitWindowPosition((glutGet(GLUT_SCREEN_WIDTH)-640)/2,(glutGet(GLUT_SCREEN_HEIGHT)-480)/2);
- ApplicationData.Window.Index=glutCreateWindow("AFC");
- }
- ApplicationData.Window.FullScreen=ApplicationData.Window.DesiredFullScreen;
- ApplicationData.Window.ChangeMode=0;
- #ifdef USE_TEXTURE
- deleteTexture(&ApplicationData.Window.TextureMotion);
- # ifdef USE_MULTIPLE_TEXTURES
- deleteTexture(&ApplicationData.Window.TextureAccum);
- # endif
- #endif
- #ifdef SCREENSAVER
- if (ApplicationData.Window.ScreenSaverMode==SCREENSAVER_MODE_SHOW)
- glutSetCursor(GLUT_CURSOR_NONE);
- else
- #endif
- glutSetCursor(GLUT_CURSOR_CROSSHAIR);
- glutDisplayFunc(displayFunc);
- glutReshapeFunc(reshapeFunc);
- glutIdleFunc(idleFunc);
- glutKeyboardFunc(keyboardFunc);
- glutSpecialFunc(specialFunc);
- glutMouseFunc(mouseFunc);
- #ifdef SCREENSAVER
- glutPassiveMotionFunc(passiveMotionFunc);
- #endif
- }
- }
-
- void destroyWindow(void){
- if (ApplicationData.Window.Index!=-1){
- if (ApplicationData.Window.FullScreen)
- glutLeaveGameMode();
- else
- glutDestroyWindow(ApplicationData.Window.Index);
- }
- ApplicationData.Window.Index=-1;
- }
-
- /*********************************************************************
- * ANIMATION CORE *
- *********************************************************************/
-
- float u1,u2,u3,u4,u5,u6;
-
- void evolveWindow(void){
- if (ApplicationData.Window.MultiSample^ApplicationData.Window.DesiredMultiSample ||
- ApplicationData.Window.DoubleBuffered^ApplicationData.Window.DesiredDoubleBuffered ||
- ApplicationData.Window.FullScreen^ApplicationData.Window.DesiredFullScreen ||
- ApplicationData.Window.ChangeMode) {
- destroyWindow();
- createWindow();
- }
- }
-
- void evolveAlloc(void){
- if (ApplicationData.Points.Count!=ApplicationData.Points.DesiredCount){
- int i;
- MEMCHECK(ApplicationData.Points.Data=(point *) realloc(ApplicationData.Points.Data,ApplicationData.Points.DesiredCount*sizeof(point)));
- if (!ApplicationData.Points.Count){
- float o=2*PI*rand()/RAND_MAX,r=(float) rand()/RAND_MAX;
- ApplicationData.Points.Data[0].X=r*cos(o);
- ApplicationData.Points.Data[0].Y=r*sin(o);
- ApplicationData.Points.Data[0].Z=0;
- ApplicationData.Points.Data[0].A=255;
- }
- for (i=ApplicationData.Points.Count;i<ApplicationData.Points.DesiredCount;i++)
- ApplicationData.Points.Data[i]=ApplicationData.Points.Data[0];
- ApplicationData.Points.Count=ApplicationData.Points.DesiredCount;
- }
- }
-
- void evolveTime(void){
- int t=glutGet(GLUT_ELAPSED_TIME),u=(t-ApplicationData.Time.PeriodStart)/ApplicationData.Time.PeriodLength;
- while (u--){
- freeTransformation(&ApplicationData.Transformations.T1);
- ApplicationData.Transformations.T1=ApplicationData.Transformations.T2;
- allocTransformation(&ApplicationData.Transformations.T2);
- ApplicationData.Time.PeriodStart+=ApplicationData.Time.PeriodLength;
- }
- ApplicationData.Time.Map=mapExp((float) (t-ApplicationData.Time.PeriodStart)/ApplicationData.Time.PeriodLength,ApplicationData.Time.Elasticity);
- if ((++ApplicationData.Time.Tick & FPS_COUNTER_TRIGGER)==FPS_COUNTER_TRIGGER){
- char s[64];
- float r;
- ApplicationData.Time.FPS=(1-FPS_COUNTER_SMOOTH)*1000*(1+FPS_COUNTER_TRIGGER)/(t+1-ApplicationData.Time.TickTime)+FPS_COUNTER_SMOOTH*ApplicationData.Time.FPS;
- ApplicationData.Time.TickTime=t;
- r=ApplicationData.Time.FPS/ApplicationData.Time.DesiredFPS;
- if (r>1.05)
- ApplicationData.Points.DesiredCount+=ApplicationData.Points.DesiredCount*(1-1/r);
- if (r<0.95)
- ApplicationData.Points.DesiredCount-=ApplicationData.Points.DesiredCount*(1-r);
- if (ApplicationData.Points.DesiredCount<MIN_POINT_COUNT){
- ApplicationData.Points.DesiredCount=MIN_POINT_COUNT;
- printf("Your system is TOO SLOW to run this program at the requested frame rate. Please lower it to improve image quality (its value MUST be less than the screen refresh rate if you are using double buffered mode, since the display cannot go faster than the screen in this case).\n");
- }
- sprintf(s,"AFC (%.0f FPS , %d points)\0",ApplicationData.Time.FPS,ApplicationData.Points.Count);
- glutSetWindowTitle(s);
- }
- }
-
- void evolvePoints(void){
- int i;
- for (i=0;i<ApplicationData.Points.Count;i++){
- int r=rand(),r1=r % ApplicationData.Transformations.T1.Count,r2=r % ApplicationData.Transformations.T2.Count;
- point *p=ApplicationData.Points.Data+i;
- float u=p->X,v=p->Y,s=ApplicationData.Time.Map,t=1-ApplicationData.Time.Map;
- applyTransformation(&ApplicationData.Transformations.T1,r1,&p->X,&p->Y);
- applyTransformation(&ApplicationData.Transformations.T2,r2,&u,&v);
- p->X=t*p->X+s*u;
- p->Y=t*p->Y+s*v;
- p->Z=0.2*p->Z+0.8*(t*r1+s*r2);
- p->R=85.*ApplicationData.ColorMap.Alpha*(2+COS(ApplicationData.ColorMap.SpaceFrequency*u1*p->Z+u4));
- p->G=85.*ApplicationData.ColorMap.Alpha*(2+COS(ApplicationData.ColorMap.SpaceFrequency*u2*p->Z+u5));
- p->B=85.*ApplicationData.ColorMap.Alpha*(2+COS(ApplicationData.ColorMap.SpaceFrequency*u3*p->Z+u6));
- }
- }
-
- void evolveProxy(void){
- int i,j,k=0,T[PROXY_SIZE][PROXY_SIZE];
- float U[2]={1,1},u=0;
- float r=(float) (1+ApplicationData.Window.Width*ApplicationData.Window.Height)/(1+ApplicationData.Points.Count);
- for (i=0;i<PROXY_SIZE;i++)
- for (j=0;j<PROXY_SIZE;j++)
- T[i][j]=0;
- i=PROXY_SIZE*PROXY_SIZE*PROXY_QUALITY;
- if (i>=ApplicationData.Points.Count)
- i=ApplicationData.Points.Count-1;
- for (;i>=0;i--)
- T[(int) (PROXY_SIZE*(ApplicationData.Points.Data[i].X+1)*0.4999)][(int) (PROXY_SIZE*(ApplicationData.Points.Data[i].Y+1)*0.4999)]++;
- for (i=0;i<PROXY_SIZE;i++)
- for (j=0;j<PROXY_SIZE;j++)
- if (T[i][j])
- k++;
- ApplicationData.Statistics.Density=(float) k/(PROXY_SIZE*PROXY_SIZE);
- ApplicationData.Points.Size=(2.01-ApplicationData.Display.Sharpness)*sqrt(ApplicationData.Statistics.Density*r);
- if (ApplicationData.Points.Rounded){
- glGetFloatv(GL_POINT_SIZE_RANGE,U);
- if (U[1]>U[0]+0.01){
- ApplicationData.Points.Size*=0.5*PI;
- if (ApplicationData.Points.Size<U[0])
- ApplicationData.Points.Size=U[0];
- if (ApplicationData.Points.Size>U[1])
- ApplicationData.Points.Size=U[1];
- glGetFloatv(GL_POINT_SIZE_GRANULARITY,&u);
- if (u>0)
- ApplicationData.Points.Size=U[0]+roundf((ApplicationData.Points.Size-U[0])/u)*u;
- } else
- ApplicationData.Points.Size=U[0];
- } else
- ApplicationData.Points.Size=roundf(ApplicationData.Points.Size);
- if (ApplicationData.Points.Size<1)
- ApplicationData.Points.Size=1;
- if (ApplicationData.Display.BlendMethod<2){
- ApplicationData.ColorMap.Alpha=ApplicationData.Display.Attenuation*ApplicationData.Display.Luminance*r*ApplicationData.Statistics.Density/pow(ApplicationData.Points.Size,2);
- if (ApplicationData.ColorMap.Alpha>1)
- ApplicationData.ColorMap.Alpha=1;
- if (ApplicationData.Display.MotionBlur>=2)
- ApplicationData.ColorMap.Alpha=sqrt(ApplicationData.ColorMap.Alpha);
- if (ApplicationData.ColorMap.Alpha<MIN_COLOR)
- ApplicationData.ColorMap.Alpha=MIN_COLOR;
- } else
- ApplicationData.ColorMap.Alpha=ApplicationData.Display.Luminance;
- }
-
- void evolveColorMap(void){
- float t=0.001*ApplicationData.ColorMap.TimeFrequency*glutGet(GLUT_ELAPSED_TIME);
- u1=2+cos(+0.12*t);
- u2=2+cos(+0.13*t);
- u3=2+cos(-0.16*t);
- u4=+1.9*(t+cos(+1.0*t));
- u5=+1.4*(t-cos(-1.2*t));
- u6=-1.1*(t+cos(-1.4*t));
- }
-
- void evolveStatistics(void){
- if (ApplicationData.MainMenu->Active){
- int t=glutGet(GLUT_ELAPSED_TIME)/1000;
- sprintf(ApplicationData.Statistics.sFrame,"Frame : 0x%X",ApplicationData.Time.Tick);
- sprintf(ApplicationData.Statistics.sTime,"Time : %.2d:%.2d:%.2d",t/3600,(t/60) % 60,t % 60);
- sprintf(ApplicationData.Statistics.sFPS,"FPS : %.0f",ApplicationData.Time.FPS);
- sprintf(ApplicationData.Statistics.sPointCount,"Points count : %d",ApplicationData.Points.Count);
- sprintf(ApplicationData.Statistics.sDensity,"Surface : %.0f%%",ApplicationData.Statistics.Density*100);
- sprintf(ApplicationData.Statistics.sPointSize,"Point size : %.2f",ApplicationData.Points.Size);
- sprintf(ApplicationData.Statistics.sAlpha,"Alpha : %.1f%%",ApplicationData.ColorMap.Alpha*100);
- sprintf(ApplicationData.Statistics.sCycle,"Cycle : %.0f%%",ApplicationData.Time.Map*100);
- sprintf(ApplicationData.Statistics.sAttractor1,"Attractor #1 : %d/%d",ApplicationData.Transformations.T1.Count,ApplicationData.Transformations.T1.Degree);
- sprintf(ApplicationData.Statistics.sAttractor2,"Attractor #2 : %d/%d",ApplicationData.Transformations.T2.Count,ApplicationData.Transformations.T2.Degree);
- }
- }
-
- void evolve(void){
- evolveWindow();
- evolveAlloc();
- evolveTime();
- evolvePoints();
- evolveProxy();
- evolveColorMap();
- evolveStatistics();
- }
-
- /*********************************************************************
- * GLUT CALLBACKS *
- *********************************************************************/
-
- void displayFunc(void){
- float t=glutGet(GLUT_ELAPSED_TIME);
- glEnable(GL_BLEND);
- glPushAttrib(GL_ALL_ATTRIB_BITS);
- glPointSize(ApplicationData.Points.Size);
- if (ApplicationData.Points.Rounded)
- glEnable(GL_POINT_SMOOTH);
- else
- glDisable(GL_POINT_SMOOTH);
- #ifdef USE_TEXTURE
- switch (ApplicationData.Display.MotionBlur){
- case 0:
- #endif
- glBlendFunc(GL_ZERO,GL_ONE_MINUS_SRC_ALPHA);
- glColor4f(0,0,0,ApplicationData.Display.Attenuation);
- glRectf(-1,-1,1,1);
- #ifdef USE_TEXTURE
- break;
- case 1:
- glBlendFunc(GL_ONE,GL_ZERO);
- glColor3f(1-ApplicationData.Display.Attenuation,1-ApplicationData.Display.Attenuation,1-ApplicationData.Display.Attenuation);
- if (!paintTexture(&ApplicationData.Window.TextureMotion,GL_MODULATE))
- glClear(GL_COLOR_BUFFER_BIT);
- break;
- }
- #endif
- switch(ApplicationData.Display.BlendMethod){
- case 0:
- glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ONE);
- break;
- case 1:
- glBlendFunc(GL_ONE,GL_ONE);
- break;
- case 2:
- glBlendFunc(GL_ONE,GL_ZERO);
- break;
- }
- glInterleavedArrays(GL_C4UB_V2F,sizeof(point),ApplicationData.Points.Data);
- #ifdef USE_TEXTURE
- switch (ApplicationData.Display.MotionBlur){
- int i;
- case 0:
- case 1:
- #endif
- glDrawArrays(GL_POINTS,0,ApplicationData.Points.Count);
- #ifdef USE_TEXTURE
- break;
- # ifdef USE_MULTIPLE_TEXTURES
- default:{
- float f=ApplicationData.Display.BlendMethod<2?ApplicationData.ColorMap.Alpha:ApplicationData.Display.Attenuation/ApplicationData.Display.MotionBlur;///ApplicationData.Display.MotionBlur;
- for (i=0;i<ApplicationData.Display.MotionBlur;i++){
- int a=i*ApplicationData.Points.Count/ApplicationData.Display.MotionBlur,b=(i+1)*ApplicationData.Points.Count/ApplicationData.Display.MotionBlur-a;
- glClear(GL_COLOR_BUFFER_BIT);
- glDrawArrays(GL_POINTS,a,b);
- glPushAttrib(GL_ALL_ATTRIB_BITS);
- copyTexture(&ApplicationData.Window.TextureAccum);
- glBlendFunc(GL_ONE,GL_ZERO);
- if (i){
- glColor3f(1,1,1);
- paintTexture(&ApplicationData.Window.TextureMotion,GL_MODULATE);
- } else {
- glColor3f(1-ApplicationData.Display.Attenuation,1-ApplicationData.Display.Attenuation,1-ApplicationData.Display.Attenuation);
- if (!paintTexture(&ApplicationData.Window.TextureMotion,GL_MODULATE))
- glClear(GL_COLOR_BUFFER_BIT);
- }
- glColor3f(f,f,f);
- glBlendFunc(GL_ONE,GL_ONE);
- paintTexture(&ApplicationData.Window.TextureAccum,GL_MODULATE);
- if (i<ApplicationData.Display.MotionBlur)
- copyTexture(&ApplicationData.Window.TextureMotion);
- glPopAttrib();
- }
- break;
- }
- # endif
- }
- #endif
- glPopAttrib();
- menuDisplay(ApplicationData.MainMenu,ApplicationData.Window.Width,ApplicationData.Window.Height);
- #ifdef USE_TEXTURE
- switch (ApplicationData.Display.MotionBlur){
- case 0:
- break;
- case 1:
- copyTexture(&ApplicationData.Window.TextureMotion);
- break;
- # ifdef USE_MULTIPLE_TEXTURES
- default:
- copyTexture(&ApplicationData.Window.TextureMotion);
- break;
- # endif
- }
- #endif
- glFlush();
- glutSwapBuffers();
- }
-
- void reshapeFunc(int width,int height){
- if (!(ApplicationData.Window.Width=width))
- ApplicationData.Window.Width=1;
- if (!(ApplicationData.Window.Height=height))
- ApplicationData.Window.Height=1;
- glViewport(0,0,width,height);
- }
-
- void idleFunc(void){
- evolve();
- glutPostRedisplay();
- if (ApplicationData.Display.LimitCPUUsage)
- SLEEP(TIME_GRANULARITY);
- }
-
- void keyboardFunc(unsigned char key,int x,int y){
- #ifdef SCREENSAVER
- if (ApplicationData.Window.ScreenSaverMode==SCREENSAVER_MODE_SHOW)
- exit(0);
- #endif
- switch (key){
- case 'd':
- ApplicationData.Window.DesiredDoubleBuffered=!ApplicationData.Window.DesiredDoubleBuffered;
- CheckBoxDoubleBuffered.Data.CheckBox->Checked=ApplicationData.Window.DesiredDoubleBuffered;
- break;
- case 'f':
- ApplicationData.Window.DesiredFullScreen=!ApplicationData.Window.DesiredFullScreen;
- CheckBoxFullScreen.Data.CheckBox->Checked=ApplicationData.Window.DesiredFullScreen;
- break;
- case 'm':
- ApplicationData.Window.DesiredMultiSample=!ApplicationData.Window.DesiredMultiSample;
- CheckBoxMultiSample.Data.CheckBox->Checked=ApplicationData.Window.DesiredMultiSample;
- break;
- case 'q':
- quitExecute();
- break;
- #ifdef SCREENSAVER
- case 'r':
- resetExecute();
- break;
- #endif
- case 's':
- saveExecute();
- break;
- default:
- menuKeyboard(ApplicationData.MainMenu,key);
- }
- }
-
- void specialFunc(int key,int x,int y){
- #ifdef SCREENSAVER
- if (ApplicationData.Window.ScreenSaverMode==SCREENSAVER_MODE_SHOW)
- exit(0);
- #endif
- menuSpecial(ApplicationData.MainMenu,key);
- }
-
- void mouseFunc(int button,int state,int x,int y){
- int i;
- float u=1-2.*x/ApplicationData.Window.Width,v=1-2.*y/ApplicationData.Window.Height;
- #ifdef SCREENSAVER
- if (ApplicationData.Window.ScreenSaverMode==SCREENSAVER_MODE_SHOW)
- exit(0);
- #endif
- for (i=0;i<ApplicationData.Points.Count;i++){
- ApplicationData.Points.Data[i].X=u;
- ApplicationData.Points.Data[i].Y=v;
- }
- };
-
- #ifdef SCREENSAVER
- void passiveMotionFunc(int x,int y){
- if (ApplicationData.Window.ScreenSaverMode==SCREENSAVER_MODE_SHOW){
- if (ApplicationData.Window.MouseX==-1){
- ApplicationData.Window.MouseX=x;
- ApplicationData.Window.MouseY=y;
- } else {
- if (abs(ApplicationData.Window.MouseX-x)+abs(ApplicationData.Window.MouseY-y)>MAX_SCREENSAVER_MOUSE_OFFSET)
- exit(0);
- }
- }
- };
- #endif
-
-
- /*********************************************************************
- * INI FILE *
- *********************************************************************/
-
- void readIniFile(void){
- FILE *f;
- if (f=fopen(INI_FILENAME,"r")){
- menuLoad(ApplicationData.MainMenu,f);
- fclose(f);
- } else
- printf("Cannot read file "INI_FILENAME"\n");
- menuInit(ApplicationData.MainMenu);
- }
-
- void writeIniFile(void){
- FILE *f;
- if (f=fopen(INI_FILENAME,"w")){
- menuSave(ApplicationData.MainMenu,f);
- fclose(f);
- } else
- printf("Cannot write file" INI_FILENAME "\n");
- }
-
- /*********************************************************************
- * MENU CALLBACKS *
- *********************************************************************/
-
- void fullScreenChange(int checked){
- #ifdef SCREENSAVER
- if (ApplicationData.Window.ScreenSaverMode==SCREENSAVER_MODE_SHOW)
- ApplicationData.Window.DesiredFullScreen=1;
- else
- #endif
- ApplicationData.Window.DesiredFullScreen=checked;
- }
-
- void fullScreenParamChange(int index){
- if (ApplicationData.Window.FullScreen)
- ApplicationData.Window.ChangeMode=1;
- }
-
- void doubleBufferedChange(int checked){
- ApplicationData.Window.DesiredDoubleBuffered=checked;
- }
-
- void multiSampleChange(int checked){
- ApplicationData.Window.DesiredMultiSample=checked;
- }
-
- #ifdef USE_TEXTURE
- # ifdef USE_MULTIPLE_TEXTURES
- void motionBlurChange(int index){
- ApplicationData.Display.MotionBlur=index;
- }
- # else
- void motionBlurChange(int checked){
- ApplicationData.Display.MotionBlur=checked;
- }
- # endif
- #endif
-
- void desiredFPSChange(int position){
- ApplicationData.Time.DesiredFPS=position;
- }
-
- void limitCPUUsageChange(int checked){
- ApplicationData.Display.LimitCPUUsage=checked;
- }
-
- void resetExecute(void){
- FILE *f;
- if (f=fopen(INI_FILENAME,"w")){
- fclose(f);
- printf("Settings reset, restart the application\n");
- }
- #ifdef SCREENSAVER
- exit(0);
- #endif
- }
-
- void saveExecute(void){
- writeIniFile();
- #ifdef SCREENSAVER
- exit(0);
- #endif
- }
-
- void quitExecute(void){
- exit(0);
- }
-
- void roundedPointsChange(int checked){
- ApplicationData.Points.Rounded=checked;
- }
-
- void blendMethodChange(int index){
- ApplicationData.Display.BlendMethod=index;
- }
-
- void luminanceChange(float position){
- ApplicationData.Display.Luminance=position*0.01;
- }
-
- void sharpnessChange(float position){
- ApplicationData.Display.Sharpness=position*0.01;
- }
-
- void attenuationChange(float position){
- ApplicationData.Display.Attenuation=position*0.01;
- }
-
- void spaceFrequencyChange(float position){
- ApplicationData.ColorMap.SpaceFrequency=position;
- }
-
- void timeFrequencyChange(float position){
- ApplicationData.ColorMap.TimeFrequency=position;
- }
-
- void periodChange(float position){
- ApplicationData.Time.PeriodLength=1000*position;
- }
-
- void elasticityChange(float position){
- ApplicationData.Time.Elasticity=position;
- }
-
- void minDegreeChange(int position){
- if (position>ApplicationData.Transformations.MaxDegree)
- ITrackBarMinDegree.Data.ITrackBar->Position=ApplicationData.Transformations.MaxDegree;
- else
- ApplicationData.Transformations.MinDegree=position;
- }
-
- void maxDegreeChange(int position){
- if (position<ApplicationData.Transformations.MinDegree)
- ITrackBarMaxDegree.Data.ITrackBar->Position=ApplicationData.Transformations.MaxDegree;
- else
- ApplicationData.Transformations.MaxDegree=position;
- }
-
- /*********************************************************************
- * MAIN PROGRAM *
- *********************************************************************/
-
- #ifdef SCREENSAVER
- int strcmpleft(char *s,char *t){
- while (*s && *s==*t){
- s++;
- t++;
- }
- return !*s;
- }
-
- int findstr(char *s,char *T[]){
- char *t;
- while (t=*(T++))
- if (strcmpleft(t,s))
- return 1;
- return 0;
- }
-
- int screenSaverMode(int argc,char *argv[]){
- char *sConfigureFlags[7]={"-C","/C","C","-c","/c","c",NULL},*sPreviewFlags[7]={"-P","/P","P","-p","/p","p",NULL};
- int i;
- for (i=1;i<argc;i++){
- if (findstr(argv[i],sConfigureFlags))
- return SCREENSAVER_MODE_CONFIGURE;
- if (findstr(argv[i],sPreviewFlags))
- return SCREENSAVER_MODE_PREVIEW;
- }
- return SCREENSAVER_MODE_SHOW;
- }
- #endif
-
- int main(int argc,char *argv[]){
- #ifdef SCREENSAVER
- switch(ApplicationData.Window.ScreenSaverMode=screenSaverMode(argc,argv)){
- case SCREENSAVER_MODE_CONFIGURE:
- MainMenu.Active=1;
- break;
- case SCREENSAVER_MODE_PREVIEW:
- return 0;
- }
- #endif
- srand(time(NULL));
- #ifdef USE_COS_TABLE
- initCos();
- #endif
- ApplicationData.MainMenu=&MainMenu;
- readIniFile();
- allocTransformation(&ApplicationData.Transformations.T1);
- allocTransformation(&ApplicationData.Transformations.T2);
- glutInit(&argc,argv);
- createWindow();
- printf("Entering main loop, press [Escape] for menu, use arrows to navigate.\n");
- glutMainLoop();
- return 0;
- }
#define USE_COS_TABLE
#define USE_TEXTURE
#define USE_MULTIPLE_TEXTURES
//#define SCREENSAVER
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include "glut_import.h"
#include "menu.h"
/*********************************************************************
* CONSTANTS *
*********************************************************************/
#define FPS_COUNTER_TRIGGER 15
#define FPS_COUNTER_SMOOTH 0.3
#define PROXY_SIZE 32
#define PROXY_QUALITY 5
#define MIN_COLOR (10./256.)
#define MIN_POINT_COUNT 300
#define INI_FILENAME "AFC.ini"
#ifdef USE_MULTIPLE_TEXTURES
# ifndef USE_TEXTURE
# error You cannot specify USE_MULTIPLE_TEXTURES without specifying USE_TEXTURE
# endif
# define INVALID_TEXTURE_INDEX 0xFFFFFFFF
#endif
/*********************************************************************
* PLATFORM *
*********************************************************************/
#ifdef __WIN32__
# ifdef SCREENSAVER
# define SCREENSAVER_MODE_SHOW 0x1
# define SCREENSAVER_MODE_CONFIGURE 0x2
# define SCREENSAVER_MODE_PREVIEW 0x4
# define MAX_SCREENSAVER_MOUSE_OFFSET 10
# endif
# include <windows.h>
# define SLEEP(_DELAY) Sleep(_DELAY)
# define TIME_GRANULARITY 12
#else
# ifdef SCREENSAVER
# error Usage of SCREENSAVER reserved for Windows
# endif
# include <unistd.h>
# define SLEEP(_DELAY) usleep(1000*_DELAY)
# define TIME_GRANULARITY 6
#endif
/*********************************************************************
* COSINE TABLE SUPPORT *
*********************************************************************/
#ifdef USE_COS_TABLE
# define COS_TABLE_QUALITY 0x1000
float CosTable[COS_TABLE_QUALITY];
void initCos(void){
int i;
for (i=0;i<COS_TABLE_QUALITY;i++)
CosTable[i]=cos(PI*i/COS_TABLE_QUALITY);
}
float cosTable(float x){
int n;
if (x<0)
x=-x;
n=((int) roundf(COS_TABLE_QUALITY*x/PI)) % (2*COS_TABLE_QUALITY);
if (n<COS_TABLE_QUALITY)
return CosTable[n];
else
return CosTable[2*COS_TABLE_QUALITY-1-n];
}
# define COS(_X) cosTable((_X))
# define SIN(_X) cosTable((_X)-0.5*PI)
#else
# define COS(_X) cos((_X))
# define SIN(_X) sin((_X))
#endif
/*********************************************************************
* MACROS *
*********************************************************************/
#define ASSERT(_X,_S) if (!(_X)) {printf("%s\n",_S);exit(-1);}
#define MEMCHECK(_X) if (!(_X)) {printf("Memory allocation failed\n");exit(-1);}
/*********************************************************************
* TYPES *
*********************************************************************/
typedef struct{
int Count,Degree;
float *Matrix;
} transformation;
#ifdef USE_TEXTURE
typedef struct{
# ifdef USE_MULTIPLE_TEXTURES
unsigned int Index;
# endif
int ImageWidth,ImageHeight,Width,Height;
} texture;
#endif
#pragma pack(push,1)
#pragma pack(1)
typedef struct{
unsigned char R,G,B,A;
float X,Y,Z;
} point;
#pragma pack(pop)
/*********************************************************************
* APPLICATION DATA *
*********************************************************************/
struct {
struct {
int Index,Width,Height,FullScreen,DesiredFullScreen,DoubleBuffered,DesiredDoubleBuffered,MultiSample,DesiredMultiSample,ChangeMode;
#ifdef SCREENSAVER
int ScreenSaverMode,MouseX,MouseY;
#endif
#ifdef USE_TEXTURE
texture TextureMotion;
# ifdef USE_MULTIPLE_TEXTURES
texture TextureAccum;
# endif
#endif
} Window;
struct {
int Tick,PeriodStart,PeriodLength,TickTime;
float Elasticity,Map,FPS,DesiredFPS;
} Time;
struct {
transformation T1,T2;
int MinDegree,MaxDegree;
} Transformations;
struct {
int Count,DesiredCount,Rounded;
float Size;
point *Data;
} Points;
struct {
float Alpha,SpaceFrequency,TimeFrequency;
} ColorMap;
struct {
int BlendMethod,LimitCPUUsage,MotionBlur,Accumulation;
float Luminance,Sharpness,Attenuation;
} Display;
struct {
float Density;
char sFrame[64],sTime[64],sFPS[64],sPointCount[64],sDensity[64],sPointSize[64],sAlpha[64],sCycle[64],sAttractor1[64],sAttractor2[64];
} Statistics;
menu *MainMenu;
} ApplicationData={
{-1,1,1,0,0,1,1,0,0,0
#ifdef SCREENSAVER
,0,-1,-1
#endif
#ifdef USE_TEXTURE
# ifdef USE_MULTIPLE_TEXTURES
,{INVALID_TEXTURE_INDEX,0,0,0,0},{INVALID_TEXTURE_INDEX,0,0,0,0}
# else
,{0,0,0,0}
# endif
#endif
},
{0,0,5000,0,5,0,50,40},
{{0,0,NULL},{0,0,NULL},0,20},
{0,2*MIN_POINT_COUNT,1,1,NULL},
{0,1,1},
{0,0,0,0,1,1,0.1},
{0,"","","","","","","","","",""}
};
/*********************************************************************
* FUNCTIONS *
*********************************************************************/
void evolveWindow(void);
void evolveAlloc(void);
void evolveTime(void);
void evolvePoints(void);
void evolveProxy(void);
void evolveColorMap(void);
void evolve(void);
void displayFunc(void);
void reshapeFunc(int,int);
void idleFunc(void);
void keyboardFunc(unsigned char,int,int);
void specialFunc(int,int,int);
void mouseFunc(int,int,int,int);
#ifdef SCREENSAVER
void passiveMotionFunc(int,int);
#endif
void readIniFile(void);
void writeIniFile(void);
void fullScreenChange(int);
void fullScreenParamChange(int);
void doubleBufferedChange(int);
void multiSampleChange(int);
#ifdef USE_TEXTURE
void motionBlurChange(int);
#endif
void desiredFPSChange(int);
void limitCPUUsageChange(int);
void resetExecute(void);
void saveExecute(void);
void quitExecute(void);
void roundedPointsChange(int);
void blendMethodChange(int);
void luminanceChange(float);
void sharpnessChange(float);
void attenuationChange(float);
void spaceFrequencyChange(float);
void timeFrequencyChange(float);
void periodChange(float);
void elasticityChange(float);
void minDegreeChange(int);
void maxDegreeChange(int);
/*********************************************************************
* MENU DESIGN *
*********************************************************************/
SEPARATOR(Separator);
CHECKBOX(CheckBoxFullScreen,"Fullscreen (F)",0,fullScreenChange);
static char *ListBoxResolution_Items[6]={"default","320x240","640x480","800x600","1024x768","1280x1024"};
LISTBOX(ListBoxResolution,"Fullscreen resolution :",0,ListBoxResolution_Items,fullScreenParamChange);
static char *ListBoxBPP_Items[4]={"default","16","24","32"};
LISTBOX(ListBoxBPP,"Fullscreen color depth (BPP) :",0,ListBoxBPP_Items,fullScreenParamChange);
static char *ListBoxFrequency_Items[11]={"default","50","60","65","70","72","75","80","85","90","100"};
LISTBOX(ListBoxFrequency,"Fullscreen refresh rate (Hz) :",0,ListBoxFrequency_Items,fullScreenParamChange);
CHECKBOX(CheckBoxDoubleBuffered,"Double buffered (D)",1,doubleBufferedChange);
CHECKBOX(CheckBoxMultiSample,"Multi sample (M)",0,multiSampleChange);
#ifdef USE_TEXTURE
# ifdef USE_MULTIPLE_TEXTURES
static char *ListBoxMotionBlur_Items[7]={"Single buffer","Double buffer","Triple buffer (2x filter)",
"Triple buffer (3x filter)","Triple buffer (4x filter)","Triple buffer (5x filter)",
"Triple buffer (6x filter)"};
LISTBOX(ListBoxMotionBlur,"Motion blur",1,ListBoxMotionBlur_Items,motionBlurChange);
# else
CHECKBOX(CheckBoxMotionBlur,"High quality motion blur",1,motionBlurChange);
# endif
#endif
ITRACKBAR(FTrackBarDesiredFPS,"Requested frame rate: %d",5,120,40,1,desiredFPSChange);
CHECKBOX(CheckBoxLimitCPUUsage,"Limit CPU usage",0,limitCPUUsageChange);
#ifdef SCREENSAVER
STATICTEXT(StaticTextReset,"Reset settings (R)",1,resetExecute);
STATICTEXT(StaticTextSave,"Save settings and exit (S)",1,saveExecute);
STATICTEXT(StaticTextQuit,"Cancel (Q)",1,quitExecute);
# ifdef USE_TEXTURE
static menuitem *MenuPageAFC_Items[14]={
# else
static menuitem *MenuPageAFC_Items[13]={
# endif
#else
STATICTEXT(StaticTextSave,"Save settings (S)",1,saveExecute);
STATICTEXT(StaticTextReset,"Reset settings",1,resetExecute);
STATICTEXT(StaticTextQuit,"Quit (Q)",1,quitExecute);
# ifdef USE_TEXTURE
static menuitem *MenuPageAFC_Items[15]={
# else
static menuitem *MenuPageAFC_Items[14]={
# endif
#endif
&CheckBoxFullScreen,
&ListBoxResolution,
&ListBoxBPP,
&ListBoxFrequency,
&Separator,
&CheckBoxDoubleBuffered,
&CheckBoxMultiSample,
#ifdef USE_TEXTURE
# ifdef USE_MULTIPLE_TEXTURES
&ListBoxMotionBlur,
# else
&CheckBoxMotionBlur,
# endif
#endif
&FTrackBarDesiredFPS,
&CheckBoxLimitCPUUsage,
&Separator,
#ifdef SCREENSAVER
&StaticTextReset,
&StaticTextSave,
&StaticTextQuit
#else
&StaticTextSave,
&StaticTextReset,
&Separator,
&StaticTextQuit
#endif
};
MENUPAGE(MenuPageAFC,"AFC Version 1.0",MenuPageAFC_Items);
CHECKBOX(CheckBoxRoundedPoints,"Rounded points",1,roundedPointsChange);
static char *ListBoxBlendMethod_Items[3]={"Logarithmic","Linear","Maximum"};
LISTBOX(ListBoxBlendMethod,"Blend color method :",0,ListBoxBlendMethod_Items,blendMethodChange);
FTRACKBAR(FTrackBarLuminance,"Luminance : %.0f%%",0,200,100,1,luminanceChange);
FTRACKBAR(FTrackBarSharpness,"Sharpness : %.0f%%",0,200,100,1,sharpnessChange);
FTRACKBAR(FTrackBarAttenuation,"Attenuation : %.1f%%",0.1,100,10,0.1,attenuationChange);
FTRACKBAR(FTrackBarSpaceFrequency,"Colormap space frequency : %.2f",0,50,1,0.02,spaceFrequencyChange);
FTRACKBAR(FTrackBarTimeFrequency,"Colormap time frequency : %.2f",0,20,1,0.02,timeFrequencyChange);
static menuitem *MenuPageDisplay_Items[9]={
&CheckBoxRoundedPoints,
&ListBoxBlendMethod,
&Separator,
&FTrackBarLuminance,
&FTrackBarSharpness,
&FTrackBarAttenuation,
&Separator,
&FTrackBarSpaceFrequency,
&FTrackBarTimeFrequency
};
MENUPAGE(MenuPageDisplay,"DISPLAY",MenuPageDisplay_Items);
FTRACKBAR(FTrackBarPeriod,"Cycle length : %.1f sec",0.5,20,5,0.1,periodChange);
FTRACKBAR(FTrackBarElasticity,"Cycle elasticity : %.1f",0.1,30,5,0.1,elasticityChange);
ITRACKBAR(ITrackBarMinDegree,"Min attractor degree : %d",3,15,6,1,minDegreeChange);
ITRACKBAR(ITrackBarMaxDegree,"Max attractor degree : %d",3,15,6,1,maxDegreeChange);
static menuitem *MenuPageAttractor_Items[4]={&FTrackBarPeriod,&FTrackBarElasticity,&ITrackBarMinDegree,&ITrackBarMaxDegree};
MENUPAGE(MenuPageAttractor,"ATTRACTOR",MenuPageAttractor_Items);
STATICTEXT(StaticTextFrame,ApplicationData.Statistics.sFrame,0,NULL);
STATICTEXT(StaticTextTime,ApplicationData.Statistics.sTime,0,NULL);
STATICTEXT(StaticTextFPS,ApplicationData.Statistics.sFPS,0,NULL);
STATICTEXT(StaticTextPointCount,ApplicationData.Statistics.sPointCount,0,NULL);
STATICTEXT(StaticTextDensity,ApplicationData.Statistics.sDensity,0,NULL);
STATICTEXT(StaticTextPointSize,ApplicationData.Statistics.sPointSize,0,NULL);
STATICTEXT(StaticTextAlpha,ApplicationData.Statistics.sAlpha,0,NULL);
STATICTEXT(StaticTextCycle,ApplicationData.Statistics.sCycle,0,NULL);
STATICTEXT(StaticTextAttractor1,ApplicationData.Statistics.sAttractor1,0,NULL);
STATICTEXT(StaticTextAttractor2,ApplicationData.Statistics.sAttractor2,0,NULL);
static menuitem *MenuPageStatistics_Items[12]={
&StaticTextFrame,
&StaticTextTime,
&StaticTextFPS,
&Separator,
&StaticTextPointCount,
&StaticTextDensity,
&StaticTextPointSize,
&StaticTextAlpha,
&Separator,
&StaticTextCycle,
&StaticTextAttractor1,
&StaticTextAttractor2
};
MENUPAGE(MenuPageStatistics," STATISTICS ",MenuPageStatistics_Items);
static menupage *MainMenu_Pages[4]={&MenuPageAFC,&MenuPageDisplay,&MenuPageAttractor,&MenuPageStatistics};
MENU(MainMenu,MainMenu_Pages);
/*********************************************************************
* UTILITIES *
*********************************************************************/
int pgcd(int x,int y){
if (y)
return pgcd(y,x%y);
else
return x;
}
int ppcm(int x,int y){
return (x*y)/pgcd(x,y);
}
int nextPowerOfTwo(int x){
int u=1;
while (u<x)
u*=2;//<<=1;
return u;
}
float mapExp(float x,float t){
if (x<0.5)
return 0.5*pow(2*x,t);
else
return 1-0.5*pow(2-2*x,t);
}
/*********************************************************************
* TEXTURE UTILITIES *
*********************************************************************/
#ifdef USE_TEXTURE
void copyTexture(texture *T){
# ifdef USE_MULTIPLE_TEXTURES
if (T->Index==INVALID_TEXTURE_INDEX)
glGenTextures(1,&T->Index);
glBindTexture(GL_TEXTURE_2D,T->Index);
# endif
if (ApplicationData.Window.Width!=T->ImageWidth || ApplicationData.Window.Height!=T->ImageHeight){
T->ImageWidth=ApplicationData.Window.Width;
T->ImageHeight=ApplicationData.Window.Height;
T->Width=nextPowerOfTwo(T->ImageWidth);
T->Height=nextPowerOfTwo(T->ImageHeight);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,T->Width,T->Height,0,GL_RGB,GL_UNSIGNED_BYTE,NULL);
}
glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,T->ImageWidth,T->ImageHeight);
}
int paintTexture(texture *T,int Mode){
# ifdef USE_MULTIPLE_TEXTURES
if (T->Index!=INVALID_TEXTURE_INDEX && T->Width && T->Height){
# else
if (T->Width && T->Height){
# endif
float u=(float) T->ImageWidth/T->Width,v=(float) T->ImageHeight/T->Height;
glPushAttrib(GL_ALL_ATTRIB_BITS);
glPushMatrix();
# ifdef USE_MULTIPLE_TEXTURES
glBindTexture(GL_TEXTURE_2D,T->Index);
# endif
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f(0,0);
glVertex2f(-1,-1);
glTexCoord2f(0,v);
glVertex2f(-1,1);
glTexCoord2f(u,v);
glVertex2f(1,1);
glTexCoord2f(u,0);
glVertex2f(1,-1);
glEnd();
glDisable(GL_TEXTURE_2D);
glPopMatrix();
glPopAttrib();
return 1;
}
return 0;
}
void deleteTexture(texture *T){
# ifdef USE_MULTIPLE_TEXTURES
if (T->Index!=INVALID_TEXTURE_INDEX){
glDeleteTextures(1,&T->Index);
T->Index=INVALID_TEXTURE_INDEX;
# endif
T->Width=0;
T->Height=0;
T->ImageWidth=0;
T->ImageHeight=0;
# ifdef USE_MULTIPLE_TEXTURES
}
# endif
}
#endif
/*********************************************************************
* AFFINE TRANSFORMATIONS *
*********************************************************************/
void allocTransformation(transformation *t){
int i,*T;
if (ApplicationData.Transformations.MaxDegree==ApplicationData.Transformations.MinDegree)
t->Degree=ApplicationData.Transformations.MinDegree;
else
t->Degree=ApplicationData.Transformations.MinDegree+(rand() % (1+ApplicationData.Transformations.MaxDegree-ApplicationData.Transformations.MinDegree));
t->Count=t->Degree-(rand() % (t->Degree/2));
if (t->Count==t->Degree)
t->Count--;
MEMCHECK(T=(int *) calloc(t->Degree,sizeof(int)));
MEMCHECK(t->Matrix=(float *) malloc(6*t->Count*sizeof(float)));
for (i=0;i<t->Count;i++){
float o=2*PI*(rand() % t->Degree)/t->Degree,u=(rand() % 2)-0.5,v=-0.5;
int k=-1,j=1+(rand() % (t->Degree-i));
t->Matrix[6*i]=u*cos(o);
t->Matrix[6*i+1]=-v*sin(o);
t->Matrix[6*i+3]=u*sin(o);
t->Matrix[6*i+4]=v*cos(o);
while (j){
k++;
if (!T[k])
j--;
}
T[k]=1;
o=PI*(1.+2*k)/t->Degree;
t->Matrix[6*i+2]=0.5*cos(o);
t->Matrix[6*i+5]=0.5*sin(o);
}
free(T);
}
void freeTransformation(transformation *t){
free(t->Matrix);
t->Count=0;
}
void applyTransformation(transformation *t,int r,float *x,float *y){
float u=t->Matrix[6*r]*(*x)+t->Matrix[6*r+1]*(*y)+t->Matrix[6*r+2];
*y=t->Matrix[6*r+3]*(*x)+t->Matrix[6*r+4]*(*y)+t->Matrix[6*r+5];
*x=u;
}
/*********************************************************************
* WINDOW *
*********************************************************************/
void createWindow(void){
if (ApplicationData.Window.Index==-1){
int m=GLUT_RGBA;
char s[64]="";
if (ApplicationData.Window.DesiredDoubleBuffered)
m|=GLUT_DOUBLE;
ApplicationData.Window.DoubleBuffered=ApplicationData.Window.DesiredDoubleBuffered;
if (ApplicationData.Window.DesiredMultiSample)
m|=GLUT_MULTISAMPLE;
ApplicationData.Window.MultiSample=ApplicationData.Window.DesiredMultiSample;
glutInitDisplayMode(m);
if (ApplicationData.Window.DesiredFullScreen){
if (ListBoxResolution.Data.ListBox->ItemIndex)
strcat(s,ListBoxResolution.Data.ListBox->Items[ListBoxResolution.Data.ListBox->ItemIndex]);
if (ListBoxBPP.Data.ListBox->ItemIndex){
strcat(s,":");
strcat(s,ListBoxBPP.Data.ListBox->Items[ListBoxBPP.Data.ListBox->ItemIndex]);
}
if (ListBoxFrequency.Data.ListBox->ItemIndex){
strcat(s,"@");
strcat(s,ListBoxFrequency.Data.ListBox->Items[ListBoxFrequency.Data.ListBox->ItemIndex]);
}
if (*s){
glutGameModeString(s);
if (!glutGameModeGet(GLUT_GAME_MODE_POSSIBLE)){
printf("Unsupported display mode (%s). Fullscreen has been canceled.\n",s);
ApplicationData.Window.DesiredFullScreen=0;
}
}
}
CheckBoxFullScreen.Data.CheckBox->Checked=ApplicationData.Window.DesiredFullScreen;
if (ApplicationData.Window.DesiredFullScreen)
ApplicationData.Window.Index=glutEnterGameMode();
else {
glutInitWindowSize(640,480);
glutInitWindowPosition((glutGet(GLUT_SCREEN_WIDTH)-640)/2,(glutGet(GLUT_SCREEN_HEIGHT)-480)/2);
ApplicationData.Window.Index=glutCreateWindow("AFC");
}
ApplicationData.Window.FullScreen=ApplicationData.Window.DesiredFullScreen;
ApplicationData.Window.ChangeMode=0;
#ifdef USE_TEXTURE
deleteTexture(&ApplicationData.Window.TextureMotion);
# ifdef USE_MULTIPLE_TEXTURES
deleteTexture(&ApplicationData.Window.TextureAccum);
# endif
#endif
#ifdef SCREENSAVER
if (ApplicationData.Window.ScreenSaverMode==SCREENSAVER_MODE_SHOW)
glutSetCursor(GLUT_CURSOR_NONE);
else
#endif
glutSetCursor(GLUT_CURSOR_CROSSHAIR);
glutDisplayFunc(displayFunc);
glutReshapeFunc(reshapeFunc);
glutIdleFunc(idleFunc);
glutKeyboardFunc(keyboardFunc);
glutSpecialFunc(specialFunc);
glutMouseFunc(mouseFunc);
#ifdef SCREENSAVER
glutPassiveMotionFunc(passiveMotionFunc);
#endif
}
}
void destroyWindow(void){
if (ApplicationData.Window.Index!=-1){
if (ApplicationData.Window.FullScreen)
glutLeaveGameMode();
else
glutDestroyWindow(ApplicationData.Window.Index);
}
ApplicationData.Window.Index=-1;
}
/*********************************************************************
* ANIMATION CORE *
*********************************************************************/
float u1,u2,u3,u4,u5,u6;
void evolveWindow(void){
if (ApplicationData.Window.MultiSample^ApplicationData.Window.DesiredMultiSample ||
ApplicationData.Window.DoubleBuffered^ApplicationData.Window.DesiredDoubleBuffered ||
ApplicationData.Window.FullScreen^ApplicationData.Window.DesiredFullScreen ||
ApplicationData.Window.ChangeMode) {
destroyWindow();
createWindow();
}
}
void evolveAlloc(void){
if (ApplicationData.Points.Count!=ApplicationData.Points.DesiredCount){
int i;
MEMCHECK(ApplicationData.Points.Data=(point *) realloc(ApplicationData.Points.Data,ApplicationData.Points.DesiredCount*sizeof(point)));
if (!ApplicationData.Points.Count){
float o=2*PI*rand()/RAND_MAX,r=(float) rand()/RAND_MAX;
ApplicationData.Points.Data[0].X=r*cos(o);
ApplicationData.Points.Data[0].Y=r*sin(o);
ApplicationData.Points.Data[0].Z=0;
ApplicationData.Points.Data[0].A=255;
}
for (i=ApplicationData.Points.Count;i<ApplicationData.Points.DesiredCount;i++)
ApplicationData.Points.Data[i]=ApplicationData.Points.Data[0];
ApplicationData.Points.Count=ApplicationData.Points.DesiredCount;
}
}
void evolveTime(void){
int t=glutGet(GLUT_ELAPSED_TIME),u=(t-ApplicationData.Time.PeriodStart)/ApplicationData.Time.PeriodLength;
while (u--){
freeTransformation(&ApplicationData.Transformations.T1);
ApplicationData.Transformations.T1=ApplicationData.Transformations.T2;
allocTransformation(&ApplicationData.Transformations.T2);
ApplicationData.Time.PeriodStart+=ApplicationData.Time.PeriodLength;
}
ApplicationData.Time.Map=mapExp((float) (t-ApplicationData.Time.PeriodStart)/ApplicationData.Time.PeriodLength,ApplicationData.Time.Elasticity);
if ((++ApplicationData.Time.Tick & FPS_COUNTER_TRIGGER)==FPS_COUNTER_TRIGGER){
char s[64];
float r;
ApplicationData.Time.FPS=(1-FPS_COUNTER_SMOOTH)*1000*(1+FPS_COUNTER_TRIGGER)/(t+1-ApplicationData.Time.TickTime)+FPS_COUNTER_SMOOTH*ApplicationData.Time.FPS;
ApplicationData.Time.TickTime=t;
r=ApplicationData.Time.FPS/ApplicationData.Time.DesiredFPS;
if (r>1.05)
ApplicationData.Points.DesiredCount+=ApplicationData.Points.DesiredCount*(1-1/r);
if (r<0.95)
ApplicationData.Points.DesiredCount-=ApplicationData.Points.DesiredCount*(1-r);
if (ApplicationData.Points.DesiredCount<MIN_POINT_COUNT){
ApplicationData.Points.DesiredCount=MIN_POINT_COUNT;
printf("Your system is TOO SLOW to run this program at the requested frame rate. Please lower it to improve image quality (its value MUST be less than the screen refresh rate if you are using double buffered mode, since the display cannot go faster than the screen in this case).\n");
}
sprintf(s,"AFC (%.0f FPS , %d points)\0",ApplicationData.Time.FPS,ApplicationData.Points.Count);
glutSetWindowTitle(s);
}
}
void evolvePoints(void){
int i;
for (i=0;i<ApplicationData.Points.Count;i++){
int r=rand(),r1=r % ApplicationData.Transformations.T1.Count,r2=r % ApplicationData.Transformations.T2.Count;
point *p=ApplicationData.Points.Data+i;
float u=p->X,v=p->Y,s=ApplicationData.Time.Map,t=1-ApplicationData.Time.Map;
applyTransformation(&ApplicationData.Transformations.T1,r1,&p->X,&p->Y);
applyTransformation(&ApplicationData.Transformations.T2,r2,&u,&v);
p->X=t*p->X+s*u;
p->Y=t*p->Y+s*v;
p->Z=0.2*p->Z+0.8*(t*r1+s*r2);
p->R=85.*ApplicationData.ColorMap.Alpha*(2+COS(ApplicationData.ColorMap.SpaceFrequency*u1*p->Z+u4));
p->G=85.*ApplicationData.ColorMap.Alpha*(2+COS(ApplicationData.ColorMap.SpaceFrequency*u2*p->Z+u5));
p->B=85.*ApplicationData.ColorMap.Alpha*(2+COS(ApplicationData.ColorMap.SpaceFrequency*u3*p->Z+u6));
}
}
void evolveProxy(void){
int i,j,k=0,T[PROXY_SIZE][PROXY_SIZE];
float U[2]={1,1},u=0;
float r=(float) (1+ApplicationData.Window.Width*ApplicationData.Window.Height)/(1+ApplicationData.Points.Count);
for (i=0;i<PROXY_SIZE;i++)
for (j=0;j<PROXY_SIZE;j++)
T[i][j]=0;
i=PROXY_SIZE*PROXY_SIZE*PROXY_QUALITY;
if (i>=ApplicationData.Points.Count)
i=ApplicationData.Points.Count-1;
for (;i>=0;i--)
T[(int) (PROXY_SIZE*(ApplicationData.Points.Data[i].X+1)*0.4999)][(int) (PROXY_SIZE*(ApplicationData.Points.Data[i].Y+1)*0.4999)]++;
for (i=0;i<PROXY_SIZE;i++)
for (j=0;j<PROXY_SIZE;j++)
if (T[i][j])
k++;
ApplicationData.Statistics.Density=(float) k/(PROXY_SIZE*PROXY_SIZE);
ApplicationData.Points.Size=(2.01-ApplicationData.Display.Sharpness)*sqrt(ApplicationData.Statistics.Density*r);
if (ApplicationData.Points.Rounded){
glGetFloatv(GL_POINT_SIZE_RANGE,U);
if (U[1]>U[0]+0.01){
ApplicationData.Points.Size*=0.5*PI;
if (ApplicationData.Points.Size<U[0])
ApplicationData.Points.Size=U[0];
if (ApplicationData.Points.Size>U[1])
ApplicationData.Points.Size=U[1];
glGetFloatv(GL_POINT_SIZE_GRANULARITY,&u);
if (u>0)
ApplicationData.Points.Size=U[0]+roundf((ApplicationData.Points.Size-U[0])/u)*u;
} else
ApplicationData.Points.Size=U[0];
} else
ApplicationData.Points.Size=roundf(ApplicationData.Points.Size);
if (ApplicationData.Points.Size<1)
ApplicationData.Points.Size=1;
if (ApplicationData.Display.BlendMethod<2){
ApplicationData.ColorMap.Alpha=ApplicationData.Display.Attenuation*ApplicationData.Display.Luminance*r*ApplicationData.Statistics.Density/pow(ApplicationData.Points.Size,2);
if (ApplicationData.ColorMap.Alpha>1)
ApplicationData.ColorMap.Alpha=1;
if (ApplicationData.Display.MotionBlur>=2)
ApplicationData.ColorMap.Alpha=sqrt(ApplicationData.ColorMap.Alpha);
if (ApplicationData.ColorMap.Alpha<MIN_COLOR)
ApplicationData.ColorMap.Alpha=MIN_COLOR;
} else
ApplicationData.ColorMap.Alpha=ApplicationData.Display.Luminance;
}
void evolveColorMap(void){
float t=0.001*ApplicationData.ColorMap.TimeFrequency*glutGet(GLUT_ELAPSED_TIME);
u1=2+cos(+0.12*t);
u2=2+cos(+0.13*t);
u3=2+cos(-0.16*t);
u4=+1.9*(t+cos(+1.0*t));
u5=+1.4*(t-cos(-1.2*t));
u6=-1.1*(t+cos(-1.4*t));
}
void evolveStatistics(void){
if (ApplicationData.MainMenu->Active){
int t=glutGet(GLUT_ELAPSED_TIME)/1000;
sprintf(ApplicationData.Statistics.sFrame,"Frame : 0x%X",ApplicationData.Time.Tick);
sprintf(ApplicationData.Statistics.sTime,"Time : %.2d:%.2d:%.2d",t/3600,(t/60) % 60,t % 60);
sprintf(ApplicationData.Statistics.sFPS,"FPS : %.0f",ApplicationData.Time.FPS);
sprintf(ApplicationData.Statistics.sPointCount,"Points count : %d",ApplicationData.Points.Count);
sprintf(ApplicationData.Statistics.sDensity,"Surface : %.0f%%",ApplicationData.Statistics.Density*100);
sprintf(ApplicationData.Statistics.sPointSize,"Point size : %.2f",ApplicationData.Points.Size);
sprintf(ApplicationData.Statistics.sAlpha,"Alpha : %.1f%%",ApplicationData.ColorMap.Alpha*100);
sprintf(ApplicationData.Statistics.sCycle,"Cycle : %.0f%%",ApplicationData.Time.Map*100);
sprintf(ApplicationData.Statistics.sAttractor1,"Attractor #1 : %d/%d",ApplicationData.Transformations.T1.Count,ApplicationData.Transformations.T1.Degree);
sprintf(ApplicationData.Statistics.sAttractor2,"Attractor #2 : %d/%d",ApplicationData.Transformations.T2.Count,ApplicationData.Transformations.T2.Degree);
}
}
void evolve(void){
evolveWindow();
evolveAlloc();
evolveTime();
evolvePoints();
evolveProxy();
evolveColorMap();
evolveStatistics();
}
/*********************************************************************
* GLUT CALLBACKS *
*********************************************************************/
void displayFunc(void){
float t=glutGet(GLUT_ELAPSED_TIME);
glEnable(GL_BLEND);
glPushAttrib(GL_ALL_ATTRIB_BITS);
glPointSize(ApplicationData.Points.Size);
if (ApplicationData.Points.Rounded)
glEnable(GL_POINT_SMOOTH);
else
glDisable(GL_POINT_SMOOTH);
#ifdef USE_TEXTURE
switch (ApplicationData.Display.MotionBlur){
case 0:
#endif
glBlendFunc(GL_ZERO,GL_ONE_MINUS_SRC_ALPHA);
glColor4f(0,0,0,ApplicationData.Display.Attenuation);
glRectf(-1,-1,1,1);
#ifdef USE_TEXTURE
break;
case 1:
glBlendFunc(GL_ONE,GL_ZERO);
glColor3f(1-ApplicationData.Display.Attenuation,1-ApplicationData.Display.Attenuation,1-ApplicationData.Display.Attenuation);
if (!paintTexture(&ApplicationData.Window.TextureMotion,GL_MODULATE))
glClear(GL_COLOR_BUFFER_BIT);
break;
}
#endif
switch(ApplicationData.Display.BlendMethod){
case 0:
glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ONE);
break;
case 1:
glBlendFunc(GL_ONE,GL_ONE);
break;
case 2:
glBlendFunc(GL_ONE,GL_ZERO);
break;
}
glInterleavedArrays(GL_C4UB_V2F,sizeof(point),ApplicationData.Points.Data);
#ifdef USE_TEXTURE
switch (ApplicationData.Display.MotionBlur){
int i;
case 0:
case 1:
#endif
glDrawArrays(GL_POINTS,0,ApplicationData.Points.Count);
#ifdef USE_TEXTURE
break;
# ifdef USE_MULTIPLE_TEXTURES
default:{
float f=ApplicationData.Display.BlendMethod<2?ApplicationData.ColorMap.Alpha:ApplicationData.Display.Attenuation/ApplicationData.Display.MotionBlur;///ApplicationData.Display.MotionBlur;
for (i=0;i<ApplicationData.Display.MotionBlur;i++){
int a=i*ApplicationData.Points.Count/ApplicationData.Display.MotionBlur,b=(i+1)*ApplicationData.Points.Count/ApplicationData.Display.MotionBlur-a;
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_POINTS,a,b);
glPushAttrib(GL_ALL_ATTRIB_BITS);
copyTexture(&ApplicationData.Window.TextureAccum);
glBlendFunc(GL_ONE,GL_ZERO);
if (i){
glColor3f(1,1,1);
paintTexture(&ApplicationData.Window.TextureMotion,GL_MODULATE);
} else {
glColor3f(1-ApplicationData.Display.Attenuation,1-ApplicationData.Display.Attenuation,1-ApplicationData.Display.Attenuation);
if (!paintTexture(&ApplicationData.Window.TextureMotion,GL_MODULATE))
glClear(GL_COLOR_BUFFER_BIT);
}
glColor3f(f,f,f);
glBlendFunc(GL_ONE,GL_ONE);
paintTexture(&ApplicationData.Window.TextureAccum,GL_MODULATE);
if (i<ApplicationData.Display.MotionBlur)
copyTexture(&ApplicationData.Window.TextureMotion);
glPopAttrib();
}
break;
}
# endif
}
#endif
glPopAttrib();
menuDisplay(ApplicationData.MainMenu,ApplicationData.Window.Width,ApplicationData.Window.Height);
#ifdef USE_TEXTURE
switch (ApplicationData.Display.MotionBlur){
case 0:
break;
case 1:
copyTexture(&ApplicationData.Window.TextureMotion);
break;
# ifdef USE_MULTIPLE_TEXTURES
default:
copyTexture(&ApplicationData.Window.TextureMotion);
break;
# endif
}
#endif
glFlush();
glutSwapBuffers();
}
void reshapeFunc(int width,int height){
if (!(ApplicationData.Window.Width=width))
ApplicationData.Window.Width=1;
if (!(ApplicationData.Window.Height=height))
ApplicationData.Window.Height=1;
glViewport(0,0,width,height);
}
void idleFunc(void){
evolve();
glutPostRedisplay();
if (ApplicationData.Display.LimitCPUUsage)
SLEEP(TIME_GRANULARITY);
}
void keyboardFunc(unsigned char key,int x,int y){
#ifdef SCREENSAVER
if (ApplicationData.Window.ScreenSaverMode==SCREENSAVER_MODE_SHOW)
exit(0);
#endif
switch (key){
case 'd':
ApplicationData.Window.DesiredDoubleBuffered=!ApplicationData.Window.DesiredDoubleBuffered;
CheckBoxDoubleBuffered.Data.CheckBox->Checked=ApplicationData.Window.DesiredDoubleBuffered;
break;
case 'f':
ApplicationData.Window.DesiredFullScreen=!ApplicationData.Window.DesiredFullScreen;
CheckBoxFullScreen.Data.CheckBox->Checked=ApplicationData.Window.DesiredFullScreen;
break;
case 'm':
ApplicationData.Window.DesiredMultiSample=!ApplicationData.Window.DesiredMultiSample;
CheckBoxMultiSample.Data.CheckBox->Checked=ApplicationData.Window.DesiredMultiSample;
break;
case 'q':
quitExecute();
break;
#ifdef SCREENSAVER
case 'r':
resetExecute();
break;
#endif
case 's':
saveExecute();
break;
default:
menuKeyboard(ApplicationData.MainMenu,key);
}
}
void specialFunc(int key,int x,int y){
#ifdef SCREENSAVER
if (ApplicationData.Window.ScreenSaverMode==SCREENSAVER_MODE_SHOW)
exit(0);
#endif
menuSpecial(ApplicationData.MainMenu,key);
}
void mouseFunc(int button,int state,int x,int y){
int i;
float u=1-2.*x/ApplicationData.Window.Width,v=1-2.*y/ApplicationData.Window.Height;
#ifdef SCREENSAVER
if (ApplicationData.Window.ScreenSaverMode==SCREENSAVER_MODE_SHOW)
exit(0);
#endif
for (i=0;i<ApplicationData.Points.Count;i++){
ApplicationData.Points.Data[i].X=u;
ApplicationData.Points.Data[i].Y=v;
}
};
#ifdef SCREENSAVER
void passiveMotionFunc(int x,int y){
if (ApplicationData.Window.ScreenSaverMode==SCREENSAVER_MODE_SHOW){
if (ApplicationData.Window.MouseX==-1){
ApplicationData.Window.MouseX=x;
ApplicationData.Window.MouseY=y;
} else {
if (abs(ApplicationData.Window.MouseX-x)+abs(ApplicationData.Window.MouseY-y)>MAX_SCREENSAVER_MOUSE_OFFSET)
exit(0);
}
}
};
#endif
/*********************************************************************
* INI FILE *
*********************************************************************/
void readIniFile(void){
FILE *f;
if (f=fopen(INI_FILENAME,"r")){
menuLoad(ApplicationData.MainMenu,f);
fclose(f);
} else
printf("Cannot read file "INI_FILENAME"\n");
menuInit(ApplicationData.MainMenu);
}
void writeIniFile(void){
FILE *f;
if (f=fopen(INI_FILENAME,"w")){
menuSave(ApplicationData.MainMenu,f);
fclose(f);
} else
printf("Cannot write file" INI_FILENAME "\n");
}
/*********************************************************************
* MENU CALLBACKS *
*********************************************************************/
void fullScreenChange(int checked){
#ifdef SCREENSAVER
if (ApplicationData.Window.ScreenSaverMode==SCREENSAVER_MODE_SHOW)
ApplicationData.Window.DesiredFullScreen=1;
else
#endif
ApplicationData.Window.DesiredFullScreen=checked;
}
void fullScreenParamChange(int index){
if (ApplicationData.Window.FullScreen)
ApplicationData.Window.ChangeMode=1;
}
void doubleBufferedChange(int checked){
ApplicationData.Window.DesiredDoubleBuffered=checked;
}
void multiSampleChange(int checked){
ApplicationData.Window.DesiredMultiSample=checked;
}
#ifdef USE_TEXTURE
# ifdef USE_MULTIPLE_TEXTURES
void motionBlurChange(int index){
ApplicationData.Display.MotionBlur=index;
}
# else
void motionBlurChange(int checked){
ApplicationData.Display.MotionBlur=checked;
}
# endif
#endif
void desiredFPSChange(int position){
ApplicationData.Time.DesiredFPS=position;
}
void limitCPUUsageChange(int checked){
ApplicationData.Display.LimitCPUUsage=checked;
}
void resetExecute(void){
FILE *f;
if (f=fopen(INI_FILENAME,"w")){
fclose(f);
printf("Settings reset, restart the application\n");
}
#ifdef SCREENSAVER
exit(0);
#endif
}
void saveExecute(void){
writeIniFile();
#ifdef SCREENSAVER
exit(0);
#endif
}
void quitExecute(void){
exit(0);
}
void roundedPointsChange(int checked){
ApplicationData.Points.Rounded=checked;
}
void blendMethodChange(int index){
ApplicationData.Display.BlendMethod=index;
}
void luminanceChange(float position){
ApplicationData.Display.Luminance=position*0.01;
}
void sharpnessChange(float position){
ApplicationData.Display.Sharpness=position*0.01;
}
void attenuationChange(float position){
ApplicationData.Display.Attenuation=position*0.01;
}
void spaceFrequencyChange(float position){
ApplicationData.ColorMap.SpaceFrequency=position;
}
void timeFrequencyChange(float position){
ApplicationData.ColorMap.TimeFrequency=position;
}
void periodChange(float position){
ApplicationData.Time.PeriodLength=1000*position;
}
void elasticityChange(float position){
ApplicationData.Time.Elasticity=position;
}
void minDegreeChange(int position){
if (position>ApplicationData.Transformations.MaxDegree)
ITrackBarMinDegree.Data.ITrackBar->Position=ApplicationData.Transformations.MaxDegree;
else
ApplicationData.Transformations.MinDegree=position;
}
void maxDegreeChange(int position){
if (position<ApplicationData.Transformations.MinDegree)
ITrackBarMaxDegree.Data.ITrackBar->Position=ApplicationData.Transformations.MaxDegree;
else
ApplicationData.Transformations.MaxDegree=position;
}
/*********************************************************************
* MAIN PROGRAM *
*********************************************************************/
#ifdef SCREENSAVER
int strcmpleft(char *s,char *t){
while (*s && *s==*t){
s++;
t++;
}
return !*s;
}
int findstr(char *s,char *T[]){
char *t;
while (t=*(T++))
if (strcmpleft(t,s))
return 1;
return 0;
}
int screenSaverMode(int argc,char *argv[]){
char *sConfigureFlags[7]={"-C","/C","C","-c","/c","c",NULL},*sPreviewFlags[7]={"-P","/P","P","-p","/p","p",NULL};
int i;
for (i=1;i<argc;i++){
if (findstr(argv[i],sConfigureFlags))
return SCREENSAVER_MODE_CONFIGURE;
if (findstr(argv[i],sPreviewFlags))
return SCREENSAVER_MODE_PREVIEW;
}
return SCREENSAVER_MODE_SHOW;
}
#endif
int main(int argc,char *argv[]){
#ifdef SCREENSAVER
switch(ApplicationData.Window.ScreenSaverMode=screenSaverMode(argc,argv)){
case SCREENSAVER_MODE_CONFIGURE:
MainMenu.Active=1;
break;
case SCREENSAVER_MODE_PREVIEW:
return 0;
}
#endif
srand(time(NULL));
#ifdef USE_COS_TABLE
initCos();
#endif
ApplicationData.MainMenu=&MainMenu;
readIniFile();
allocTransformation(&ApplicationData.Transformations.T1);
allocTransformation(&ApplicationData.Transformations.T2);
glutInit(&argc,argv);
createWindow();
printf("Entering main loop, press [Escape] for menu, use arrows to navigate.\n");
glutMainLoop();
return 0;
}
Conclusion
Signification des options: [Options générales] -Fullscreen: active/désactive le mode full screen, avec possibilité de spécifier le mode d'affichage -Double buffered: indique si la fenêtre est doublebuffered (moins de clignotements) -Multi sample: active le mode multisample (lignes et points plus lisses) -Motion blur: indique le degré de lissage temporel -Requested frame rate: nombre d'images par secondes désirées (éviter de dépasser la fréquence de l'écran lorsque la fenêtre est double buffered) -Limit CPU usage: tente de limiter un peu la consommation de resources -Save settings: enregistre tout dans un fichier ini -Reset settings: remet à zéro le fichier ini (nécessite de redémarrer le programme pour être pris en compte) -Quit: quitter [Display] -Rounded points: indique si les points doivent être antialiasés (plus lisses) -Blend color method: indique quelle méthode de mélange de couleurs utiliser -Luminance: brillance globale de l'affichage -Sharpness: détail de l'attracteur -Attenuation: atténuation temporelle du motion blur -Colormap space frequency: fréquence spatiale (nombre de couleurs simultanées) de la palette de couleurs -Colormap time frequency: fréquence temporelle (variation dans le temps) de la palette [Attractor] -Cycle length: longueur du cycle de transfert d'un attracteur à l'autre -Cycle elasticity: "élasticité" du transfert (oscillations plus ou moins brusques) -Min attractor degree: complexité minimale des attracteurs -Max attractor degree: complexité maximale des attracteurs
Fichier Zip
Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !
Télécharger le zip
Historique
- 07 janvier 2008 15:20:45 :
- Typo dans le code
- 07 janvier 2008 18:50:59 :
- J'avais oublié de renommer le .exe en .ex_
- 13 janvier 2008 14:55:27 :
- Options supplémentaires, utilisation de textures pour le motion blur et l'accumulation des densités de couleur.
Sources de la même categorie
Sources en rapport avec celle ci
Commentaires et avis
Discussions en rapport avec ce code source dans le forum
glut - openGL [ par loss ]
Quels sont les fichiers necessaires pour utiliser glut(je compile avec VC++)?Ou est ce que je peux les telecharger?Merci d avance.
Gestion de la souris OpenGL SANS GLUT [ par Xentor ]
Comment faire pour connaitre le déplacement de la souris sans utiliser Glut ? (Savoir si on la déplace en haut, à gauche, etc...) J'ai fait plusieurs
OpenGl, glut et Dev c++ 4 [ par fabienGL ]
J'envoie un message car je passait au moin 3 heures sur le forums j'ai essayé tout ce ki à était di mé rien à faire ... j'utilise DEV C++ 4 et je sui
OpenGl & glut avec Dev c++ 4 et WinXP [ par fabienGL ]
J'envoie un message car je passait au moin 3 heures sur le forums j'ai essayé tout ce ki à était di mé rien à faire ... j'utilise DEV C++ 4 et j'ai Wi
glut et opengl [ par MiTcH37 ]
voila ce que j'ai lorsque je compile un prog avec du glut.h...C:\DOCUME~2\Mitch1\LOCALS~1\Temp\cc6Pbaaa.o(.text+0xcc):souris2.cpp: undefined reference
opengl [ par MiTcH37 ]
J'aimerais bien faire de l'opengl, mais ça marche pas... voila ce que j'ai lorsque je compile un prog avec du glut.h...C:\DOCUME~2\Mitch1\LOCALS~1\Tem
devc++ [ par MiTcH37 ]
qqun se sert de devc++ ?J'aimerais bien faire de l'opengl, mais ça marche pas... > > > > voila ce que j'ai lorsque je compile un prog avec
erreur de compile d une source opengl utilisant glut [ par kribler ]
KR!Bl3Rg lerreur suivante qui s afffiche :LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@16quelqun pourrai maidermerci d
Pb Dev C++ 5 et OpenGl [ par guillaume21 ]
J'ai installé glut avec Dev c++ 5. J'ai mis glut.h dans include, glut32.lib dans lib et le dll dans system32 (et mem ds lib lol).J'ai aussi ajouté les
Mélanger OpenGL et Glut [ par tintin72 ]
SalutJ'aimerai me servir des fonctions d'entrée clavier/souris proposées par Glut, mais j'ai vu que Glut s'initialise avec une fonction main façon C.i
|
Téléchargements
Logiciels à télécharger sur le même thème :
|