   compilation probs: OGRE/bullet (abstract types and virtual functions)
  I'm new and I am trying to compile some sample code that uses OGRE and bullet.  I think I have done everything correctly as far as making sure all dependencies are taken care of, but for some reason I can't get this to compile.  The problems are mainly coming from this file (Player.h).  I fixed a couple of errors I got, but there are still others.  Although I modified a couple of things to fix a couple of errors, I am always hesitant to change code that is supposed to work as is.  This is part of a tutorial, and it's a bit frustrating that I can't even compile the code and get to real part of the tutorial.  I suppose getting code to compile has merit too.  Any help would be greatly appreciated. Here is the error message I get when attempting to compile.In file included from MyFrameListener.h:19,  from Application.cpp:2:Player.h: In member function ‘virtual void Player::move(float, float, float)’:Player.h:274: error: cannot declare variable ‘myCback’ to be of abstract type ‘AllRayResultCallback’Player.h:13: note:   because the following virtual functions are pure within ‘AllRayResultCallback’:/usr/local/include/BulletCollision/CollisionDispatch/btCollisionWorld.h:230: note: virtual btScalar btCollisionWorld::RayResultCallback::addSingleResult(btCollisionWorld::LocalRayResult&, bool)Player.h:275: error: no matching function for call to ‘btCollisionWorld::rayTest(btVector3&, btVector3&, AllRayResultCallback&, int)’/usr/local/include/BulletCollision/CollisionDispatch/btCollisionWorld.h:397: note: candidates are: virtual void btCollisionWorld::rayTest(const btVector3&, const btVector3&, btCollisionWorld::RayResultCallback&) constPlayer.h:#ifndef PLAYER_H#define PLAYER_H#include <btBulletCollisionCommon.h>#include <Ogre.h>#define BTVEC3_TO_OGREVEC3(v)btVector3(v[0], v[1], v[2])#define OGREVEC3_TO_BTVEC3(v)Vector3(v[0], v[1], v[2])struct  AllRayResultCallback : public btCollisionWorld::RayResultCallback{    AllRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld)    : m_rayFromWorld(rayFromWorld), m_rayToWorld(rayToWorld), m_closestHitFraction(1.0)    {    }    btVector3   m_rayFromWorld;    btVector3   m_rayToWorld;    btVector3   m_hitNormalWorld;    btVector3   m_hitPointWorld;    float m_closestHitFraction;  virtual btScalar AddSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)    {   if (rayResult.m_hitFraction < m_closestHitFraction)  m_closestHitFraction = rayResult.m_hitFraction;   m_collisionObject = rayResult.m_collisionObject;   if (normalInWorldSpace)   {  m_hitNormalWorld = rayResult.m_hitNormalLocal;   } else   {  ///need to transform normal into worldspace  m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal;   } m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,m_closestHitFraction);   return 1.f;    }};using namespace Ogre;class Player{public:    enum direction { FORWARD, BACKWARD, TURN_LEFT, TURN_RIGHT };    protected:    //    // OGRE    //    static const double scale = 0.002;    static const double turnSpeed = 120;    static const double forwardSpeed = 0.5;    static const double mThreshold = .1;   Vector3 lastPos, lastPos2;   Entity* charEnt;    SceneNode* charNode;    AnimationState* charCurAnim;   Entity* contactEnt;    SceneNode* contactNode;   ManualObject* debugRayObject;    SceneNode* debugRayNode;   SceneManager* mSceneMgr;   //    // bullet    //    btCollisionWorld* mColWorld;    btCylinderShape* mCylShape;    btCollisionObject* mCylColObj;   FrameEvent evt;   bool firstMove;    bool validMoveLast;   double colRayLength;    double colRayLastY;    //    // OpenAL    //    // buffer and source for our collision sound effect    ALuint alBuffer;    ALuint alSource;    public:    Player(SceneManager* sceneMgr, btCollisionWorld* btColWorld) :    mSceneMgr(sceneMgr), mColWorld(btColWorld){   firstMove = true;   validMoveLast = false;   charCurAnim = NULL;    }   virtual ~Player(){   //   // In your game, buffer deallocation should probably be   // done by some sound management class. It is placed here   // to make the code understandable. In general, you should   // not perform buffer allocation/deallocation with    // your game object instances since   // you may have a buffer shared across multiple sources.   // Sources are, on the other hand, ok.   //   alDeleteBuffers(1, &alBuffer);   alDeleteSources(1, &alSource);    }   virtual void init(){   Light* light = mSceneMgr->createLight("wootLight");   light->setType(Light::LT_POINT);   light->setPosition(5.0, 12.0, 0.0); light->setCastShadows(true);   light->setSpecularColour(0.1, 0.1, 0.1);   light->setDiffuseColour(0.35, 0.35, 0.35); //   // create a ninja   //   charEnt = mSceneMgr->createEntity("Robot", "ninja.mesh");   //charEnt->setNormaliseNormals(true);   charEnt->setCastShadows(true);   charNode = mSceneMgr->getRootSceneNode()->  createChildSceneNode("RobotNode");   charNode->attachObject(charEnt);   charNode->scale(scale, scale, scale);   charNode->setPosition(0.0, 0.0, 0.0); //   // 1.) create the shape   // 2.) create and set the collision object   // 3.) add the collision object to the collision world   //   Vector3 aabbExtents = charEnt->getBoundingBox().getHalfSize(); btVector3 cylHalfExtents(aabbExtents[0] * scale * .8, aabbExtents[1] * 0.25 * scale, aabbExtents[2] * scale * .8);   mCylShape = new btCylinderShape(cylHalfExtents); mCylColObj = new btCollisionObject();   mCylColObj->setCollisionShape(mCylShape); btTransform trans;   trans.setIdentity();   trans.setOrigin(btVector3(0.0, aabbExtents[1] * scale, 0.0));   mCylColObj->setWorldTransform(trans);   mColWorld->addCollisionObject(mCylColObj, 1, 2); //   // create our contact entity   //   contactEnt = mSceneMgr->createEntity("Contact", "Cube.mesh");   //contactEnt->setNormaliseNormals(true);   contactNode = mSceneMgr->getRootSceneNode()->  createChildSceneNode("ContactNode");   contactNode->attachObject(contactEnt);   contactNode->setPosition(0.0, 0.0, 0.0);   contactNode->scale(0.01, 0.01, 0.01); colRayLength = aabbExtents.y * scale; //   // create our ray drawing object   //   debugRayObject = new ManualObject("debugRay");    debugRayNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("debugRayNode");   MaterialPtr myManualObjectMaterial = MaterialManager::getSingleton().create("rayMaterial", "debugger");    myManualObjectMaterial->setReceiveShadows(false);    myManualObjectMaterial->getTechnique(0)->setLightingEnabled(true);    myManualObjectMaterial->getTechnique(0)->getPass(0)->setDiffuse(0,0,1,0);    myManualObjectMaterial->getTechnique(0)->getPass(0)->setAmbient(0,0,1);    myManualObjectMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(0,0,1);   debugRayObject->begin("rayMaterial", Ogre::RenderOperation::OT_LINE_LIST);    debugRayObject->position(0.0, 0.0, 0.0);   debugRayObject->position(0.0, colRayLength, 0.0);   debugRayObject->end();   debugRayNode->attachObject(debugRayObject);   //   // Load up our wave file into the buffer   //   ALenum format;   ALsizei size;   ALvoid* data;   ALfloat freq;//   // if you have multiple characters using the same sound effect, the    // buffer generation and references should be kept somewhere that is accessible   // by all game objects. I would recommend creating a singleton sound manager class.   //   alGenBuffers(1, &alBuffer); //data = alutLoadMemoryFromFile((ALbyte*)"media/sound/smack.wav", &format, &size, &freq);   data = alutLoadMemoryFromFile("media/sound/smack.wav", &format, &size, &freq);   alBufferData(alBuffer, format, data, size, (ALsizei)freq); alGenSources(1, &alSource); if(alGetError() != AL_NO_ERROR) {  cout << "could generate AL buffer and/or source" << endl;  exit(1);   }   // bind our source to buffer   alSourcei (alSource, AL_BUFFER, alBuffer);   // set some source options   alSourcef(alSource, AL_PITCH, 1.0);   alSourcef(alSource, AL_GAIN, 1.0);   alSourcei(alSource, AL_LOOPING, false);    }    virtual bool validMove(float curY){   if (firstMove) return true;   return abs(colRayLastY - curY) < mThreshold;    }    virtual void changeAnimation(const String& name, bool loop=true){   if (charCurAnim)  charCurAnim->setEnabled(false);   AnimationState* animState = charEnt->getAnimationState(name);   animState->setLoop(loop);   animState->setEnabled(true);   charCurAnim = animState; charCurAnim->addTime(evt.timeSinceLastFrame);    }    virtual void setPosition(float x, float y, float z)    {   Vector3 aabbExtents = charEnt->getBoundingBox().getHalfSize(); // update the character and debug ray   charNode->setPosition(x, y, z);   debugRayNode->setPosition(x, y, z); // update the collision volume   btTransform trans;   trans.setIdentity();   trans.setOrigin(btVector3(x, y + aabbExtents[1] * scale, z));   mCylColObj->setWorldTransform(trans);    }    virtual void move(float x, float y, float z)    {   // construct ray   btVector3 from, to;   from.setValue(x, y + colRayLength, z);   to.setValue(x, 0.0, z); // perform ray test   AllRayResultCallback myCback(from, to);   mColWorld->rayTest(from, to, myCback, 2); lastPos = charNode->getPosition();   if (validMove(myCback.m_hitPointWorld[1])) {  changeAnimation("Walk");    contactNode->setPosition(myCback.m_hitPointWorld[0], myCback.m_hitPointWorld[1],myCback.m_hitPointWorld[2]  );    double diff = myCback.m_hitPointWorld[1];  setPosition(x, diff, z);    colRayLastY = myCback.m_hitPointWorld[1];   } else {  changeAnimation("Idle2");   } firstMove = false;    }    virtual void getPosition(float& x, float& y, float& z)    {   const Vector3 pos = charNode->getPosition();   x = pos[0]; y = pos[1]; z = pos[2];    }    virtual void move(direction dir) {   float forwardDelta = evt.timeSinceLastFrame * forwardSpeed;   float turnDelta = evt.timeSinceLastFrame * turnSpeed;   float pos[3];   getPosition(pos[0], pos[1], pos[2]);//const Quaternion& orient = charNode->getWorldOrientation();   const Quaternion& orient = charNode->_getDerivedOrientation();   Vector3 zAxis = orient.zAxis();    Quaternion rot;    switch (dir) {  case FORWARD: // hes facing down the negative Z so we need to negate the displacement move(pos[0] - zAxis[0] * forwardDelta, pos[1] - zAxis[1] * forwardDelta, pos[2] - zAxis[2] * forwardDelta); break;  case BACKWARD: move(pos[0] + zAxis[0] * forwardDelta, pos[1] + zAxis[1] * forwardDelta, pos[2] + zAxis[2] * forwardDelta); break;  case TURN_LEFT: rot = Quaternion(Degree(turnDelta), Vector3(0.0, 1.0, 0.0)); charNode->rotate(rot, SceneNode::TS_LOCAL); break;  case TURN_RIGHT: rot = Quaternion(Degree(-turnDelta), Vector3(0.0, 1.0, 0.0)); charNode->rotate(rot, SceneNode::TS_LOCAL); break;  }    } virtual void updateFrameBegin(const FrameEvent& evt) {  this->evt = evt;    int nManifolds = mColWorld->getDispatcher()->getNumManifolds();  int nContact = 0;   // Each manifold is basically a contact surface. A manifold may  // only be created between two objects and it is possible for  // multiple manifolds to exist for a given pair.  for (int i = 0; i < nManifolds; ++i) {  btPersistentManifold* contactManifold = mColWorld->  getDispatcher()->getManifoldByIndexInternal(i);  btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());  btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());  if (obA == mCylColObj || obB == mCylColObj) nContact += contactManifold->getNumContacts();   } //cout << "num contacts: " << nContact << endl;   if (nContact > 0) {  //  // play our sound effect if not already playing  //  ALint state;  alGetSourcei(alSource, AL_SOURCE_STATE, &state);  if (state != AL_PLAYING) { alSourcePlay(alSource);  }  setPosition(lastPos[0], lastPos[1], lastPos[2]);   }   } virtual void updateFrameEnd(const FrameEvent& evt) {  // Switch back to the idle animation after the frame has been  // drawn.  changeAnimation("Idle2");   }};#endif /*PLAYER_H_*/
  Your struct defines AddSingleResult, yet it should be addSingleResult instead.   