Solved

OpenGl

Posted on 2000-05-01
3
1,073 Views
Last Modified: 2012-06-21
ONLY OPENGL CODE WILL BE ACCEPTED!!!

I need a sample program of a bitmap that looks like a ball thrown up. When
gravity overpowers the throw the ball should fall down. Please do not not use glut.h use only gl.h or glu.h I will assign extra 50 points if the program works!!!
0
Comment
Question by:TryHarder
3 Comments
 

Expert Comment

by:slavik022300
Comment Utility
If you want to I can write it with glut.h (for windows) if you assign the extra 50 points.
0
 

Accepted Solution

by:
gholami earned 50 total points
Comment Utility
the points are not worth the value of this, but I will post it anyways.
before you compile you should have a file called balled.cfg and should contain these values

20
1.00
0.03
-9.8

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <gl\gl.h>
#include <gl\glu.h>

#include <math.h>
#include <time.h>
#include <stdio.h>
//-------------------------------------------------------------------
// General definitions and classes.
typedef long Bool;
typedef long Int;
typedef float Float;

typedef unsigned char      UInt8;
typedef signed char            Int8;

typedef unsigned short      UInt16;
typedef short                  Int16;

typedef unsigned long      UInt32;
typedef long                  Int32;

typedef char*                  PStr;              // pointer to a string
typedef const char *      PConstStr;          // pointer to a constant string

typedef UInt8*                  PUInt8;
typedef Int8*                  PInt8;

typedef UInt16*                  PUInt16;
typedef Int16*                  PInt16;

typedef UInt32*                  PUInt32;
typedef Int32*                  PInt32;

#define True 1
#define False 0
#define Null 0

// Toast pointer based allocations in one fell swoop.
#define NUKE(x) if(x != 0) {delete x; x=0;}

// Platform specific debug info.
#ifdef _DEBUG
      #define __DEBUG
#endif //DEBUG

// CDECL is used for functions that take variable arguments.
#ifndef CDECL
      #define CDECL __cdecl
#endif

// APIDECL is used on global public functions.
#ifndef APIDECL
      #define APIDECL __stdcall
#endif


// Not used yet... but soon.
#define EXPORT

//-------------------------------------------------------------------
// PointI2D & PointUI2D: Copywrite 18/07/97
// TBI - Write wrapper class.
typedef tagPOINT PointI2D;
typedef struct _tag_PointUI2D
{
      UInt32 x, y;
} PointUI2D;

// SizeI2D: Copywrite 18/07/97
// TBI - Write wrapper class.
typedef tagSIZE SizeI2D;

// RectI: Copywrite 18/07/97
// TBI - Write wrapper class.
typedef tagRECT RectI;

//-------------------------------------------
#define sqr( X )      ( (X) * (X) )                               // Square the X
#define PI                        3.14159265358979323846f
#define DEG2RAD(X)            (PI*(X)/180.0)      // Degrees -> Radians
#define RAD2DEG(X)            ((X)*180.0/PI)      // Radians -> Degrees
#define rnd()            ((Float)rand()*(1.0f /(Float)RAND_MAX))  // Floating point random number generator ( 0 -> 1)

// fabs: Absolute function.
//#undef abs
//#define abs(a)     ( (a) > 0 ? (a) : -(a) )

// Force sign clamping to (-1;0;1)
#define sgn(a)      ((a)<0?-1:((a)?1:0))

#ifndef max
      #define max( a, b )   ((a) > (b) ? (a) : (b))
#endif

#ifndef min
      #define min( a, b )   ((a) < (b) ? (a) : (b))
#endif

// Macro to release an object.
#define RELEASE(x) if(x != NULL) {x->Release(); x = NULL;}
// Macro to display a message box containing the given string.
#define DISPLAYMSG(x) MessageBox(NULL, x, "Planet Toast Message", MB_OK);

#define EPSILON        1e-8
#define ZERO               EPSILON
#define M_1_MAXINT       4.65661287524579692410E-10      //--->  1/(2^31-1) 1/meu maxint 32bits
#define M_1_255            (1.0 / 255.0)
#define M_1_65535   (1.0 / 65535.0)
#define M_1_65500   (1.0 / 65500.0)
#define SNAP_BIAS      (Float)(1<<19)

class SVector3D
{
public:
      SVector3D() {};
      SVector3D( Float tx, Float ty, Float tz )
      { x = tx; y = ty; z = tz; w = 1.f; }

      SVector3D( Float tx, Float ty, Float tz, Float tw )
      { x = tx; y = ty; z = tz; w = tw; }

      union {
            Float x;      // Coorinate
            Float nx;      // Normal
      };

      union {
            Float y;
            Float ny;
      };

      union {
            Float z;
            Float nz;
      };

      Float w;  // This coordinate is only used for the final transformation process. Not used by any of the vector methods.

      //-------------------------------------------
      // General utility functions.
      void Print(char *s = Null );      // Prints the vector's coordinates to the "stderr" stream.
      void Rand();                              // Randomly generates a new vector.
      inline Float DotProduct( const SVector3D &other );      // DotProduct of this vector into the other vector.
      inline void       CrossProduct( const SVector3D &a, const SVector3D &b );  // Calculates the cross product of "a" and "b", then storing it in this vector.
      inline Float Length();      // Returns the length of this vector.

      //-------------------------------------------
      // Results of these opperations are contained in "this" vector by default.
      inline Float Normalize(); // Normalizes this vector, and returns the scalar value used to normalize the vector.
      inline void      Zero( );             // Reset variables to a normal zero constant. (w = 1.f)
      inline void      Scale( Float s );  // Scale this vector by "s".
      inline void      Add( const SVector3D &other );      // Add the other vector to this vector.
      inline void      Subtract( const SVector3D &other );      // Subtract the other vector from this vector. (result is contained in this vector.)
      inline void      Combine( const SVector3D &other, Float s=1.f ); // Combine vectors with a scalar quantity.
      inline void      Lerp( const SVector3D &a, const SVector3D &b, Float fPercent );      // Linear Interpolate
      inline void      LerpW( const SVector3D &a, const SVector3D &b, Float fPercent );// Linear Interpolate with W
      inline void      RotV( const SVector3D &e, const SVector3D &p ); // Rotate this vector to the normal of e.
      inline void GetAngles( Float &fPan, Float &fPitch );            // Retrieve the angles of this vector.

      // Assignment opperator.
      const SVector3D& operator=( const SVector3D &point )
      { x = point.x; y = point.y; z = point.z; w = point.w; return *this; }

      // Math opperations.
      // Unary.
      friend SVector3D operator*( const SVector3D& ptSrc1, float fScalar );
      friend SVector3D operator+( const SVector3D& ptSrc1, const SVector3D& ptSrc2 );
      friend SVector3D operator-( const SVector3D& ptSrc1, const SVector3D& ptSrc2 );

      // Binary.
      const SVector3D& operator+=( const SVector3D& ptSrc )
      { Add( ptSrc ); return *this; }

      const SVector3D& operator-=( const SVector3D& ptSrc )
      { Subtract( ptSrc ); return *this; }

      //-------------------------------------------
      // Matrix transformation process.
//      void      Transform( const SVector3D &v, const SMatrix &a );
};

//------------------------------------------------------------------------
// Inline implementation.

//-------------------------------------------
// General utility functions.

// DotProduct of this vector into the other vector.
Float SVector3D::DotProduct( const SVector3D &other )
{
      return(x * other.x + y * other.y + z * other.z);
}

// Calculates the cross product of "a" and "b", then storing it in this vector.
void SVector3D::CrossProduct( const SVector3D &a, const SVector3D &b )
{
      x = a.y * b.z - b.y * a.z;
      y = b.x * a.z - a.x * b.z;
      z = a.x * b.y - b.x * a.y;
}

// Returns the length of this vector.
Float SVector3D::Length()
{
      return  (Float) sqrt( sqr(x) + sqr(y) + sqr(z) );
}

//------------------------------------------------------------------------
// Results of these opperations are contained in "this" vector by default.

//-------------------------------------------
// Normalizes this vector, and returns the scalar value used to normalize the vector.
Float SVector3D::Normalize()
{
      Float n, nn ;

      nn = sqr(x) + sqr(y) + sqr(z);
      if ( nn < ZERO ) return 0.0f;

      nn = (Float) sqrt(nn);
      n = 1.0f / nn;
      x *= n;
      y *= n;
      z *= n;
      return nn;
}

void SVector3D::Zero( )
{
      x = y = z = 0.f;
      w = 1.f;
}

// Scale this vector by "s".
void SVector3D::Scale( Float s )
{
      x *= s;
      y *= s;
      z *= s;
}

// Add the other vector to this vector.
void SVector3D::Add( const SVector3D &other )
{
      x += other.x;
      y += other.y;
      z += other.z;
}

// Subtract the other vector from this vector.
void SVector3D::Subtract( const SVector3D &other )
{
      x -= other.x;
      y -= other.y;
      z -= other.z;
}

// Combine vectors with a scalar quantity.
void SVector3D::Combine( const SVector3D &other, Float s)
{
  x += s * other.x;
  y += s * other.y;
  z += s * other.z;
}

// Linear Interpolate
void SVector3D::Lerp( const SVector3D &a, const SVector3D &b, Float fPercent )
{
      x = a.x*(1.f-fPercent) + b.x*fPercent;
      y = a.y*(1.f-fPercent) + b.y*fPercent;
      z = a.z*(1.f-fPercent) + b.z*fPercent;
}

// Linear Interpolate with W
void SVector3D::LerpW( const SVector3D &a, const SVector3D &b, Float fPercent )
{
      x = a.x*(1.f-fPercent) + b.x*fPercent;
      y = a.y*(1.f-fPercent) + b.y*fPercent;
      z = a.z*(1.f-fPercent) + b.z*fPercent;
      w = a.w*(1.f-fPercent) + b.w*fPercent;
}

// Rotate a quaternion vector ("p") around a normal ("e").
void SVector3D::RotV( const SVector3D &e, const SVector3D &p )
{
      Float m = (Float)sqrt( sqr( p.y ) + sqr( p.z ) ) ;
      Float im = 1.0f / m ;

      x = m * e.x + p.x * e.z ;
      y = ( -p.x * p.y * e.x  + p.z * e.y ) * im + p.y * e.z ;
      z = ( -p.x * p.z * e.x  - p.y * e.y ) * im + p.z * e.z ;
}

// Retrieve the angles of this vector.
void SVector3D::GetAngles( Float &fPan, Float &fPitch )
{
//      fPan = -(Float)atan2( x, z );
//      fPitch = 0;//(Float)atan2( sin(fPan)*z + cos(fPan)*x, y);
      double dx, dy, dz;
      dx = (double)x;
      dy = (double)y;
      dz = (double)z;
      if(dz > 0.0001f)
      {
            fPan = (Float) -atan(dx/dz);
            dz /= cos((double)fPan);
            fPitch = (Float) atan(dy/dz);
      } else if(dz < -0.0001f)
      {
            fPan = (Float) (PI-atan(dx/dz));
            dz /= cos((double)fPan-PI);
            fPitch = (Float) -atan(dy/dz);
      } else
      {
            fPan = 0.0;
            fPitch = (Float)-PI/2.f;
      }
}

// Math opperations.
inline SVector3D operator*( const SVector3D& ptSrc1, float fScalar )
{
      SVector3D ptTmp(ptSrc1);
      ptTmp.Scale( fScalar );
      return ptTmp;
}

inline SVector3D operator+( const SVector3D& ptSrc1, const SVector3D& ptSrc2 )
{
      SVector3D ptTmp(ptSrc1);
      ptTmp.Add( ptSrc2 );
      return ptTmp;
}

inline SVector3D operator-( const SVector3D& ptSrc1, const SVector3D& ptSrc2 )
{
      SVector3D ptTmp(ptSrc1);
      ptTmp.Subtract( ptSrc2 );
      return ptTmp;
}

//-------------------------------------------------------------------
// Extra tidbits...

//-------------------------------------------
// Calculates the equation of "b" to the power of "e".
Int      IPower( Int b, Int e );

//-------------------------------------------
// Prints the vector's coordinates to the "stderr" stream.
void SVector3D::Print(char *s )
{
      // If we have an informative string, then print it.
      if(s)
            fprintf(stderr, "%s\n", s);

      // Print the vector info.
      fprintf(stderr,">%12g\t%12g\t%12g\t%12g\n", (double)x, (double)y, (double)z, (double)w );
}

// Randomly generates a new vector.
void SVector3D::Rand()
{
      x = 1.f - 2.f * rnd();
      y = 1.f - 2.f * rnd();
      z = 1.f - 2.f * rnd();
}

//-------------------------------------------
// Calculates the equation of "b" to the power of "e".
Int      IPower( Int b, Int e )
{
      Int result = 1 ;

      // Loop the multiplication process for each exponent.
      while( e-- )
            result *= b ;

      return result;
}

#define MAX_TEXTURE_NAME_LENGTH 64

class CTexture
{
public:
      CTexture();
      ~CTexture();

      // Create and load the files.
      int LoadBMP(char* szFileName);
    int LoadJPG(char* szFileName, int asAlpha = 0);

      void Toast();

      void Use();

protected:
      // Generates the nesessary internal data.
      int Create(char* szFileName);

      char m_szName[MAX_TEXTURE_NAME_LENGTH];
      unsigned int m_nID;

      // Status information.
      UInt32 m_nWidth, m_nHeight;
};

char szAppName[];
float fTime=0.f, fDeltaTime=0.f;
//-------
// Stuff.
int Init();
void Shutdown();

// Draw all the scene related stuff.
void Render();
//----------------------------------
// Timer info.
LARGE_INTEGER TimerFreq;      // Timer Frequency.
LARGE_INTEGER TimeStart;      // Time of start.
LARGE_INTEGER TimeCur;            // Current time.

///////////////////////////
// BEGIN MAX
///////////////////////////

static int fullscreen;

///////////////////////////
// END MAX
///////////////////////////

// Good 'ol generic drawing stuff.
LRESULT CALLBACK SkeletonProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );

// Usefull debugger thingy.
      const int kMaxDebugMessageLength = 1024;
      void DebugOut(const char *szFormat, ...)
      {
            va_list argList;
            char szBuffer[kMaxDebugMessageLength];

            va_start(argList, szFormat);
            _vsnprintf(szBuffer, kMaxDebugMessageLength, szFormat, argList);
            va_end(argList);

            OutputDebugString(szBuffer);
      }

void ChangeDisplayMode()
{

  DEVMODE device_mode;
 
  memset(&device_mode, 0, sizeof(DEVMODE));

  device_mode.dmSize = sizeof(DEVMODE);

  device_mode.dmPelsWidth  = 640;
  device_mode.dmPelsHeight = 480;
  device_mode.dmFields     = DM_PELSWIDTH | DM_PELSHEIGHT;

  ChangeDisplaySettings(&device_mode, CDS_FULLSCREEN);

}
 
void RestoreDisplayMode()
{

  ChangeDisplaySettings(0, 0);

}

// Select the pixel format for a given device context
void SetDCPixelFormat(HDC hDC)
{

  int nPixelFormat;

      static PIXELFORMATDESCRIPTOR pfd = {
            sizeof(PIXELFORMATDESCRIPTOR),      // Size of this structure
            1,                                                // Version of this structure
            PFD_DRAW_TO_WINDOW |                  // Draw to Window (not to bitmap)
            PFD_SUPPORT_OPENGL |                  // Support OpenGL calls in window
            PFD_DOUBLEBUFFER,                        // Double buffered mode
            PFD_TYPE_RGBA,                              // RGBA Color mode
            GetDeviceCaps(hDC, BITSPIXEL),      // Want the display bit depth            
            0,0,0,0,0,0,                              // Not used to select mode
            0,0,                                          // Not used to select mode
            0,0,0,0,0,                                    // Not used to select mode
            16,                                                // Size of depth buffer
            0,                                                // Not used to select mode
            0,                                                // Not used to select mode
            PFD_MAIN_PLANE,                              // Draw in main plane
            0,                                                // Not used to select mode
            0,0,0
      };                                                      // Not used to select mode

      // Choose a pixel format that best matches that described in pfd
      nPixelFormat = ChoosePixelFormat(hDC, &pfd);
      DebugOut( "PixelFormat Selected: %d\nBPP: %d\n", nPixelFormat, GetDeviceCaps(hDC, BITSPIXEL) );

      // Set the pixel format for the device context
      SetPixelFormat(hDC, nPixelFormat, &pfd);
}

void ChangeSize( GLsizei w, GLsizei h )
{
      // Prevent a divide by Zero
      if( h == 0 )
            h = 1;

      // Set viewport to our dimensions.
      glViewport( 0, 0, w, h);
}

GLsizei g_w, g_h;
int bReady;

// Good ol' creation code.
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
      // Say we're not ready to render yet.
      bReady = 0;

      // Setup the window class.
      WNDCLASS wc;
      HWND hWnd;
      wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
      wc.lpfnWndProc      = (WNDPROC)SkeletonProc;
      wc.cbClsExtra = 0;
      wc.cbWndExtra = 0;
      wc.hInstance = hInstance;
      wc.hIcon = NULL;
      wc.hCursor = LoadCursor( NULL, IDC_ARROW );

      wc.hbrBackground = NULL;
      wc.lpszMenuName = NULL;
      wc.lpszClassName = szAppName;

      if (strstr(lpCmdLine, "-fullscreen"))
            fullscreen = 1;
      else
            fullscreen = 0;

      // Announce it to the Microsloth OS.
      if( RegisterClass( &wc ) == 0)
      {
            MessageBox( NULL, "Failed to register the idiot window class, right before creating the window.", "Fatal Blow", MB_OK | MB_ICONERROR );
            return FALSE;      // Failed to create window, so just quit right away.
      }

      // Make it go.......
      if( fullscreen == 0 )
      { // Default startup mode.
            hWnd = CreateWindow(
                        szAppName,
                        szAppName,
                        WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
                        CW_USEDEFAULT, CW_USEDEFAULT,
                        640, 480,
                        NULL, NULL,
                        hInstance,
                        NULL );
      } else
      { // alternate startup mode, to bring up full screen.
            hWnd = CreateWindow(
                        szAppName,
                        szAppName,
                        WS_POPUP,
                        0, 0,
                        640, 480,
                        NULL, NULL,
                        hInstance,
                        NULL );
      }

      if( hWnd == NULL )
      {
            MessageBox( NULL, "Failed to create the effect window.", "Fatal Blow", MB_OK | MB_ICONERROR );
            return FALSE;      // Failed to create window, so just quit right away.
      }

      // Make it visible...
      ShowWindow( hWnd, SW_SHOW );
      UpdateWindow( hWnd );

      // Reset the timer stuff.
      QueryPerformanceFrequency(&TimerFreq);
      QueryPerformanceCounter(&TimeStart);


      // Prepare the scene for rendering.
      if( Init() == 0 )
      {
            MessageBox( hWnd, "Failed to initialize the visual effect.", "Fatal Blow", MB_OK | MB_ICONERROR );
            return FALSE;      // Failed init, so just quit right away.
      }

      // We're now ready.
      bReady = 1;

      // Usual running around in circles bit...
      int bGotMsg;
      MSG  msg;
      PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE );
    while( WM_QUIT != msg.message  )
    {
            // Use PeekMessage() if the app is active, so we can use idle time to
            // render the scene. Else, use GetMessage() to avoid eating CPU time.
            bGotMsg = PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE );

            if( bGotMsg )
        {
                  // Translate and dispatch the message
                  TranslateMessage( &msg );
                  DispatchMessage( &msg );
        }
            else
            {
                  InvalidateRect( hWnd, NULL, FALSE );
            }
    }

      // Not ready to render anymore.
      bReady = 0;

      // Nuke all applicable scene stuff.
      Shutdown();

      return msg.wParam;
}

// Stupid usual callback window proc message spud gun.
LRESULT CALLBACK SkeletonProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
      // Keep drawing stuff around.
      static HGLRC hRC;
      static HDC hDC;

      switch( uMsg )
      {
      case WM_CREATE:
            // Remember our mSloth drawing context.
            hDC = GetDC( hWnd );

            if( fullscreen )
            {
              ChangeDisplayMode();
            }

          // Select our precious pixel format.
            SetDCPixelFormat( hDC );

            // Yeppers, make something that OpenGL understands.
            hRC = wglCreateContext( hDC );
            wglMakeCurrent( hDC, hRC );
            break;

      case WM_KEYDOWN:
            if (wParam == VK_ESCAPE) {
              DestroyWindow(hWnd);
            }
            break;
 
      case WM_DESTROY:
            wglMakeCurrent( hDC, NULL );
            wglDeleteContext( hRC );

            if( fullscreen )
            {
              RestoreDisplayMode();
            }

            PostQuitMessage( 0 );
            break;

      case WM_SIZE:
            g_w = LOWORD(lParam);
            g_h = HIWORD(lParam);
            ChangeSize( g_w, g_h );
            break;

      case WM_PAINT:
            if( bReady )
            {
                  // Get the current time, and update the time controller.
                  QueryPerformanceCounter(&TimeCur);
                  float fOldTime = fTime;
                  fTime = (float)((double)(TimeCur.QuadPart-TimeStart.QuadPart)/(double)TimerFreq.QuadPart);
                  fDeltaTime = fTime - fOldTime;

                  // Draw all the scene related stuff.
                  Render();

                  // Make it all visible at once!
                  SwapBuffers( hDC );

                  // We actually did something with this rect, so announce it to the mSloth OS.
                  ValidateRect( hWnd, NULL );
            }
            break;

      default:
            return DefWindowProc( hWnd, uMsg, wParam, lParam );
      }

      return 0;
}


//----------------------------------------
// Usefull debugger thingy.
void DebugOut(const char *szFormat, ...);
//----------------------------------------

// Change your App Name.
char szAppName[] = "Balled";

// Timer info.  Very useful for keeping animated stuff in sync on different computers.
extern float fTime, fDeltaTime;

// Current window dimensions.
extern GLsizei g_w, g_h;

GLUquadricObj *myQuadric;

#define MAX_SPHERES (128)

static float collideLoss;
static float airFriction;
static float gravityStrength;

struct Sphere {
      float radius;
      float r, g, b;
      float mass;
      SVector3D pos;
      SVector3D vel;      

      void BounceAbout(SVector3D n);
} sphereList[MAX_SPHERES+1];
int numSpheres;
//index MAX_SPHERES of spherelist is the enclosing sphere

void SetupMySpheres(void);
void AdvanceSpheres(float dTime);
void DrawSpheres(void);
int ClosingIn(Sphere *s, Sphere *t);

// Startup Stuff.
int Init()      // Called right after the window is created, and OpenGL is initialized.
{
      float ambient[4], diffuse[4], position[4];

      // Reset the matrix to something we know.
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      float x = (float)g_w/(float)g_h; // Correct the viewing ratio of the window in the X axis.
      gluPerspective(90.0f, x, 1.0f, 150.0f);

      // Reset model view matrix stack.
      glMatrixMode( GL_MODELVIEW );
      glLoadIdentity();
      gluLookAt(30.0f, 20.0f, 30.0f,
                  0.0f, 0.0f, 0.0f,
                  0.0f, 1.0f, 0.0f);      

      glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
      
      glEnable(GL_CULL_FACE);
      glCullFace(GL_BACK);

      glEnable(GL_DEPTH_TEST);

      glEnable(GL_COLOR_MATERIAL);

      glEnable(GL_LIGHTING);

      ambient[0]=0.3f;
      ambient[1]=0.3f;
      ambient[2]=0.3f;
      ambient[3]=1.0f;

      glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);

      diffuse[0]=1.0f;
      diffuse[1]=1.0f;
      diffuse[2]=1.0f;
      diffuse[3]=1.0f;

      position[0]=1.0f;
      position[1]=1.0f;
      position[2]=0.0f;
      position[3]=0.0f;

      glLightfv(GL_LIGHT0, GL_POSITION, position);      
      glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);      
      glEnable(GL_LIGHT0);      

      //set up our spheres
      SetupMySpheres();

      myQuadric=gluNewQuadric();
      gluQuadricDrawStyle(myQuadric, GLU_FILL);

      // If everything went well, then return 1.
      // Returning 0 will cause the program to quit right away.
      return myQuadric!=0;
}

void Shutdown() // Called right after the window is destroyed.
{
      gluDeleteQuadric(myQuadric);
}

// Draw all the scene related stuff.
void Render()
{
      float dTime, dTimeLeft;
      glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

      dTimeLeft=fDeltaTime;
      while(dTimeLeft>EPSILON) {
            if(dTimeLeft>0.05) {
                  dTime=0.05;                  
            } else {
                  dTime=dTimeLeft;
            }      
            dTimeLeft-=dTime;
            AdvanceSpheres(dTime);
      }
      
      DrawSpheres();      
}

void SetupMySpheres(void) {
      FILE *file;
      int num=0;
      float angle, dist;

      collideLoss=0.995f;
      airFriction=0.01f;
      gravityStrength=-9.8f;

      file=fopen("balled.cfg", "rt");
      fscanf(file, "%d%f%f%f", &num, &collideLoss, &airFriction, &gravityStrength);
      fclose(file);

      if(num>MAX_SPHERES)
            num=MAX_SPHERES;

      srand((unsigned)time(NULL));


      for(numSpheres=0; numSpheres<num; numSpheres++) {
            sphereList[numSpheres].radius=(float)(rand()%7)+1;
            sphereList[numSpheres].r=((float)(rand()%256))/255.0f;
            sphereList[numSpheres].g=((float)(rand()%256))/255.0f;
            sphereList[numSpheres].b=((float)(rand()%256))/255.0f;
            angle=((float)(rand()%360))*3.14159f/180.0f;
            dist=(float)(rand()%30);
            sphereList[numSpheres].pos.x=dist*cos(angle);
            sphereList[numSpheres].pos.y=0.0f;
            sphereList[numSpheres].pos.z=dist*sin(angle);
            sphereList[numSpheres].vel.x=0.0;
            sphereList[numSpheres].vel.y=0.0;
            sphereList[numSpheres].vel.z=0.0;
            sphereList[numSpheres].mass=pow(sphereList[numSpheres].radius,3.0f);
      }
      numSpheres=num;

      sphereList[MAX_SPHERES].radius=50.0f;
      sphereList[MAX_SPHERES].r=0.5f;
      sphereList[MAX_SPHERES].g=0.2f;
      sphereList[MAX_SPHERES].b=0.7f;
      sphereList[MAX_SPHERES].pos.x=0.0f;
      sphereList[MAX_SPHERES].pos.y=0.0f;
      sphereList[MAX_SPHERES].pos.z=0.0f;

}

void AdvanceSpheres(float dTime) {
      int i, j;
      Sphere *s, *t;
      SVector3D g(0.0f, gravityStrength, 0.0f), norm, v1i, v1f, v2i, v2f, rel, v1p, v2p;
      float dist;

      for(i=0; i<numSpheres; i++) {
            s=sphereList+i;

            s->pos=s->pos + s->vel*dTime + g*(dTime*dTime*0.5f);                        
            //a little air resistance
            s->vel=s->vel*exp(-dTime*airFriction);
            s->vel=s->vel + g*dTime;            
      }

      //check for collisions with big sphere
      for(i=0; i<numSpheres; i++) {
            s=sphereList+i;
            
            dist=s->pos.Length();
            dist+=s->radius;

            if(dist>=sphereList[MAX_SPHERES].radius) {
                  //collision.  reflect vel about norm
                  norm=s->pos;

                  if(norm.DotProduct(s->vel)>0.0f) {
                        s->BounceAbout(norm);            
                        //lose some energy in the collision
                        s->vel.Scale(collideLoss);
                  }
            }
      }
      //check for ball-ball collisions
      for(i=0; i<numSpheres; i++) {
            s=sphereList+i;
            for(j=i+1; j<numSpheres; j++) {
                  t=sphereList+j;
                  //does s collide with t?
                  dist=(s->pos-t->pos).Length();
                  if(dist<=(s->radius+t->radius)) {
                        //collision.
                        //compute relative to t, v=0;
                        if(ClosingIn(s, t)) {
                              //collision normal... things happen relative to this
                              norm=t->pos-s->pos;
                              norm.Normalize();

                              //break down the speeds into components along
                              //the normal, and 'the rest'
                              v1i=norm*s->vel.DotProduct(norm);
                              v2i=norm*t->vel.DotProduct(norm);
                              v1p=s->vel-v1i;
                              v2p=t->vel-v2i;
                              rel=v2i;
                              v1i=v1i-rel;
                              //v2i is zero
                              
                              //got this momentum collision thing
                              //out of a physics text
                              v1f=v1i*((s->mass-t->mass)/(s->mass+t->mass));
                              v2f=v1i*((2.0f*s->mass)/(s->mass+t->mass));                              
                              
                              //make em relative to t
                              v1f=v1f+rel;
                              v2f=v2f+rel;
                              //lose some energy in the collision
                              v1f.Scale(collideLoss);
                              v2f.Scale(collideLoss);
                              //add in the part that didnt change
                              s->vel=v1p+v1f;
                              t->vel=v2p+v2f;                        
                        }
                  }
            }
      }
}

void DrawSpheres(void) {
      int i;
      
      gluQuadricOrientation(myQuadric, GLU_OUTSIDE);

      for(i=0; i<numSpheres; i++) {
            glColor3f(sphereList[i].r,
                        sphereList[i].g,
                        sphereList[i].b);            

            glPushMatrix();
                  glTranslatef(sphereList[i].pos.x,
                                    sphereList[i].pos.y,
                                    sphereList[i].pos.z);
                  gluSphere(myQuadric, sphereList[i].radius, 12, 6);
            glPopMatrix();
      }

      //draw the big sphere
      glColor3f(sphereList[MAX_SPHERES].r,
                        sphereList[MAX_SPHERES].g,
                        sphereList[MAX_SPHERES].b);            
      gluQuadricOrientation(myQuadric, GLU_INSIDE);
      gluSphere(myQuadric, sphereList[MAX_SPHERES].radius, 24, 12);      
      
}

void Sphere::BounceAbout(SVector3D n) {
      float len;
      
      vel.Scale(-1.0f);

      n.Normalize();
      len=vel.DotProduct(n);
      n=n*len;

      vel+=(n-vel)*2.0f;
}

int ClosingIn(Sphere *s, Sphere *t) {
      //are they heading toward each other?
      SVector3D delta;

      delta=s->pos-t->pos;

      //from t to s      
      if(delta.DotProduct(t->vel)>0.0f)
            return 1;

      //from s to t      
      if(delta.DotProduct(s->vel)<0.0f)
            return 1;

      return 0;
}

if you want me to e-mail you the files e-mail me first
compr0@hotmail.com

0
 

Author Comment

by:TryHarder
Comment Utility
gholami, Sorry for not responding. Just got home from a vacation trip. Getting back to what you wrote. My friend showed me a MUCH simpler and much smaller version of this task. I appreciate your help in wring it. I am raising the points to 25 and assigning them to you. Thank you once again.
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now