Raycasting with Irrbullet

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
eejin
Posts: 97
Joined: Sun Jul 24, 2011 11:50 am

Raycasting with Irrbullet

Post by eejin »

Hi, I'm trying to create a charachter that is able to shoot. Now I want to know if the bullet is going to hit a prop/building or enemy.
So I thought about casting a ray and there are topics talking about it but I can't find any code that casts a ray.
So how do I cast a ray and maybe find wich Object I hit?

Maybe I overlooked something but I searched for about an hour.
randomMesh
Posts: 1186
Joined: Fri Dec 29, 2006 12:04 am

Re: Raycasting with Irrbullet

Post by randomMesh »

I'd use Bullets native methods for this. There's btCollisionWorld::rayTest().
"Whoops..."
eejin
Posts: 97
Joined: Sun Jul 24, 2011 11:50 am

Re: Raycasting with Irrbullet

Post by eejin »

Ok thanks.
But I'm having a little trouble with adding a collision box to an animated model. I just want a cilinder (I got a box now but how do I get a cilinder?) but the program crashes.

Code: Select all

 scene::IAnimatedMeshSceneNode* player = smgr->addAnimatedMeshSceneNode(smgr->getMesh("media/soldier.x"));
        if (player) {
        player->setMaterialFlag(video::EMF_LIGHTING, false);
        player->setMaterialTexture( 0, driver->getTexture("media/Soldier.png") );
        player->setPosition(core::vector3df(10,0,0));
        player->setScale(core::vector3df(0.027,0.027,0.027));
        
        ICollisionShape *playershape = new IBoxShape(player, 1, false);
 
        IRigidBody *playerbody;
        playerbody = world->addRigidBody(playershape);
        }
Also I tryd that code and it gives me this error:
C:\Users\blurblurblur\Documents\Irrlicht\irrlicht-1.7.2\examples\04.Movement\main.cpp|134|error: missing template arguments before '(' token
With this code:

Code: Select all

btCollisionWorld::rayTest (core::vector3d(playerPosition), core::vector3df(playerPosition),0);
randomMesh
Posts: 1186
Joined: Fri Dec 29, 2006 12:04 am

Re: Raycasting with Irrbullet

Post by randomMesh »

core::vector3d is not a Bullet class.

and

Code: Select all

 
scene::IAnimatedMeshSceneNode* player = smgr->addAnimatedMeshSceneNode(smgr->getMesh("media/soldier.x"));
ICollisionShape *playershape = new IBoxShape(player, 1, false);
 
is totally wrong. How can Bullet know what an IAnimatedMeshSceneNode is?
"Whoops..."
eejin
Posts: 97
Joined: Sun Jul 24, 2011 11:50 am

Re: Raycasting with Irrbullet

Post by eejin »

randomMesh wrote:core::vector3d is not a Bullet class.

and

Code: Select all

 
scene::IAnimatedMeshSceneNode* player = smgr->addAnimatedMeshSceneNode(smgr->getMesh("media/soldier.x"));
ICollisionShape *playershape = new IBoxShape(player, 1, false);
 
is totally wrong. How can Bullet know what an IAnimatedMeshSceneNode is?
So I knew it was wrong so how do I fix it?

EDIT:
I got it to this:

Code: Select all

 
btCollisionWorld::ClosestRayResultCallback result(btVector3(playerPosition.X,playerPosition.Y,playerPosition.Z), btVector3(0,0,0));
btCollisionWorld::rayTest (btVector3(playerPosition.X,playerPosition.Y,playerPosition.Z), btVector3(0,0,0),result);
but it needs an object or something:
C:\Users\blurblarblie\Documents\Irrlicht\irrlicht-1.7.2\examples\04.Movement\main.cpp|132|error: cannot call member function 'virtual void btCollisionWorld::rayTest(const btVector3&, const btVector3&, btCollisionWorld::RayResultCallback&) const' without object

So I figured it would have to be something like this but I dont understand the parameters:

Code: Select all

 
btCollisionWorld::addCollisionObject (btCollisionObject * collisionObject, short int collisionFilterGroup = btBroadphaseProxy::DefaultFilter, short int collisionFilterMask = btBroadphaseProxy::AllFilter)
 
Last edited by eejin on Fri Jun 29, 2012 9:17 pm, edited 1 time in total.
randomMesh
Posts: 1186
Joined: Fri Dec 29, 2006 12:04 am

Re: Raycasting with Irrbullet

Post by randomMesh »

Fix it by using the mighty search function. I wrote a simple Hello World programm using plain Bullet, which you can find easily. (Sorry, no raycasting, but there are examples in the Bullet Forum, the Wiki and the source folder of Bullet.
"Whoops..."
eejin
Posts: 97
Joined: Sun Jul 24, 2011 11:50 am

Re: Raycasting with Irrbullet

Post by eejin »

I wouldn't have posted before searching and I'm trying to get it to work.
I got this now but it still crashes when it started

Code: Select all

 
scene::IAnimatedMeshSceneNode* player = smgr->addAnimatedMeshSceneNode(smgr->getMesh("media/soldier.x"));
        if (player) {
        player->setMaterialFlag(video::EMF_LIGHTING, false);
        player->setMaterialTexture( 0, driver->getTexture("media/Soldier.png") );
        player->setPosition(core::vector3df(10,0,0));
        player->setScale(core::vector3df(0.027,0.027,0.027));
 
        ICollisionShape *playershape = new IGImpactMeshShape(player,smgr->getMesh("media/soldier.x"),1);
        IRigidBody *playerbody;
        playerbody = world->addRigidBody(playershape);
        }
 
Nevermind the player I managed to fix this but I can't get the ray to work.
randomMesh
Posts: 1186
Joined: Fri Dec 29, 2006 12:04 am

Re: Raycasting with Irrbullet

Post by randomMesh »

Since you didn't post a full compilable program i can't tell. Maybe wrong paths. Have a look at the console output.

For the records: Here's the Hello World program i was talking about.
"Whoops..."
Rusk
Posts: 7
Joined: Fri Feb 03, 2012 1:51 am

Re: Raycasting with Irrbullet

Post by Rusk »

I used raycasting in bullet a while ago when I made a function to select a unit on screen by clicking on it. Maybe you can get some ideas from it.

The Obj3d class is just all the things needed to describe a unit, for both irrlicht and bullet in a big mess: scenenode, collisionshape, rigidbody and so on. It's very ugly, so I won't post that. But I will mention that Obj3d.isMyCollision is just a test for (collisionObject->getCollisionShape() == mybtCollisionShape).

Note that you can use collisionMask and collisionGroup if you want to exclude some objects from the raycast. Also, looping through all units and seeing if they are hit worked for me, since I only ran it on user input, but it's not really the best solution.

Code: Select all

Obj3d* clickSelect(irr::scene::ISceneManager* smgr,
    irr::scene::ICameraSceneNode* camera,
    MyEventReceiver* receiver,
    btDiscreteDynamicsWorld* dynWorld,
    std::vector<Obj3d*> units)
{
    Obj3d* result = 0;
 
    // Use irrlicht to get a ray from mouse cursor position.
    irr::core::line3df ray =
        smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
        receiver->GetMouseState().Position, camera);
 
    // Convert ray to bullet vectors.
    btVector3 start(ray.start.X, ray.start.Y, ray.start.Z);
    btVector3 end(ray.end.X, ray.end.Y, ray.end.Z);
 
    // Do a raycast
    btCollisionWorld::ClosestRayResultCallback RayCallback(start, end);
    RayCallback.m_collisionFilterGroup = 1;
    RayCallback.m_collisionFilterMask = 1;
    dynWorld->getCollisionWorld()->rayTest(start, end, RayCallback);
    if (RayCallback.hasHit())
    {
        for (std::vector<Obj3d*>::iterator i=units.begin();i!=units.end();++i)
        {
            if ( (*i)->isMyCollision(RayCallback.m_collisionObject) )
                result = *i;
        }
    }
    return result;
}
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: Raycasting with Irrbullet

Post by hendu »

You could just store pointers to your Obj3d objects in the bullet objects' userdata ;)
eejin
Posts: 97
Joined: Sun Jul 24, 2011 11:50 am

Re: Raycasting with Irrbullet

Post by eejin »

What is a btDiscreteDynamicsWorld?
I got an irrBulletWorld *world;.
randomMesh
Posts: 1186
Joined: Fri Dec 29, 2006 12:04 am

Re: Raycasting with Irrbullet

Post by randomMesh »

It belongs to Bullet.
randomMesh wrote: I'd use Bullets native methods for this. There's btCollisionWorld::rayTest().
I don't know if irrBullet supports ray casting. Never used it.
"Whoops..."
eejin
Posts: 97
Joined: Sun Jul 24, 2011 11:50 am

Re: Raycasting with Irrbullet

Post by eejin »

randomMesh wrote:It belongs to Bullet.
randomMesh wrote: I'd use Bullets native methods for this. There's btCollisionWorld::rayTest().
I don't know if irrBullet supports ray casting. Never used it.
I can figure out it belongs to bullet -_-. I wonder why I can't use Irrbulletworld for it.
eejin
Posts: 97
Joined: Sun Jul 24, 2011 11:50 am

Re: Raycasting with Irrbullet

Post by eejin »

I'm still having trouble with the character. I want it to have a cilinder like shape facing upright.
Irrbullet doesn't seem to have a cilinder shape built in so I tried the boxshape first but It doesn't seem to move after it stood still for a couple of seconds. I also want a cilinder shape. How would I achieve that?
Here is a small example:

Code: Select all

#include <irrlicht.h>
#include <irrBullet.h>
 
using namespace irr;
 
irrBulletWorld *world;
 
class MyEventReceiver : public IEventReceiver
{
public:
    virtual bool OnEvent(const SEvent& event)
    {
        if (event.EventType == irr::EET_KEY_INPUT_EVENT)
            KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
 
        return false;
    }
 
    virtual bool IsKeyDown(EKEY_CODE keyCode) const
    {
        return KeyIsDown[keyCode];
    }
 
    MyEventReceiver()
    {
        for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
            KeyIsDown[i] = false;
    }
 
private:
    bool KeyIsDown[KEY_KEY_CODES_COUNT];
};
 
int main()
{
    MyEventReceiver receiver;
 
    IrrlichtDevice* device = createDevice(video::EDT_OPENGL,
            core::dimension2d<u32>(1280, 720), 16, false, false, false, &receiver);
 
    video::IVideoDriver* driver = device->getVideoDriver();
    scene::ISceneManager* smgr = device->getSceneManager();
 
    world = createIrrBulletWorld(device, true, true);
    world->setDebugMode(EPDM_DrawAabb |EPDM_DrawContactPoints);
    world->setGravity(core::vector3df(0,-10,0));
 
    scene::IAnimatedMeshSceneNode* player = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/sydney.md2"));
    if (player)
        player->setMaterialFlag(video::EMF_LIGHTING, false);
        player->setMaterialTexture( 0, driver->getTexture("../../media/sydney.bmp"));
        player->setScale(core::vector3df(0.027,0.027,0.027));
 
        ICollisionShape *playershape = new IBoxShape(player, 10, false);
 
        IRigidBody *playerbody;
        playerbody = world->addRigidBody(playershape);
 
    scene::ISceneNode *Floor = device->getSceneManager()->addCubeSceneNode(1.0);
    if (Floor)
    {
        Floor->setScale(core::vector3df(25,1,20)); // 400, 3, 400
        Floor->setPosition(core::vector3df(0,-1,0));
        Floor->setMaterialFlag(video::EMF_LIGHTING, false);
        Floor->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
 
        ICollisionShape *Floorshape = new IBoxShape(Floor, 0, false);
        IRigidBody *Floorbody;
        Floorbody = world->addRigidBody(Floorshape);
    }
 
    scene::ISceneNode *Node = device->getSceneManager()->addCubeSceneNode(1.0);
    if (Node)
    {
        Node->setScale(core::vector3df(2,2,2)); // 400, 3, 400
        Node->setPosition(core::vector3df(2,0,1));
        Node->setMaterialFlag(video::EMF_LIGHTING, false);
        Node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
 
        ICollisionShape *shape = new IBoxShape(Node, 10, false);
 
        IRigidBody *body;
        body = world->addRigidBody(shape);
    }
 
    smgr->addCameraSceneNode(0, core::vector3df(0,8,-2), core::vector3df(0,0,0));
 
    int lastFPS = -1;
    u32 then = device->getTimer()->getTime();
    const f32 MOVEMENT_SPEED = 1.f;
 
    while(device->run())
    {
        const u32 now = device->getTimer()->getTime();
        const f32 frameDeltaTime = (f32)(now - then) / 1000.f; // Time in seconds
        then = now;
        world->stepSimulation(frameDeltaTime, 120);
 
        if(receiver.IsKeyDown(irr::KEY_KEY_W))
            playerbody->applyCentralForce(core::vector3df(0,0,5), ERBTS_WORLD);
        else if(receiver.IsKeyDown(irr::KEY_KEY_S))
            playerbody->applyCentralForce(core::vector3df(0,0,-5), ERBTS_WORLD);
 
        if(receiver.IsKeyDown(irr::KEY_KEY_A))
            playerbody->applyCentralForce(core::vector3df(-5,0,0), ERBTS_WORLD);
        else if(receiver.IsKeyDown(irr::KEY_KEY_D))
            playerbody->applyCentralForce(core::vector3df(+5,0,0), ERBTS_WORLD);
 
        driver->beginScene(true, true, video::SColor(255,113,113,133));
 
        smgr->drawAll(); // draw the 3d scene
        device->getGUIEnvironment()->drawAll();
 
        driver->endScene();
 
        int fps = driver->getFPS();
 
        if (lastFPS != fps)
        {
            core::stringw tmp(L"[");
            tmp += driver->getName();
            tmp += L"] fps: ";
            tmp += fps;
 
            device->setWindowCaption(tmp.c_str());
            lastFPS = fps;
        }
    }
 
    device->drop();
 
    return 0;
}
It's about the player node that doesnt move after receiving a force impulse when it stood still for a few seconds.
zerochen
Posts: 273
Joined: Wed Jan 07, 2009 1:17 am
Location: Germany

Re: Raycasting with Irrbullet

Post by zerochen »

hi,

bullet obj deactivate after a few seconds so you must active them explicit or disable the deactivation

eg

Code: Select all

 
body->setActivationState(EAS_DISABLE_DEACTIVATION)
 
Post Reply