/********************************************************************** DEMO OpenGL/OpenAL (3D Spatalization) Listener (OpenAL) - Camera (OpenGL) Source Helicopter - rotating about the origin. Source Radar - rotating along z-axis Source Van - Moving on xy plane FIX ME 1) The movment of camera seem to be wrong. 2) The Radar should rotate at the vertex instead of the base TO DO 1) Add control to adjust height, path and speed of the Helicopter. 2) Add control to adjust the cone of inner/outer angle of the Radar. 3) use joystick to move listener/camera 4) make it conformed to OpenAL 1.1 specification. Function:- 1) Attenutation By Distance 2) Panning Left/Right 3) Doppler Effect (Not completed) 4) Angle of Cone (Not completed) 5) Background Music (Not yet implemented) ***********************************************************************/ #include #include #include #include #include #include #include #define PI 3.1415265359 #define PIdiv180 3.1415265359/180.0 int LastUpdate=0; int GetTime() { timeb t; ftime(&t); return 1000 * t.time + t.millitm; } void OnIdle() { static int nLastTime = GetTime(); static int nFrameCount = 0; if (nFrameCount++ == 100) { float fFPS = 100000.0f/static_cast(GetTime() - nLastTime); char Title[256]; sprintf(Title, "Demo 3D - %.2f FPS", fFPS); glutSetWindowTitle(Title); nFrameCount = 0; nLastTime = GetTime(); } glutPostRedisplay(); } struct SF3dVector { GLfloat x,y,z; }; struct SF2dVector { GLfloat x,y; }; class CCamera { private: SF3dVector Position; SF3dVector ViewDir; bool ViewDirChanged; GLfloat RotatedX, RotatedY, RotatedZ; void GetViewDir ( void ); public: CCamera(); void Render ( void ); void Move ( SF3dVector Direction ); void RotateX ( GLfloat Angle ); void RotateY ( GLfloat Angle ); void RotateZ ( GLfloat Angle ); void RotateXYZ ( SF3dVector Angles ); void MoveForwards ( GLfloat Distance ); void StrafeRight ( GLfloat Distance ); }; CCamera Camera; #define NUM_BUFFERS 5 #define NUM_SOURCES 5 #define NUM_ENVIRONMENTS 1 ALfloat listenerPos[3]; ALfloat listenerVel[3]={0.0,0.0,0.0}; ALfloat listenerOri[]={0.0,0.0,0.0, 1.0, 0.0,0.0}; struct { ALfloat Pos[3]; ALfloat Vel[3]; ALfloat rgb[3]; ALfloat polar_distance,angle; ALboolean playing; } source_3d[NUM_SOURCES]; ALuint buffer[NUM_BUFFERS]; ALuint source[NUM_SOURCES]; ALuint environment[NUM_ENVIRONMENTS]; int GLwin; void set_listener_pos(ALfloat x,ALfloat y,ALfloat z) { listenerPos[0]=x; listenerPos[1]=y; listenerPos[2]=z; alListenerfv(AL_POSITION,listenerPos); } void set_source_pos(int idx,ALfloat x,ALfloat y,ALfloat z) { source_3d[idx].Pos[0]=x; source_3d[idx].Pos[1]=y; source_3d[idx].Pos[2]=z; } void set_source_vel(int idx,ALfloat x,ALfloat y,ALfloat z) { source_3d[idx].Vel[0]=x; source_3d[idx].Vel[1]=y; source_3d[idx].Vel[2]=z; } void set_source_rgb(int idx,ALfloat r,ALfloat g,ALfloat b) { source_3d[idx].rgb[0]=r; source_3d[idx].rgb[1]=g; source_3d[idx].rgb[2]=b; } SF3dVector F3dVector ( GLfloat x, GLfloat y, GLfloat z ) { SF3dVector tmp; tmp.x = x; tmp.y = y; tmp.z = z; return tmp; } SF3dVector AddF3dVectors (SF3dVector* u, SF3dVector* v) { SF3dVector result; result.x = u->x + v->x; result.y = u->y + v->y; result.z = u->z + v->z; return result; } void AddF3dVectorToVector ( SF3dVector * Dst, SF3dVector * V2) { Dst->x += V2->x; Dst->y += V2->y; Dst->z += V2->z; } /***************************************************************************************/ CCamera::CCamera() { //Init with standard OGL values: Position = F3dVector ( 0.0, 2.0, 0.0); set_listener_pos(Position.x,Position.y,Position.z); ViewDir = F3dVector( 0.0, -1.0, 0.0); ViewDirChanged = true; //Only to be sure: RotatedX = RotatedY = RotatedZ = 0.0; } void CCamera::GetViewDir( void ) { SF3dVector Step1, Step2; //Rotate around Y-axis: Step1.x = cos( (RotatedY + 90.0) * PIdiv180); Step1.z = -sin( (RotatedY + 90.0) * PIdiv180); //Rotate around X-axis: double cosX = cos (RotatedX * PIdiv180); Step2.x = Step1.x * cosX; Step2.z = Step1.z * cosX; Step2.y = sin(RotatedX * PIdiv180); //Rotation around Z-axis not yet implemented, so: ViewDir = Step2; } void CCamera::Move (SF3dVector Direction) { AddF3dVectorToVector(&Position, &Direction ); } void CCamera::RotateZ (GLfloat Angle) { RotatedZ += Angle; ViewDirChanged = true; } void CCamera::RotateY (GLfloat Angle) { RotatedY += Angle; ViewDirChanged = true; } void CCamera::RotateX (GLfloat Angle) { RotatedX += Angle; ViewDirChanged = true; } void CCamera::Render( void ) { glRotatef(-RotatedX , 1.0, 0.0, 0.0); glRotatef(-RotatedY , 0.0, 1.0, 0.0); glRotatef(-RotatedZ , 0.0, 0.0, 1.0); glTranslatef( -Position.x, -Position.y, -Position.z ); } void CCamera::MoveForwards( GLfloat Distance ) { if (ViewDirChanged) GetViewDir(); SF3dVector MoveVector; MoveVector.x = ViewDir.x * -Distance; MoveVector.y = ViewDir.y * -Distance; MoveVector.z = ViewDir.z * -Distance; AddF3dVectorToVector(&Position, &MoveVector ); set_listener_pos(Position.x,Position.y,Position.z); } void CCamera::StrafeRight ( GLfloat Distance ) { if (ViewDirChanged) GetViewDir(); SF3dVector MoveVector; MoveVector.y = -ViewDir.x * -Distance; MoveVector.x = ViewDir.y * -Distance; MoveVector.z = 0.0; AddF3dVectorToVector(&Position, &MoveVector ); } void reshape(int x, int y) { if (y == 0 || x == 0) return; //Set a new projection matrix glMatrixMode(GL_PROJECTION); glLoadIdentity(); //Angle of view:40 degrees //Near clipping plane distance: 0.5 //Far clipping plane distance: 20.0 gluPerspective(40.0,(GLdouble)x/(GLdouble)y,0.1, 100.0); glMatrixMode(GL_MODELVIEW); glViewport(0,0,x,y); } void Display(void) { int i; ALfloat direction[3]; GLfloat polar_distance,polar_angle; glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); Camera.Render(); glRotatef(-90.0, 1.0, 0.0, 0.0); glTranslatef(0.0, 8.0 , 1.0); glScalef(1.0,1.0,1.0); /* Draw reference plane */ glColor3f(1.0,1.0,1.0); glPushMatrix(); glTranslatef(0.0, 0.0 ,0.0); glBegin(GL_LINES); for (int xc = 0; xc <= 100; xc++) { glVertex3f( -50.0 + xc , 50.0, 0.0); glVertex3f( -50.0 + xc , -50.0, 0.0); } for (int yc = 0; yc <= 100; yc++) { glVertex3f( 50.0, -50.0 + yc, 0.0 ); glVertex3f( -50.0, -50.0 + yc, 0.0 ); } glEnd(); glPopMatrix(); if ( LastUpdate != 0 ) { float fSecs = static_cast(GetTime() - LastUpdate)/1000.0; /* Calculation of 3D position of the sound source Helicopter - circular path around the origin Radar - rotate around the origin Van - moving headon to listener - moving left/right in front of listener - path around the origin */ source_3d[0].angle+= fSecs; if ( source_3d[0].angle > 360.0 ) source_3d[0].angle -= 360.0; source_3d[1].angle -= fSecs*100.0; if ( source_3d[1].angle < -360.0 ) source_3d[1].angle += 360.0; source_3d[2].Pos[1] += source_3d[2].Vel[1] * fSecs; if ( source_3d[2].Pos[1] < -99.0 ) { source_3d[2].Pos[1] = 99.0; }; source_3d[3].Pos[0]+= source_3d[3].Vel[0] * fSecs; if ( fabs(source_3d[3].Pos[0]) > 101.0 ) { if ( source_3d[3].Pos[0] > 0.0 ) source_3d[3].Vel[0] = -fabs(source_3d[3].Vel[0]); else source_3d[3].Vel[0] = fabs(source_3d[3].Vel[0]); }; source_3d[4].angle -= fSecs * 0.01; if ( source_3d[4].angle < -360.0 ) source_3d[4].angle += 360.0; }; LastUpdate = GetTime(); for (i=0; i