Solved

OpenGl

Posted on 2000-05-01
3
1,074 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
ID: 2769113
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
ID: 2771678
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
ID: 2807282
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

911 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

16 Experts available now in Live!

Get 1:1 Help Now