You are here:

C++/Opengl C++ in Linux - Animation/evolve not working

Advertisement


Question
Hi Ralph, I am very new to C++/opengl and I have been having alot of trouble with my C++ code for the Linux OS. What i need to do is Produce the basic animation for a golf shot, whereby the user defines the angles and magnitude for the shot. The class golf is defined in a seperate file (golf.c++) and then run in golftest.c++ . My problem is that the actual animation part is not working, i print out the velocities and XYZ and i can see that in theory the golf ball is moving but the animation of the shape (sphere) remains stationary at (0,0,0). Any help you could give on solving this would be greatly appreciated. Also how could i go about adding a 3D camera to the scene?

Code for golf.c++

#include <iostream.h>
#include <math.h>
#include <stdlib.h>
float myrand(){return((1.0*rand())/RAND_MAX);}

class golf{      //define the object/class

public:
   float getx();float gety();float getz();
   float getvx();float getvy();float getvz();
   golf(float ,float, float);
   void  evolve(float t);
    bool inplay();
    static void movepin();
  private:float x,y,z,vx,vy,vz,time;   
  static float g,pinx,pinz,c_o_r;
};

//Class Variables

float golf::g=0.1;
float golf::pinx=0.5;
float golf::pinz=0.5;
float golf::c_o_r=0.5;

float golf::getx(){ return x; }
float golf::gety(){ return y; }
float golf::getz(){ return z; }
float golf::getvx(){ return vx; }
float golf::getvy(){ return vy; }
float golf::getvz(){ return vz; }

float pi = 3.14259;

void  golf::movepin()
{
 pinx = myrand();
 pinz = myrand();

}

golf::golf(float anglex, float anglez,  float mag )
{
    x=0,y=0,z=0, time=0;
       // given magnitude and anglex and angle y
      // assign to vx , vy and vz
  vx = mag*cos(anglez*(pi/180))*cos(anglex*(pi/180));
  vy = mag*cos(anglez*(pi/180))*sin(anglex*(pi/180));
  vz = mag*cos((3.14/2)-anglez*(pi/180));

}


bool golf::inplay()
{
    if(x>1 || x<-1) return false;
  if(y>1 || y<-1) return false;
  if(z>1 || z<-1) return false;
 // etc
}

void golf::evolve(float delta){
    time+=delta;
    y+=vy*delta;
    x+=vx*delta;
    z+=vz*delta;
     //Print out xyz and velocities
    cout << "x= " << x << " y= " << y << " z = " << z << "\n";
    cout << "vx= " << vx << "vy= " << vy << " vz = " << vz << "\n";      
    vz+=-g*delta;
    if(z<0)
      {
        vz=-1*c_o_r; // bounce
        z=.001; // make sure ball is above ground
      }
    inplay();
}

code for golftest.c++

#include "golf.c++"
#include <iostream.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <GL/glut.h>


void init(void){}

//Global variables

   float angle1=45;   //set default values for angle and mag for testing purposes
     float angle2=45;
     float mag=5;
     char c='#';
  float delta=0.01;

//initiate gball

golf gball = golf(0,0,0);

void keyboard(unsigned char key, int x, int y)
{
 
     if(key!='f')
  {
     cout << "processing " << key << "\n" ; //check that key press has registered
    switch(key)
      {
  case('s'):
    angle1+=5; if(angle1>180)angle1=180;
    break;
  case('a'):
    angle1-=5; if(angle1<0)angle1=0;
    break;
  case('w'):     
    angle2+=5; if(angle2>90)angle2=90;
    break;
  case('x'):
    angle2-=5; if(angle2<0)angle2=0;
    break;
  case('o'):
    mag+=0.1;
    break;
  case('p'):
    mag+=-0.1; if(mag<0)mag=0;
    break;
  case('m'):
    golf::movepin();
    break;
      }
     //print chages made to angles and magnitude
    cout << "angle1 " << angle1 << " angle2 " << angle2 << " magnitude " << mag << "\n";
      
  }
     else
  {
         cout << "fire\n";   //test whether this part of code is reached
         golf gball = golf(angle1,angle2,mag);
         float time =0;
         while(gball.inplay())
         {      
        gball.evolve(delta);   
        glutPostRedisplay();   
     
         }   
  }
}


void display (void)
{
     glClear(GL_COLOR_BUFFER_BIT);
    glLoadIdentity();
    glColor3f (1.0, 1.0, 1.0);
  glTranslatef(gball.getx(),gball.gety(),gball.getz());
  glutSolidSphere(0.01,10,10);
  glFlush();glutSwapBuffers();
}

void anim()
{
   glutPostRedisplay();
}


int main(int argc, char * argv[])
{
  glutInit(&argc, argv);
     glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
     glutInitWindowSize (800, 800);
     glutCreateWindow (argv[0]);   
  init();    
  glutKeyboardFunc (keyboard);
  glutDisplayFunc (display);          
     glutIdleFunc(anim);
     glutMainLoop();
     return 0;
}


Thank you very much for any help you can give.

Matt

Answer
I am not an expert in OpenGL but it seems to me from a quick look at your code that you have two versions of an object called gball that are separate objects:

1/ The global gball defined here:

   //initiate gball
   golf gball = golf(0,0,0);

And accessed in the display function:

// Note: (void) not required for C++ for parameter-less function.
// We can just use ()
   void display (void)  
   {
       glClear(GL_COLOR_BUFFER_BIT);
       glLoadIdentity();
       glColor3f (1.0, 1.0, 1.0);
       glTranslatef(gball.getx(),gball.gety(),gball.getz());


2/ A local automatic object defined and used for all updates in the keyboard function:

   else
   {
       cout << "fire\n"; //test whether this part of code is reached
       golf gball = golf(angle1,angle2,mag);  // _NOT_ global gball

This second object is allocated on the stack frame of function calls to keyboard lives only for as long as a function call to the keyboard function, and is only visible to code of the keyboard function. In fact the C++ scope rules mean that it only lives for the duration of (and is visible within) the block in which it is defined, in this case the else block from:

   else
   {
       cout << "fire\n";   //test whether this part of code is reached
       golf gball = golf(angle1,angle2,mag);  // local gball visible
         // from here...
   // ...

         glutPostRedisplay();
       }
   // ...to here
   } // local gball destroyed here

Thus the gball you are updating in keyboard is not the global one that you are using in display. The global gball is never therefore updated and always has its initial values of 0.0, 0.0, 0.0.

Now the way you are initialising the gball objects is not efficient, you are creating a temporary golf object using the golf(0,0,0) (for global gball), which is then copied to the gball golf object and finally the temporary golf object is destroyed. The more usual (and efficient) way to define and initialise an object is to call the constructor directly on the object name:

   golf gball(0,0,0);

The only exception is for default construction which takes no parameters and you may think would be defined like so:

   Class_type object();  // ### Does NOT default construct object

But this looks to C++ like a function declaration of a function called object taking no parameters and returning a Class_type object, and in C++ (I think inherited from C) anything that looks like a function declaration is taken to be one - doh! The way around this is to simply not include the parentheses, the (), thus:

   Class_type object;  // Default constructs object

Now there may be other problems with your code but I do not have time to fully debug other people's code for them. However I hope these few points will help you move forward.  

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.