I'm trying to call a function after a ray collide with an object, I'm doing this:
void cWeapons::ray(float range, int damage, Ogre::Vector3 origin, Ogre::Vector3 direction, bool mode)
{
Ogre::Vector3 start = origin;
Ogre::Vector3 end = origin + direction * range;
OgreNewt::BasicRaycast::BasicRaycastInfo info;
// normalized screen coords in [0,1]
OgreNewt::BasicRaycast* verticalRay = new OgreNewt::BasicRaycast(cPhysicsInterface::getSingleton().getNewtWorld(),start,end,false);
info = verticalRay->getFirstHit();
if (info.mBody)
{
//check if bullet hit the player that shoot it
((cEntityGraphics*)info.mBody->getUserData())->setBodyBehavior(info.mBody,damage,mode);
return;
}
}
This is the signature of the class that has the function i want to call:
class cEntityGraphics:public Ogre::Any
{
public:
//Constructor
cEntityGraphics();
...
//Set Functions
virtual void setBodyBehavior(cEntity *entity, int damage, bool mode);
...
~cEntityGraphics();
};
This is the error i got:
1>------ Build started: Project: Dark Future, Configuration: Debug Win32 ------
1>Compiling...
1>cWeapons.cpp
1>c:\ogrenew\dark future\cweapons.cpp(18) : error C2440: 'type cast' : cannot convert from 'const Ogre::Any' to 'cEntityGraphics *'
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>c:\ogrenew\dark future\cweapons.cpp(18) : error C2227: left of '->setBodyBehavior' must point to class/struct/union/generic type
1>Build log was saved at "file://c:\ogrenew\Dark Future\Dark Future\Debug\BuildLog.htm"
1>Dark Future - 2 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
What I'm doing wrong? How can i call a function of the collideable object?
This worked with the old OgreNewt.
Ok i fixed the problem above but now when the ray detects a collision gives me a memory error in runtime, here is the code:
cPlayerGraphics.h
#ifndef _CPLAYERGRAPHICS_H_
#define _CPLAYERGRAPHICS_H_
#include <Ogre.h>
#include "cGraphicalInterface.h"
#include "cPlayer.h"
#include "cPhysicsInterface.h"
#include "cPlayerCollisionHandler.h"
#include "cEntityGraphics.h"
#include "cPlayerFrameListener.h"
using namespace Ogre;
class cPlayerGraphics: public cEntityGraphics
{
public:
//Constructor
cPlayerGraphics();
...
virtual void setBodyBehavior(int damage, bool mode);
...
~cPlayerGraphics();
};
#endif
Here are the relevant lines from cPlayerGraphics.cpp
void cPlayerGraphics::setBodyBehavior(int damage, bool mode)
{
if (mode)
{
mMyEntity->setDamage(damage);
mMyEntity->setHitPoints(mMyEntity->getHitPoints() - damage);
if (mMyEntity->getHitPoints() <= 0)
{
mMyEntity->setIsActive(0);
}
}
}
void cPlayerGraphics::createPlayerEntity(Ogre::String entityName, Ogre::String meshName, bool castShadows, bool isVisible, Ogre::Vector3 position, Ogre::Vector3 scale, Quaternion orientation)
{
mPlayer = new cPlayer();
mPlayer->setWeight(80.0f);
mPlayer->setHitPoints(100);
cPlayerCollisionHandler * playerCollision = new cPlayerCollisionHandler(mPlayer);
mBodyNode = createNode(entityName,meshName,castShadows,isVisible,position,scale,orientation);
mPlayerController = playerCollision->createPlayerController(scale,mBodyNode);
addPlayerFrameListener(mPlayerController,playerCollision,mPlayer);
setEntity(mPlayer);
mBody = mPlayerController->getBody0();
cPhysicsInterface::getSingleton().setUserData(mBody,(Ogre::Any)this); <------
}
As you can see I'm calling the setUserData function.
Here is where I'm calling it:
void cWeapons::ray(float range, int damage, Ogre::Vector3 origin, Ogre::Vector3 direction, bool mode)
{
Ogre::Vector3 start = origin;
Ogre::Vector3 end = origin + (direction - origin);
OgreNewt::BasicRaycast::BasicRaycastInfo info;
// normalized screen coords in [0,1]
OgreNewt::BasicRaycast* verticalRay = new OgreNewt::BasicRaycast(cPhysicsInterface::getSingleton().getNewtWorld(),start,end,false);
info = verticalRay->getFirstHit();
if (info.mBody)
{
((cEntityGraphics&)info.mBody->getUserData()).setBodyBehavior(damage,mode);
return;
}
}
What I'm missing? Please see the screenshot.
Now i tried to do something different here it is:
void cWeapons::ray(float range, int damage, Ogre::Vector3 origin, Ogre::Vector3 direction, bool mode)
{
Ogre::Vector3 start = origin;
Ogre::Vector3 end = origin + (direction - origin);
OgreNewt::BasicRaycast::BasicRaycastInfo info;
// normalized screen coords in [0,1]
OgreNewt::BasicRaycast* verticalRay = new OgreNewt::BasicRaycast(cPhysicsInterface::getSingleton().getNewtWorld(),start,end,false);
info = verticalRay->getFirstHit();
if (info.mBody)
{
cEntityGraphics *test = Ogre::any_cast<cEntityGraphics*>(info.mBody->getUserData());
test->setBodyBehavior();
//((cEntityGraphics&)info.mBody->getUserData()).setBodyBehavior(damage,mode);
return;
}
}
And here is the log:
23:33:51: OGRE EXCEPTION(2:InvalidParametersException): Bad cast from type 'int' to 'class cEntityGraphics *' in Ogre::any_cast at c:\ogrenew\ogremain\include\ogreany.h (line 407)
I'm without clues please help!
Houdini
17-09-2010 15:32:58
Might be an obvious suggestion, but did you check to ensure you do NOT have OGRENEWT_NO_OGRE_ANY defined? If it's defined then the getUserData() function would not return an Ogre::Any instance, but instead a void*.
FYI, if you don't have that defined you could always define it. I remember having issues with Ogre::Any myself so I defined OGRENEWT_NO_OGRE_ANY and just typecast to/from void* to my actual class instances. You might want to just try that.
- Houdini
First of all thanks a lot for your reply
I don't have it defined, can you give me an example how to define it?
Thanks in advance!
SFCBias
18-09-2010 17:55:40
You don't want this to be defined because then you cant use OgreAny at all. You should debug and step through it and before the cast, be SURE that you're getting the right body and a valid userAny. If noone does this ill update OgreNewt to use the newer version of setUserAny that gives an optional key so that you can specify which Any you want to get, that way if it doesn't exist you'll probably get an error telling you so.
Thanks a lot for your reply mate
I found one of the problems, the ray was hitting the NPC not me, since the ray is casting from the middle of the NPC body, the first collision he finds is his own body, after i found this i put a mBody->setUserData(Ogre::Any(this)); in the NPC body also. But i had another problem, here it is:
19:08:36: OGRE EXCEPTION(2:InvalidParametersException): Bad cast from type 'class cNonPlayerCharacterGraphics *' to 'class cEntityGraphics *' in Ogre::any_cast at c:\ogrenew\ogremain\include\ogreany.h (line 407)
Why it can't cast from cNonPlayerCharacterGraphics *' to 'class cEntityGraphics * if cNonPlayerCharacterGraphics inherits from cEntityGraphics?
I have another question, how can I ignore a body to prevent the NPC's ray detect his own body?
SFCBias
18-09-2010 20:18:18
It's probably that an any cast isn't what you should be using. As for the ray cast try and make sure that the ray begins _outside_ the body.
What should i use instead of the any cast? getUserData only deals with Any i tried this:
((cEntityGraphics&)info.mBody->getUserData()).setBodyBehavior(damage,mode);
But i got a memory error, I'm without ideas, with the old newton i did:
((cEntityGraphics*)info.mBody->getUserData())->setBodyBehavior(damage,mode);
and it worked without errors, now i can't make this work, what should i do?
SFCBias
19-09-2010 00:36:28
could you show the classes. ( I really only want to see the functions in each of them)
cEntityGraphics.h
#ifndef _CENTITYGRAPHICS_H_
#define _CENTITYGRAPHICS_H_
#include <Ogre.h>
#include "cPhysicsInterface.h"
#include "cEntity.h"
#include "cEntityCollisionHandler.h"
using namespace Ogre;
class cEntityGraphics
{
protected:
Ogre::SceneNode* mBodyNode;
Ogre::Entity *mEntity;
const Ogre::Vector3 ENTITYINITIALPOSITION;
Ogre::Vector3 mSize;
Ogre::Vector3 mCenterOffset;
Ogre::Vector3 mScale;
cEntity *mMyEntity;
public:
//Constructor
cEntityGraphics();
//Getters
virtual Ogre::SceneNode* getNode();
virtual Ogre::Vector3 getMeshSize();
virtual Ogre::Entity* getOgreEntity();
virtual cEntity* getEntity();
//Set Functions
virtual void setBodyBehavior(int damage, bool mode);
virtual void setEntity(cEntity *entity);
//Create Functions
virtual Ogre::SceneNode* createNode(Ogre::Entity* entity, bool isVisible, Ogre::Vector3 position, Ogre::Vector3 scale, Quaternion orientation);
virtual Ogre::SceneNode* createNode(Ogre::String entityName, Ogre::String meshName, const std::string &materialFileName, Ogre::String nodeName, bool castShadows, bool normaliseNormals, bool isVisible, Ogre::Vector3 position, Ogre::Vector3 scale, Quaternion orientation);
virtual Ogre::SceneNode* createNode(Ogre::String entityName, Ogre::String meshName, bool castShadows, bool isVisible, Ogre::Vector3 position, Ogre::Vector3 scale, Quaternion orientation);
virtual Ogre::Entity* createEntity(Ogre::String entityName, Ogre::String meshName, bool castShadows);
virtual OgreNewt::Body* createAndAssignPhysicalBodyToEntity(cEntityCollisionHandler *entityCollision, Ogre::SceneNode *node);
//Destructor
~cEntityGraphics();
};
#endif
cPlayerGraphics.h
#ifndef _CPLAYERGRAPHICS_H_
#define _CPLAYERGRAPHICS_H_
#include <Ogre.h>
#include "cGraphicalInterface.h"
#include "cPlayer.h"
#include "cPhysicsInterface.h"
#include "cPlayerCollisionHandler.h"
#include "cEntityGraphics.h"
#include "cPlayerFrameListener.h"
using namespace Ogre;
class cPlayerGraphics: public cEntityGraphics
{
private:
SceneNode* camView;
cPlayer *mPlayer;
cPlayerCollisionHandler *mPlayerCollision;
OgreNewt::Body *mBody;
OgreNewt::PlayerController* mPlayerController;
public:
//Constructor
cPlayerGraphics();
//Getters
Ogre::SceneNode* getCamView();
cPlayer* getPlayer();
OgreNewt::Body* getOgreNewtBody();
OgreNewt::PlayerController* getPlayerController();
virtual void setBodyBehavior(int damage, bool mode);
//Create Functions
void addPlayerFrameListener(OgreNewt::PlayerController* playerController, cPlayerCollisionHandler * playerCollision, cPlayer* player);
void createPlayerEntity(Ogre::String entityName, Ogre::String meshName, bool castShadows, bool isVisible, Ogre::Vector3 position, Ogre::Vector3 scale, Quaternion orientation);
//Destructor
~cPlayerGraphics();
};
#endif
cNonPlayerCharacterGraphics.h
#ifndef _CNONPLAYERCHARACTERGRAPHICS_H_
#define _CNONPLAYERCHARACTERGRAPHICS_H_
#include <Ogre.h>
#include "cGraphicalInterface.h"
#include "cNonPlayerCharacter.h"
#include "cPhysicsInterface.h"
#include "cNonPlayerCollisionHandler.h"
#include "cNonPlayerFrameListener.h"
#include "cEntityGraphics.h"
using namespace Ogre;
class cNonPlayerCharacterGraphics: public cEntityGraphics
{
private:
cNonPlayerCharacter *mNonPlayerCharacter;
cNonPlayerCollisionHandler *mNonPlayerCollision;
OgreNewt::Body *mEntityBody;
OgreNewt::PlayerController* mNonPlayerController;
public:
//Constructor
cNonPlayerCharacterGraphics(OgreNewt::Body *entityBody);
virtual void setBodyBehavior(int damage, bool mode);
//Create Functions
void addNonPlayerFrameListener(Ogre::Entity * entity, cNonPlayerCollisionHandler *nonPlayerCollision, OgreNewt::PlayerController* nonPlayerController, OgreNewt::Body *entityBody);
void createNonPlayerEntity(Ogre::String entityName, Ogre::String meshName, bool castShadows, bool isVisible, Ogre::Vector3 position, Ogre::Vector3 scale, Quaternion orientation);
void addEnemy(OgreNewt::PlayerController *entityController);
//Destructor
~cNonPlayerCharacterGraphics();
};
#endif
Create entity
OgreNewt::Body* cEntityGraphics::createAndAssignPhysicalBodyToEntity(cEntityCollisionHandler *entityCollision, Ogre::SceneNode *node)
{
OgreNewt::Body* body = entityCollision->createPhysicalBody(mSize,mCenterOffset,mScale);
cPhysicsInterface::getSingleton().assignBodyToNode(body,node);
body->setUserData(Ogre::Any(this));
//cPhysicsInterface::getSingleton().setUserData(body,(Ogre::Any)this);
return body;
}
Create NPC
void cNonPlayerCharacterGraphics::createNonPlayerEntity(Ogre::String entityName, Ogre::String meshName, bool castShadows, bool isVisible, Ogre::Vector3 position, Ogre::Vector3 scale, Quaternion orientation)
{
mEntity = createEntity(entityName,meshName,castShadows);
mBodyNode = createNode(mEntity,isVisible,position,scale,orientation);
mNonPlayerCharacter = new cNonPlayerCharacter();
setEntity(mNonPlayerCharacter);
mNonPlayerCollision = new cNonPlayerCollisionHandler(mNonPlayerCharacter);
mNonPlayerController = mNonPlayerCollision->createNonPlayerController(mEntity,scale,mBodyNode);
addNonPlayerFrameListener(mEntity,mNonPlayerCollision,mNonPlayerController,mEntityBody);
mNonPlayerController->getBody0()->setUserData(Ogre::Any(this));
}
Create Player
void cPlayerGraphics::createPlayerEntity(Ogre::String entityName, Ogre::String meshName, bool castShadows, bool isVisible, Ogre::Vector3 position, Ogre::Vector3 scale, Quaternion orientation)
{
mPlayer = new cPlayer();
mPlayer->setWeight(80.0f);
mPlayer->setHitPoints(100);
cPlayerCollisionHandler * playerCollision = new cPlayerCollisionHandler(mPlayer);
mBodyNode = createNode(entityName,meshName,castShadows,isVisible,position,scale,orientation);
mPlayerController = playerCollision->createPlayerController(scale,mBodyNode);
addPlayerFrameListener(mPlayerController,playerCollision,mPlayer);
setEntity(mPlayer);
mBody = mPlayerController->getBody0();
mBody->setUserData(Ogre::Any(this));
//cPhysicsInterface::getSingleton().setUserData(mBody,this);
}
Do you need to see more code?
SFCBias
19-09-2010 01:35:38
Hmm i can't imagine why your code wouldn't work but i can't imagine it being a problem with ogre...Try this. When you call setUserAny on the body, go ahead and cast it to your derived class. In other words change
mBody->setUserData(Ogre::Any(this));
To
mBody->setUserData(Ogre::Any(static_cast<cEntityGraphics*>(this)));
That way when you do the any cast it won"t have to do the conversion. Then tell me how that goes.
Thanks a lot mate for your help, i was seeing that no one will help me.
Tomorrow i will try it and i post here if it work, 1h55 here in Portugal i have to go sleep
Mate thanks a lot for your help, thanks to you it's working
I had afraid that we can't use polymorphism with the getUserData.
SFCBias
19-09-2010 13:18:03
No problem, I knew you could use polymorphism with it because I do it myself but i find it strange that it didn't work initially for you. But still if everything works its a good thing.