//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#ifdef __WIN32__
#include <windows.h> // Header pour les Applications Windows
#endif
#include <stdio.h> // Header d'Entrée/Sortie Standard
#include <GL/glut.h> // Header OpenGL Utility Toolkit (GLUT)
#include <math.h> // Header OpenGL Utility Toolkit (GLUT)
#define pi 3.1415926535897932384626433832795f // PI pour les angles
#ifndef __cplusplus
typedef int bool;
#define false (1==2)
#define true (1==1)
#endif
//------------------------------------------------------------------------------
// Variables & Constantes
//------------------------------------------------------------------------------
// Gestion du temps
typedef struct
{
int tps; // temps depuis le début
int non_ecoule; // temps non ecoulé pendant la pause
float ecart; // ecart de temps entre deux frames
long int frame; // nombre de frames depuis le début
int frame_fps; // nombre réinitialisé pour les FPS
int base; // temps réinitialisé pour les FPS
int pause; // pause du temps
float fps; // nombre de FPS
} TEMPS;
TEMPS temps;
// pour la fenêtre
int WIDTH=640; // largeur de la fenêtre
int HEIGHT=480; // hauteur de la fenêtre
// pour le motion blur
UINT g_Texture[2];
int g_Viewport = 0;
int g_BlurRate = 50;
// Gestion d'une tentacule
typedef struct
{
float posx, posy, posz;
float angle, vitesse, accel;
float color;
} TENTACULE;
TENTACULE tentacule;
//------------------------------------------------------------------------------
// Fonctions & Procédures
//------------------------------------------------------------------------------
void Tentacule ( TENTACULE * );
void Branche ( float, float, float );
void ReSizeGLScene ( int, int );
void InitGL ( );
void DrawGL ( );
void Titre ( );
int main( int, char**, char** );
//------------------------------------------------------------------------------
// Peut-on afficher la frame suivante ? Et on calcule/affiche le nombre de FPS
//------------------------------------------------------------------------------
bool AnimateNextFrame ( int desiredFrameRate )
{
static float temps_ecoule = 0.0f;
temps_ecoule += temps.ecart;
// on vérifie si on peut animer la prochaine frame (1 seconde / FPS)
if( temps_ecoule > ( 1.0f / (float) desiredFrameRate ) )
{
temps_ecoule = 0.0f;
return true;
}
else return false; // on anime pas encore
}
//------------------------------------------------------------------------------
// Crée une texture vide
//------------------------------------------------------------------------------
void CreateRenderTexture(UINT textureArray[], int size, int channels, int type, int textureID)
{
unsigned int *pTexture = NULL; // crée un pointeur
// Alloue de la mémoire et initialise la mémoire
pTexture = ( unsigned int * ) malloc ( size * size * channels * sizeof ( unsigned int ) );
memset(pTexture, 0, size * size * channels * sizeof(unsigned int));
// Enregistre la texture dans OpenGL
glGenTextures(1, &textureArray[textureID]);
glBindTexture(GL_TEXTURE_2D, textureArray[textureID]);
glTexImage2D(GL_TEXTURE_2D, 0, channels, size, size, 0, type, GL_UNSIGNED_INT, pTexture);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
// Since we stored the texture space with OpenGL, we can delete the image data
free ( pTexture );
}
//------------------------------------------------------------------------------
// DrawMB : Dessine ce qui est nécessaire, avec Motion Blur
//------------------------------------------------------------------------------
void DrawMB()
{
int x, y;
float bass=0, aigu=0;
glDisable(GL_TEXTURE_2D);
glEnable(GL_COLOR);
// MotionBlur
Tentacule ( &tentacule );
glDisable(GL_COLOR);
glEnable(GL_TEXTURE_2D);
glColor3d(1,1,1);
}
//------------------------------------------------------------------------------
// DrawNMB : Dessine ce qui est nécessaire, sans Motion Blur
//------------------------------------------------------------------------------
void DrawNMB()
{
glEnable(GL_COLOR);
glDisable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
// Non Motion Blur
Tentacule ( &tentacule );
glDisable(GL_COLOR);
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glColor3d(1,1,1);
}
//------------------------------------------------------------------------------
// Rendu du Motion Blur
//------------------------------------------------------------------------------
void RenderMotionBlur ( int textureID )
{
int add=10;
glPushMatrix();
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, g_Texture[textureID]);
glColor4f(1, 1, 1, 0.95f);
// OrthoMode
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho( 0, WIDTH, HEIGHT, 0, 0, 1 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f); glVertex2f(-add, -add);
glTexCoord2f(0.0f, 0.0f); glVertex2f(-add, HEIGHT+add);
glTexCoord2f(1.0f, 0.0f); glVertex2f(WIDTH+add, HEIGHT+add);
glTexCoord2f(1.0f, 1.0f); glVertex2f(WIDTH+add, -add);
glEnd();
// PerspectiveMode
glMatrixMode( GL_PROJECTION );
glPopMatrix();
glMatrixMode( GL_MODELVIEW );
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glPopMatrix();
}
//------------------------------------------------------------------------------
// Modifie le titre de la fenêtre
//------------------------------------------------------------------------------
void Titre ( )
{
char title[255];
if ( temps.tps - temps.base > 83 ) // Si ca fait une seconde
{
temps.fps = temps.frame_fps * 1000.0 / ( temps.tps - temps.base );
temps.base = temps.tps; // Le temps de base est actualisé
temps.frame_fps = 0; // On recommence à compter
sprintf ( title, "%02d:%02d:%03d (%.0f FPS) (%d)", temps.tps/1000/60, temps.tps/1000%60, temps.tps%1000, temps.fps, temps.frame );
glutSetWindowTitle ( title );
}
}
//------------------------------------------------------------------------------
// Resize Function
//------------------------------------------------------------------------------
void ReSizeGLScene ( int width, int height )
{
// Pour éviter une prochaine division par zéro
if ( height == 0 ) height=1;
glViewport (0, 0, width, height ); // Notre fenêtre est redimensionnée
glMatrixMode ( GL_PROJECTION ); // Sélection d'une matrice de projection
glLoadIdentity ( ); // Initialisation de cette matrice
// Calcule de l'aspect de la fenêtre ( angle, ratio, z proche, z loin )
gluPerspective ( 45.0f, ( float ) width / ( float ) height, 0.1f, 300.0f );
glMatrixMode ( GL_MODELVIEW ); // Sélection d'une matrice modelview
glLoadIdentity ( ); // Initialisation de cette matrice
WIDTH = width;
HEIGHT = height;
}
//------------------------------------------------------------------------------
// Initialisation Function
//------------------------------------------------------------------------------
void InitGL ( )
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Arrière Plan Noir
glClearDepth(1.0f); // Configuration de la profondeur du buffer
ReSizeGLScene(WIDTH, HEIGHT);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST); // Test sur la profondeur (évite des bugs)
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glDisable(GL_BLEND);
glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
glShadeModel(GL_SMOOTH); // Smooth Shading Activé, il doit lisser les formes (?)
glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
CreateRenderTexture(g_Texture, 512, 3, GL_RGB, 0);
glEnable(GL_COLOR);
int n=0;
while ((pow(2,n) <= WIDTH) && (pow(2,n) <= HEIGHT)) n++;
g_Viewport = (int)pow(2,n-1);
}
//------------------------------------------------------------------------------
// Calcule l'angle à un temps précis et sans dépassement d'un angle max (pour tentacule)
// vitesse : vitesse de la rotation
// max : angle maximal à ne pas dépasser
// angle_old : angle déjà affiché
// Retourne l'angle calculé
//------------------------------------------------------------------------------
float CalculAngle ( float vitesse, float max, float angle_old )
{
float angle = vitesse * 25.0f;
if ( max != 0 )
{
if ( angle < -max ) angle = -max;
if ( angle > max ) angle = max;
}
return angle;
}
//------------------------------------------------------------------------------
// Dessine une tentacule
// Utilise la fonction Branche (qui dessine les 4 branches de la tentacule)
//------------------------------------------------------------------------------
void Tentacule ( TENTACULE * tentacule )
{
glPushMatrix ( );
tentacule->accel += temps.ecart*100; // on accélère
tentacule->vitesse = 2*cos(tentacule->accel*pi/180.0f); // on modifie la vitesse
tentacule->angle += tentacule->vitesse*temps.ecart*100; // on modifie l'angle
tentacule->color += temps.ecart * 0.6;
// Transformations appliquées au cube
glEnable ( GL_COLOR );
glTranslatef ( tentacule->posx, tentacule->posy, tentacule->posz ); // On se recule pour voir la scène
glRotatef ( tentacule->angle + tentacule->vitesse, 0, 0, 1 ); // On effectue une rotation sur l'axe z
glColor3f ( ( 1.0f - ( ( ( int )( ( 1.0f + tentacule->color ) * 100 ) ) % 100 ) / ( float ) 100 ), 0.0f, 0.0f );
glBegin(GL_QUADS); // On dessine notre carré centrale
glVertex3f( -1.0f, -1.0f, 0.0f );
glVertex3f( -1.0f, 1.0f, 0.0f );
glVertex3f( 1.0f, 1.0f, 0.0f );
glVertex3f( 1.0f, -1.0f, 0.0f );
glEnd();
// Les 4 Tentacules
Branche ( tentacule->vitesse, tentacule->angle, tentacule->color );
glRotatef ( 90, 0, 0, 1 ); // On effectue une rotation sur l'axe z
Branche ( tentacule->vitesse, tentacule->angle, tentacule->color );
glRotatef ( 90, 0, 0, 1 ); // On effectue une rotation sur l'axe z
Branche ( tentacule->vitesse, tentacule->angle, tentacule->color );
glRotatef ( 90, 0, 0, 1 ); // On effectue une rotation sur l'axe z
Branche ( tentacule->vitesse, tentacule->angle, tentacule->color );
glDisable ( GL_COLOR );
glPopMatrix ( );
}
//------------------------------------------------------------------------------
// Dessine une branche de tentacule
// angle : angle de départ de la rotation
// posx, posy : point de départ en x ou en y
//------------------------------------------------------------------------------
// N.B. : Couleur en dégradé : On utilse un modulo pour ne pas dépasser 1.0f
// 1.0f - ( ( ( int )( ( 0.8f + color ) * 100 ) ) % 100 ) / ( float ) 100 )
// Dégradé Pour Couleur Coul Pour Modulo Pour Modulo
// Inverse Modulo Depart Modif Modulo
//------------------------------------------------------------------------------
void Branche ( float vitesse, float angle, float color )
{
float val;
glPushMatrix ( );
// Branche inclinée
glTranslatef ( 0.0f, 2.0f, 0.0f ); // On se recule de 25 unités pour voir le cube
glColor3f ( ( 1.0f - ( ( ( int )( ( 0.8f + color ) * 100 ) ) % 100 ) / ( float ) 100 ), 0.0f, 0.0f );
val = 1.13f; // sqrt(0.8f*0.8f+0.8f*0.8f);
glBegin(GL_QUADS);
glVertex3f( -0.8f, -0.8f, 0.0f );
glVertex3f( 0.8f, -0.8f, 0.0f );
glVertex3f( val * cos ( ( 90 - 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f),
val * sin ( ( 90 - 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f), 0.0f );
glVertex3f( val * cos ( ( 90 + 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f),
val * sin ( ( 90 + 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f), 0.0f );
glEnd();
glRotatef ( -CalculAngle ( vitesse, 45, angle ), 0, 0, 1 ); // On effectue une rotation sur l'axe z
glTranslatef ( 0.0f, 1.8f, 0.0f ); // On se recule de 25 unités pour voir le cube
glColor3f ( ( 1.0f - ( ( ( int )( ( 0.6f + color ) * 100 ) ) % 100 ) / ( float ) 100 ), 0.0f, 0.0f );
val = 0.8f; //sqrt(0.6f*0.6f+0.6f*0.6f);
glBegin(GL_QUADS);
glVertex3f( -0.8f, -0.8f, 0.0f );
glVertex3f( 0.8f, -0.8f, 0.0f );
glVertex3f( val * cos ( ( 90 - 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f),
val * sin ( ( 90 - 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f), 0.0f );
glVertex3f( val * cos ( ( 90 + 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f),
val * sin ( ( 90 + 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f), 0.0f );
glEnd();
glRotatef ( -CalculAngle ( vitesse, 45, angle ), 0, 0, 1 ); // On effectue une rotation sur l'axe z
glTranslatef ( 0.0f, 1.4f, 0.0f ); // On se recule de 25 unités pour voir le cube
glColor3f ( ( 1.0f - ( ( ( int )( ( 0.4f + color ) * 100 ) ) % 100 ) / ( float ) 100 ), 0.0f, 0.0f );
val = 0.56f; //sqrt(0.4f*0.4f+0.4f*0.4f);
glBegin(GL_QUADS);
glVertex3f( -0.6f, -0.6f, 0.0f );
glVertex3f( 0.6f, -0.6f, 0.0f );
glVertex3f( val * cos ( ( 90 - 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f),
val * sin ( ( 90 - 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f), 0.0f );
glVertex3f( val * cos ( ( 90 + 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f),
val * sin ( ( 90 + 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f), 0.0f );
glEnd();
glRotatef ( -CalculAngle ( vitesse, 45, angle ), 0, 0, 1 ); // On effectue une rotation sur l'axe z
glTranslatef ( 0.0f, 1.0f, 0.0f ); // On se recule de 25 unités pour voir le cube
glColor3f ( ( 1.0f - ( ( ( int )( ( 0.2f + color ) * 100 ) ) % 100 ) / ( float ) 100 ), 0.0f, 0.0f );
val = 0.28f; //sqrt(0.2f*0.2f+0.2f*0.2f);
glBegin(GL_QUADS);
glVertex3f( -0.4f, -0.4f, 0.0f );
glVertex3f( 0.4f, -0.4f, 0.0f );
glVertex3f( val * cos ( ( 90 - 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f),
val * sin ( ( 90 - 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f), 0.0f );
glVertex3f( val * cos ( ( 90 + 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f),
val * sin ( ( 90 + 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f), 0.0f );
glEnd();
glRotatef ( -CalculAngle ( vitesse, 45, angle ), 0, 0, 1 ); // On effectue une rotation sur l'axe z
glTranslatef ( 0.0f, 0.6f, 0.0f ); // On se recule de 25 unités pour voir le cube
glColor3f ( ( 1.0f - ( ( ( int )( ( 0.1f + color ) * 100 ) ) % 100 ) / ( float ) 100 ), 0.0f, 0.0f );
val = 0.0f; //sqrt(0.0f*0.0f+0.0f*0.0f);
glBegin(GL_QUADS);
glVertex3f( -0.2f, -0.2f, 0.0f );
glVertex3f( 0.2f, -0.2f, 0.0f );
glVertex3f( val * cos ( ( 90 - 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f),
val * sin ( ( 90 - 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f), 0.0f );
glVertex3f( val * cos ( ( 90 + 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f),
val * sin ( ( 90 + 45 - CalculAngle ( vitesse, 45, angle ))*pi/180.0f), 0.0f );
glEnd();
glPopMatrix ( );
}
//------------------------------------------------------------------------------
// Draw Function
//------------------------------------------------------------------------------
void DrawGL ( )
{
temps.frame++;
temps.frame_fps++;
temps.ecart = (double)(( glutGet ( GLUT_ELAPSED_TIME ) - temps.tps - 0.0001) / 1000);
temps.tps = glutGet ( GLUT_ELAPSED_TIME );
Titre ( );
glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
ReSizeGLScene(WIDTH, HEIGHT);
if( AnimateNextFrame(g_BlurRate) )
{
glViewport(0, 0, g_Viewport, g_Viewport);
RenderMotionBlur(0);
DrawMB();
glBindTexture(GL_TEXTURE_2D,g_Texture[0]);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, g_Viewport, g_Viewport, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, WIDTH, HEIGHT);
}
RenderMotionBlur(0);
DrawNMB();
glutSwapBuffers ( );
glutPostRedisplay ( );
}
//------------------------------------------------------------------------------
// Main Function
//------------------------------------------------------------------------------
int main( int argc, char *argv[ ], char *envp[ ] )
{
// Create The Window
glutInit ( &argc, argv );
glutInitDisplayMode ( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
glutInitWindowSize ( WIDTH, HEIGHT );
glutInitWindowPosition ( 50, 50 );
glutCreateWindow ( "" );
Titre ( );
tentacule.posx = 0.0f;
tentacule.posy = 0.0f;
tentacule.posz = -15.0f;
tentacule.angle = 0.0f;
tentacule.vitesse = 0.0f;
tentacule.accel = 0.0f;
tentacule.color = 0.0f;
// OpenGL Function
glutReshapeFunc ( ReSizeGLScene );
glutDisplayFunc ( DrawGL );
InitGL ( );
glutMainLoop ( );
return 0;
}
//------------------------------------------------------------------------------
// THE END
//------------------------------------------------------------------------------