Modélisation d'une surface avec un maillage mase ressort opengl (glut)

Description

Cette source utilise la seconde loie de newton,
Le maillage est utiliser pour simuler de la pluie qui tombe...

Source / Exemple :


///----------------------------------------------------------------------------//
//
// Open GL 
// simulation des matériaux : modélisation par les particules
// avec une liaison dynamique du type masse ressort
//
// LINCK Sébastien
//----------------------------------------------------------------------------//

//----------------------------------------------------------------------------//
#include "stdafx.h"
#include <stdio.h>
#include <math.h>
#include <stdlib.h> 
#include "glut.h"

#define const_LX				20.0
#define const_LY				16.0
#define const_NX				81
#define const_NY				41
#define const_raideur			20.0
#define const_repos				0.0
#define const_masse				0.75 
#define const_dissipation		0.10
#define const_dt				0.005
#define const_gravite			9.81

#define const_init_z			9.8

#define const_freq              2.0
#ifndef M_PI
#define M_PI					3.1415926535897932384626433832795
#endif

// tableau contenant les coordonnée en Z des noeuds
double TabZNoeuds[const_NX][const_NY];
// tableau contenant les vitesses des noeuds (composante sur Z)
double TabZVitesses[const_NX][const_NY];
double temps;

double const_ampl = 1.0;

 int  xpluie = 10;
 int ypluie = 10;
 double zpluie = const_init_z;
 double const_pluie_z = 0.00;

int LightPos[4] = {0,0,15,0};
int MatSpec [4] = {1,1,1,1};

int fenw,fenh,afficher_lignes=0,afficher_interieur=1;
GLfloat rot_vue_H=0.0, rot_vue_V=0.0;
GLint startx,starty,moving=0;

 double x,y,pasx = (double)const_LX/(double)const_NX
           ,pasy = (double)const_LY/(double)const_NY,c;

unsigned rand_pluie(unsigned N)
{
  return (unsigned)((double)rand()/((double)RAND_MAX+1)*N);
}

/***************************************************************/
void action()
{
	int ix, iy; 
	double x,y,z,dx2,dy2,dz;
	double F,A,V; // Force acceleration vitesse
    static double nouvTabZNoeud[const_NX][const_NY];

  temps += const_dt;
  dx2 =(double)const_LX/(double)const_NX;
  dx2*=dx2;
  dy2=(double)const_LY/(double)const_NY;
  dy2*=dy2;

//****************************PARTIE EXCITATION***********************/

  // Excitaion de quelques points
 /*  
   for (iy=5; iy<10; iy++)
	 { 
	   TabZNoeuds[0][iy] = const_ampl * sin(const_freq *temps)	;   // z = (ft)
	   TabZVitesses[0][iy] = const_ampl * const_freq * cos(const_freq * temps)	;   // v = df(t) / dt
	   nouvTabZNoeud[0][iy]=TabZNoeuds[0][iy];
	  } 

  • /
// La pluie qui tombe if( zpluie <= 0) { TabZNoeuds[xpluie ][ypluie] = const_ampl * sin(const_freq *temps) ; // z = (ft) TabZVitesses[xpluie ][ypluie] = const_ampl * const_freq * cos(const_freq * temps) ; // v = df(t) / dt nouvTabZNoeud[xpluie ][ypluie] = TabZNoeuds[xpluie ][ypluie]; xpluie = rand_pluie( const_NX ); if( xpluie == 0) xpluie= 1;if( xpluie >= 79) xpluie= 78; ypluie = rand_pluie( const_NY ); if( ypluie == 0) ypluie= 1;if( ypluie >= 39) ypluie= 38; zpluie = const_init_z; } else { zpluie -= const_pluie_z; } /**************************** PARTIE DYNAMIQUE ****************/ // Equation de la 2ème loie de Newton // La somme des forces = La masse * L'acceleration sur chaque noeud for (ix = 1; ix < const_NX -1; ix++) { for (iy = 1; iy < const_NY -1; iy++) { // forces des 4 ressorts agissant sue le noeud selon l'axe z //**********************************************/ // liaison 1er voisin dz = TabZNoeuds[ix + 1][iy] - TabZNoeuds[ix][iy] ; F = (const_raideur * dz) / sqrt(pow(dz,2) + dx2 + dy2); // liaison 2eme voisin dz = TabZNoeuds[ix - 1][iy] - TabZNoeuds[ix][iy] ; F+= (const_raideur * dz) / sqrt(pow(dz,2) + dx2 + dy2); // liaison 3eme voisin dz = TabZNoeuds[ix][iy + 1] - TabZNoeuds[ix][iy]; F+= (const_raideur * dz) / sqrt(pow(dz,2) + dx2 + dy2); // liaison 4eme voisin dz = TabZNoeuds[ix][iy - 1] - TabZNoeuds[ix][iy]; F+= (const_raideur * dz) / sqrt(pow(dz,2) + dx2 + dy2); // Prise en compte de la force de frottement ou dissipation du noeud // Prise en compte de la dissipation F-= const_dissipation * TabZVitesses[ix][iy]; // calcul de l'accelerartion A = F / const_masse; // En déduire la vitese du noeud TabZVitesses[ix][iy] = TabZVitesses[ix][iy] + (const_dt * A); // En déduire la position courante du noeud nouvTabZNoeud[ix][iy] = TabZNoeuds[ix][iy] + (const_dt * TabZVitesses[ix][iy]); } } memcpy(TabZNoeuds,nouvTabZNoeud,const_NX*const_NY*sizeof(double)); } void initTableaux() { int ix,iy; temps = 0.0; for (ix=0; ix<const_NX; ix++) { for (iy=0; iy<const_NY; iy++) { TabZNoeuds[ix][iy]=0.0; TabZVitesses[ix][iy]=0.0; } } } void dessinerGrille() { int ix,iy; if (afficher_interieur) { for (ix=0,x=-const_NX/2.0*pasx; ix<const_NX-1; ix++) { for (iy=0,y=-const_NX/2.0*pasy; iy<const_NY-1; iy++) { glBegin(GL_QUADS); c = (TabZVitesses[ix][iy]); if (c>0.0) { if (c>1) glColor3d(0.1,0.3,1); else glColor3d(0.46-c/2.8,0.64-c/2.95,0.89+c/9.1); } else { if (c<-1) glColor3d(0.4,0.9,1); else glColor3d(0.46-c/16.66,0.64+c/3.85,0.89+c/9.09); } glVertex3d(x,y,TabZNoeuds[ix][iy]); c = (TabZVitesses[ix+1][iy]); if (c>0.0) { if (c>1) glColor3d(0.1,0.3,1); else glColor3d(0.46-c/2.8,0.64-c/2.95,0.89+c/9.1); } else { if (c<-1) glColor3d(0.4,0.9,1); else glColor3d(0.46-c/16.66,0.64+c/3.85,0.89+c/9.09); } glVertex3d(x+pasx,y,TabZNoeuds[ix+1][iy]); c = (TabZVitesses[ix+1][iy+1]); if (c>0.0) { if (c>1) glColor3d(0.1,0.3,1); else glColor3d(0.46-c/2.8,0.64-c/2.95,0.89+c/9.1); } else { if (c<-1) glColor3d(0.4,0.9,1); else glColor3d(0.46-c/16.66,0.64+c/3.85,0.89+c/9.09); } glVertex3d(x+pasx,y+pasy,TabZNoeuds[ix+1][iy+1]); c = (TabZVitesses[ix][iy+1]); if (c>0.0) { if (c>1) glColor3d(0.1,0.3,1); else glColor3d(0.46-c/2.8,0.64-c/2.95,0.89+c/9.1); } else { if (c<-1) glColor3d(0.4,0.9,1); else glColor3d(0.46-c/16.66,0.64+c/3.85,0.89+c/9.09); } glVertex3d(x,y+pasy,TabZNoeuds[ix][iy+1]); glEnd(); y+=pasy; } x+=pasx; } } if (afficher_lignes) { glColor3d(1.0,1.0,1.0); for (ix=0,x=-const_NX/2.0*pasx; ix<const_NX-1; ix++) { for (iy=0,y=-const_NX/2.0*pasy; iy<const_NY-1; iy++) { glBegin(GL_LINES); glVertex3d(x,y,TabZNoeuds[ix][iy]); glVertex3d(x+pasx,y,TabZNoeuds[ix+1][iy]); glVertex3d(x,y,TabZNoeuds[ix][iy]); glVertex3d(x,y+pasy,TabZNoeuds[ix][iy+1]); glEnd(); y+=pasy; } glBegin(GL_LINES); glVertex3d(x,y,TabZNoeuds[ix][iy]); glVertex3d(x+pasx,y,TabZNoeuds[ix+1][iy]); glEnd(); x+=pasx; } for (iy=0,y=-const_NX/2.0*pasy; iy<const_NY-1; iy++) { glBegin(GL_LINES); glVertex3d(x,y,TabZNoeuds[ix][iy]); glVertex3d(x,y+pasy,TabZNoeuds[ix][iy+1]); glEnd(); y+=pasy; } } } static void drawString(char *string, GLfloat x, GLfloat y) { glRasterPos2f(x, y); while (*string) { glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, *string); string++; } } static void draw( void ) { char texte[80]; // matériaux glMaterialiv(GL_FRONT_AND_BACK,GL_SPECULAR,MatSpec); glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,100); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0,fenw,0,fenh, -10, 100); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); /*glColor4d(1.0,1.0,1.0,2.0); sprintf(texte,"Amplitude %4.1f",const_ampl); drawString(texte,20,460);*/ glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glPushMatrix(); /* rotation du point de vue autour des axes H et V */ glRotated(rot_vue_H,1.0,0.0,0.0); glRotated(rot_vue_V,0.0,0.0,1.0); dessinerGrille(); /* glBegin(GL_POINTS); glColor3f(0.5,0.9,0.7); glVertex3d((xpluie - 40) * pasx,(ypluie -20) * pasy,zpluie); glEnd();*/ glPushMatrix(); glColor3f(1.0,1.0,1.0); glTranslated((xpluie - 40) * pasx,(ypluie - 40) * pasy,zpluie); glutSolidSphere(0.1,20,20); glPopMatrix(); glutSwapBuffers(); } static void idle( void ) { double deltat=0.0; while (deltat<0.1) { action(); deltat+=const_dt; } draw(); } /* new window size or exposure */ static void reshape( int width, int height ) { GLfloat h = (GLfloat) height / (GLfloat) width; fenw = width; fenh = height; glViewport(0, 0, (GLint)width, (GLint)height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum( -1.0, 1.0, -h, h, 2.0, 100.0 );//25 gluLookAt(0.0,-30, 15 ,0.0,0.0,-8.0,0.0,0.0,1.0); glLightiv(GL_LIGHT0,GL_POSITION,LightPos); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //glTranslatef( 0.0, 0.0, -15.0 ); //glRotatef(-90.0,1.0,0.0,0.0); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); } static void init() { glEnable( GL_DEPTH_TEST ); glEnable( GL_NORMALIZE ); glEnable( GL_SMOOTH); } /*********************************************************/ /* fonction associée aux événements de menu. */ /* - item : code associé au menu selecitonné */ static void menuFunc(int item) { if (item == 99) exit(0); if (item==11) afficher_lignes = !afficher_lignes; if (item==12) afficher_interieur = !afficher_interieur; } /*********************************************************/ /* fonction associée au clique de la souris */ /* paramètres : */ /* - button : nom du bouton pressé GLUT_LEFT_BUTTON, */ /* GLUT_MIDDLE_BUTTON ou GLUT_RIGHT_BUTTON */ /* - state : état du bouton button GLUT_DOWN ou GLUT_UP */ /* - x,y : coordonnée du curseur dans la fenêtre */ static void mouseFunc(int button, int state, int x, int y) { if (button==GLUT_LEFT_BUTTON) { if (state == GLUT_DOWN) { startx = x; starty = y; moving =1; } if (state == GLUT_UP) { moving = 0; } } } /*********************************************************/ /* fonction associée au déplacement de la souris bouton */ /* enfoncé. */ /* paramètres : */ /* - x,y : coordonnée du curseur dans la fenêtre */ static void motionFunc(int x, int y) { if (moving) { rot_vue_V += 0.5*(x-startx); rot_vue_H += 0.5*(y-starty); startx = x; starty = y; /* demande de redessin de la fenêtre */ glutPostRedisplay(); } } /*********************************************************/ /* fonction associée aux interruptions clavier */ /* paramètres : */ /* - c : caractère saisi */ /* - x,y : coordonnée du curseur dans la fenêtre */ static void kbdFunc(unsigned char c, int x, int y) { /* sortie du programme si utilisation des touches ESC, */ /* 'q' ou 'Q'*/ switch (c) { case 27 : case 'q' : case 'Q': exit(0); case 'R' : case 'r' : glutIdleFunc( idle ); break; case 'S' : case 's' : glutIdleFunc( NULL ); break; case 'a' : case 'A' : const_ampl--; break; case 'p' : case 'P' : const_pluie_z += 0.01; break; case 'o' : case 'O' : const_pluie_z -= 0.01; break; } } int main(unsigned int argc, char **argv) { GLint sousmenu; glutInit((int *)&argc, argv); glutInitWindowSize(640, 480); glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); if (glutCreateWindow("3DPHY") == GL_FALSE) { exit(0); } initTableaux(); init(); /* création d'un popup menu */ /* sous menu */ sousmenu = glutCreateMenu(menuFunc); glutAddMenuEntry("ligne", 11); glutAddMenuEntry("interieur", 12); /* menu principal */ glutCreateMenu(menuFunc); glutAddSubMenu("Affichage", sousmenu); glutAddMenuEntry("Quit", 99); /* association du menu au clique droit */ glutAttachMenu(GLUT_RIGHT_BUTTON); /* association de la fonction d'événement souris */ glutMouseFunc(mouseFunc); /* association de la fonction de DRAG */ glutMotionFunc(motionFunc); /* association de la fonction d'événement du clavier */ glutKeyboardFunc(kbdFunc); glutReshapeFunc( reshape ); glutDisplayFunc( draw ); glutMainLoop(); return 0; }

Conclusion :


J'espère que vous aimerez, la pluie qui tombe c'est toujours fascinant à regarder..

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.