[Solved]Problems with collision

majc

14-09-2010 22:49:15

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.

majc

16-09-2010 21:04:09

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.

majc

16-09-2010 23:39:38

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

majc

17-09-2010 23:39:43

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.

majc

18-09-2010 19:14:17

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.

majc

18-09-2010 22:22:13

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)

majc

19-09-2010 01:10:21

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.

majc

19-09-2010 01:56:17

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 :)

SFCBias

19-09-2010 01:56:56

Ok no problem.

majc

19-09-2010 11:48:21

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.