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

Soyez le premier à donner votre avis sur cette source.

Vue 8 279 fois - Téléchargée 564 fois

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

Ajouter un commentaire

Commentaires

Messages postés
212
Date d'inscription
mardi 17 mai 2005
Statut
Membre
Dernière intervention
23 juin 2011

Salut,

Content que cette source ai pu t'aider. ;-)
Sinon pour ce qui est de l'utilité du calcul de force des ressorts, c'est tout simplement car c'est un modèle dynamique et que si on ne prend pas en compte la force des quatre ressorts (ligne entre les points), les points restent en bas une fois le point excité. J'espère que j'ai répondu à ta question.
Messages postés
1
Date d'inscription
lundi 25 février 2008
Statut
Membre
Dernière intervention
23 juin 2011

Salut,

Tout d'abord je vous remercier sur cet exemple, je l'ai trouvé vraiment très utile.

J'ai une petit question:

Au niveau du Code tu as ajouter 4 forces

// liaison 1er voisin
dz = TabZNoeuds[ix + 1][iy] - TabZNoeuds[ix][iy] ;
printf("%f = %f - %f \n",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] ;
printf("%f = %f - %f \n",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];
printf("%f = %f - %f \n",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];
printf("%f = %f - %f \n\n",dz,TabZNoeuds[ix][iy - 1],TabZNoeuds[ix][iy]);
F+= (const_raideur * dz) / sqrt(pow(dz,2) + dx2 + dy2);

Je me demande c'est quoi exactement l'utilité de ces forces.

Merci d'avance
Messages postés
212
Date d'inscription
mardi 17 mai 2005
Statut
Membre
Dernière intervention
23 juin 2011

Salut,

Selon le lien : http://fr.wikipedia.org/wiki/M%C3%A9thode_d%27Euler

La méthode d'euler est utiliser pour calculer des valeur approchées de primitive,
Dans mon code je calcule l'accéleration qui est éale à la somme des forces (2nd loie de Newton),
puis je dérive pour obtenir la vitesse et je redérive pour obtenir la position (en fonction du temps).
Messages postés
7
Date d'inscription
lundi 4 juillet 2005
Statut
Membre
Dernière intervention
29 août 2008

visual studio existe en version express et cette version est gratuite, il y a moins de fonctionnalités que la version payante.
visual studio n'en reste pas moins le meilleur éditeur gratuit à ce jour, enfin c'est ce que j'en pense personnellement j'en ai essayé pas mal parmis ceux kdevelop vim, eclipse qui est bien aussi.
Couplé avec visual assist x que tu pourras trouver chez wholetomato l'éditeur devient vraiment puissant.
Ce que tu gagnes c'est surtout de la productivité le couple vst+vax te permet de
-documenter ton code en deux clic
-changer des signatures et propager les changements à tous les appels
-renommer des classes de la même manière
-renommer des variables
-coloration syntaxique
-aide et documentation contextuelle
etc etc
tu devrais l'essayer tout simplement

pour la méthode d'euler
http://fr.wikipedia.org/wiki/M%C3%A9thode_d%27Euler
Messages postés
30
Date d'inscription
dimanche 20 juillet 2008
Statut
Membre
Dernière intervention
7 octobre 2009
1
Salut, c'est juste que je travail avec DEV C++, j'aimerai bien que vous m'expliquiez la raison pour laquelle vous utiliser Visual; car j'aimerai bien l'apprendre s'il a un plus.
Afficher les 12 commentaires

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.