Opengl : sinusoides 3d

Description

Programme qui montre deux sons.
L'intensite du son decroit avec la distance.
En plus il y a le tracage des decibels de la somme des deux bruit en un point donne.

Source / Exemple :


#include <windows.h>
#include <math.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glaux.h>

typedef struct tagFUNC_SINUS
	{
	double dx;										// delta x
	double dy;										// delta y
	double dz;										// delta z
	double h;											// amplitude
	double lambda;								// longeur d'onde
	void   (*funcColor)(double);	// fonction de coloriage
	double arg;
	}FUNC_SINUS,*P_FUNC_SINUS;

typedef struct tagFUNC_SUM
	{
	double				dz;									// delta z
	void					(*funcColor)(double); // fonction de coloriage
	P_FUNC_SINUS	a;
	P_FUNC_SINUS	b;
	double				arg;
	}FUNC_SUM,*P_FUNC_SUM;
//------------------------------------------------------------
#define PI							3.1415926535
//------------------------------------------------------------
#define MY_MIN_ZOOM			1
#define MY_MAX_ZOOM			100

#define MY_CUBE_LINE		100
#define MY_SINUS_1			101
#define MY_SINUS_2			102
#define MY_SUM					103
//------------------------------------------------------------
void RePaint(HDC DC,double zoom,double theta,double phi)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);	
glLoadIdentity();

// position de l'oeil
gluLookAt(zoom*cos(theta)*cos(phi),zoom*sin(theta)*cos(phi),zoom*sin(phi),0,0,0,cos(theta-PI)*cos(PI/2.-phi),sin(theta-PI)*cos(PI/2.-phi),sin(PI/2.-phi));

// on trace les lignes du cube
glCallList(MY_CUBE_LINE);
// on trace la premire sinusoide
glCallList(MY_SINUS_1);
// on trace la seconde sinusoide
glCallList(MY_SINUS_2);
// on trace la somme (franges d'interferences)
glCallList(MY_SUM);

glPopMatrix();

SwapBuffers(DC);
}
//------------------------------------------------------------
void InitPixelFormat(HDC hdc)
{	
PIXELFORMATDESCRIPTOR pfd = {sizeof (PIXELFORMATDESCRIPTOR),1,PFD_SUPPORT_OPENGL | PFD_TYPE_RGBA | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER,16,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0};
SetPixelFormat(hdc,ChoosePixelFormat(hdc,&pfd),&pfd);
}
//------------------------------------------------------------	
// degrades du rouge
void FillColorRedToYellow(double x)
{glColor3d(1.,x,0.);}
void FillColorRedToMagenta(double x)
{glColor3d(1.,0.,x);}
void FillColorRedToWhite(double x)
{glColor3d(1.,x,x);}
// degrades du vert
void FillColorGreenToRed(double x)
{glColor3d(1.-x,x,x);}
void FillColorGreenToWhite(double x)
{glColor3d(x,1.,x);}
void FillColorGreenYellow(double x)
{glColor3d(x,1.,0.);}
void FillColorGreenToCyan(double x)
{glColor3d(0.,1.,x);}
// degrades du bleu
void FillColorBlueToMaganta(double x)
{glColor3d(x,0.,1.);}
void FillColorBlueToWhite(double x)
{glColor3d(x,x,1.);}
void FillColorBlueToCyan(double x)
{glColor3d(0.,x,1.);}
// degrade de gris
void FillColorBlackToWhite(double x)
{glColor3d(x,x,x);}
//------------------------------------------------------------	
// construit un sinusoide 3D de centre (dx,dy,0)
// d'amplitude <h>, et de longueur d'onde <lambda>
double calcR(P_FUNC_SINUS p,double x,double y)
{
return sqrt((x-p->dx)*(x-p->dx)+(y-p->dy)*(y-p->dy));
}

double funcSinus(P_FUNC_SINUS p,double x,double y)
{
// distance
double r;

p->arg = r = calcR(p,x,y);

if(r > 0.)
	{
	return p->dz - p->h*sin(r*2.*PI/p->lambda)/r;
	}
else
	{
	return p->dz - p->h*2.*PI/p->lambda;
	}
}
void colorSinus(P_FUNC_SINUS p,double z)
{
p->funcColor(0.5+(z-p->dz)/(2.*p->h));
//p->funcColor(1.-1./(1.+p->arg));
}
//------------------------------------------------------------	
// construit l'interference de deux sinusoides
// Ici calculs complexes ...
double funcSum(P_FUNC_SUM p,double x,double y)
{
double rA,rB;
double reA,imA;
double reB,imB;
double k;

k		= 2.*PI/p->a->lambda;
rA	= calcR(p->a,x,y);
rB	= calcR(p->b,x,y);

if(rA <= 0. || rB <= 0.)
	{
	p->arg = 0.;
	return 0.;
	}

reA = cos(k*rA)/rA;
reB = cos(k*rB)/rB;
imA = sin(k*rA)/rA;
imB = sin(k*rB)/rB;

// l'argument
p->arg = atan2(imA + imB,reA + reB);
// le module
return p->dz+4*log10((reA + reB)*(reA + reB)+(imA + imB)*(imA + imB));
}
void colorSum(P_FUNC_SUM p,double z)
{
//p->funcColor(0.5+(p->arg/(2.*PI)));
p->funcColor(0.6-(7+z-p->dz)/(9.));
}

//------------------------------------------------------------	
void CreateGraph3D(double (*calcFunc)(void*,double,double),void (*funcColor)(void*,double),void *param)
{
double x,y;
double step;

step = 0.2;

for(y=-10.+step;y<=+10.;y+=step)
	{
	glBegin(GL_QUAD_STRIP);
	for(x=-10.;x<=+10.;x+=step)
		{
		double z;

		// on doit garantir qu'il faut faire le calcul
		// AVANT le coloriage
		z	= calcFunc(param,x,y - step);
		funcColor(param,z);
		glVertex3d(x,y - step,z);

		z	= calcFunc(param,x,y);
		funcColor(param,z);
		glVertex3d(x,y,calcFunc(param,x,y));
		}
	glEnd();
	}

}
//------------------------------------------------------------	
void CreateNewList(void)
{
FUNC_SINUS	f1,f2;
FUNC_SUM		fs;

glNewList(MY_CUBE_LINE,GL_COMPILE);
	glColor3d(0.,1.,0.);

	glBegin(GL_LINE_LOOP);
		glVertex3d(-10.,-10.,-10.);
		glVertex3d(-10.,-10.,+10.);
		glVertex3d(-10.,+10.,+10.);
		glVertex3d(-10.,+10.,-10.);
	glEnd();

	glBegin(GL_LINE_LOOP);
		glVertex3d(+10.,-10.,-10.);
		glVertex3d(+10.,-10.,+10.);
		glVertex3d(+10.,+10.,+10.);
		glVertex3d(+10.,+10.,-10.);
	glEnd();

	glBegin(GL_LINES);
		glVertex3d(+10.,-10.,-10.);
		glVertex3d(-10.,-10.,-10.);
		glVertex3d(+10.,-10.,+10.);
		glVertex3d(-10.,-10.,+10.);
		glVertex3d(+10.,+10.,+10.);
		glVertex3d(-10.,+10.,+10.);
		glVertex3d(+10.,+10.,-10.);
		glVertex3d(-10.,+10.,-10.);
	glEnd();

glEndList();

glNewList(MY_SINUS_1,GL_COMPILE);
	
	f1.dx					= -0.;
	f1.dy					= -5.5;
	f1.dz					= -10.;
	f1.h					= 5.;
	f1.lambda			= 1.5;
	f1.funcColor	= FillColorRedToYellow;

	CreateGraph3D(funcSinus,colorSinus,&f1);

glEndList();

glNewList(MY_SINUS_2,GL_COMPILE);

	f2.dx					= +0.;
	f2.dy					= +5.5;
	f2.dz					= -10.;
	f2.h					= 5.;
	f2.lambda			= 1.5;
	f2.funcColor	= FillColorBlueToCyan;

	CreateGraph3D(funcSinus,colorSinus,&f2);

glEndList();

glNewList(MY_SUM,GL_COMPILE);
	
	fs.dz					= 12.5;
	fs.a					= &f1;
	fs.b					= &f2;
	fs.funcColor	=	FillColorGreenToRed;

	CreateGraph3D(funcSum,colorSum,&fs);

glEndList();

}
//------------------------------------------------------------	
LRESULT CALLBACK WindowProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam)
{
static HDC						DC;
static HGLRC					RC;
static int						cxClient,cyClient;
static double					zoom,theta,phi,_theta,_phi;
static BOOL						isMouseDown;
static int						xMouseStart,yMouseStart;

// traitement des messages
switch (iMsg)
	{
	case WM_CREATE:
		{
		DC	=	GetDC(hwnd);
		InitPixelFormat(DC);
		RC	= wglCreateContext(DC);
		wglMakeCurrent(DC,RC);
		glEnable(GL_DEPTH_TEST); 
		glClearColor(0,0,0,0); 

		zoom	= 50.;
		theta = 0.;
		phi		= 0.;

		CreateNewList();
		break;
		}
  case WM_SIZE:
		{
		cxClient = LOWORD(lParam);	cxClient = (cxClient ? cxClient : 1);
		cyClient = HIWORD(lParam);	cyClient = (cyClient ? cyClient : 1);
    glViewport(0,0,cxClient,cyClient);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.,(float)(cxClient)/(float)(cyClient),0.1,1000);
   	break;
		}
	case WM_CHAR:
		{
		switch((char)wParam)
			{
			case 'a':
				{
				zoom -= 1.;
				if(zoom < MY_MIN_ZOOM)	zoom = MY_MIN_ZOOM;
				return 0;
				}
			case 'q':
				{
				zoom += 1.;
				if(zoom > MY_MAX_ZOOM)	zoom = MY_MAX_ZOOM;
				return 0;
				}
			}
		break;
		}
	case WM_LBUTTONDOWN:
		{
		xMouseStart = LOWORD(lParam);
		yMouseStart = HIWORD(lParam);
		// on sauvegarde les angles
		_theta	= theta;
		_phi		= phi;
		isMouseDown = TRUE;
		SetCapture(hwnd);
		return 0;
		}
	case WM_LBUTTONUP:
		{
		if(isMouseDown)
			{
			ReleaseCapture();
			isMouseDown = FALSE;
			}
		return 0;
		}
	case WM_MOUSEMOVE:
		{
		if(isMouseDown)
			{
			int x,y;
			x = (int) (__int16) LOWORD(lParam);
			y = (int) (__int16) HIWORD(lParam);

			// attention, comme les coordonnees en Y
			// client sont inversees (de haut en bas)
			// il faut faire -, et non +
			// comme pout le X
			theta = _theta + ((xMouseStart - x)*2*PI)/(double)cxClient;
			phi		= _phi	 - ((yMouseStart - y)*2*PI)/(double)cyClient;
			}
		return 0;
		}
  case WM_PAINT:
		{
		RePaint(DC,zoom,theta,phi);
		return 0;
		}
	case WM_DESTROY:
		{
		glDeleteLists(MY_CUBE_LINE,1);

    wglMakeCurrent(NULL, NULL);
    wglDeleteContext(RC);
    ReleaseDC(hwnd,DC);
		PostQuitMessage(0);
		break;
		}
	}
return DefWindowProc(hwnd,iMsg,wParam,lParam);
}	
//------------------------------------------------------------
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow)
{
WNDCLASS	wc;
MSG				msg;
HWND			hWnd;

wc.style					= CS_OWNDC;
wc.lpfnWndProc		= WindowProc;
wc.cbClsExtra			= 0;
wc.cbWndExtra			= 0;
wc.hInstance			= hInstance;
wc.hIcon					= LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor				= LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground	= NULL;
wc.lpszMenuName		= NULL;
wc.lpszClassName	= "jcdSINUS3D";

RegisterClass(&wc);

hWnd = CreateWindow("jcdSINUS3D","Franges d'interférences 3D à deux sources sinusoïdales (JCD)",
										WS_OVERLAPPEDWINDOW | WS_VISIBLE,
										CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
										NULL,NULL,hInstance,NULL
										);
	
while(GetMessage(&msg,NULL,0,0))
	{
	TranslateMessage(&msg);
	DispatchMessage(&msg);
	}
	
return 0;
}

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.