Sign in to follow this  

compilation probs: OGRE/bullet (abstract types and virtual functions)

This topic is 2662 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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&) const


Player.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_*/

Share this post


Link to post
Share on other sites

This topic is 2662 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this