Terrain Collision Problem

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.
Post Reply
Ion
Posts: 5
Joined: Tue Dec 09, 2008 6:32 am
Location: Leduc, Alberta, Canada
Contact:

Terrain Collision Problem

Post by Ion »

Hello, this is my first post. However, I have use the engine for quite some time. This is the first time I have needed to ask my own question because I cant find an answer through the search.

My problem is this: When I add a terrain collision (such as in the tutorial), to an animated mesh (such as the faerie) it messes everything up. And by messes everything up, I mean the collision is choppy and the character starts bumping around everywhere.

Here is where I added the selector:

Code: Select all

ITriangleSelector *selector = smgr->createTerrainTriangleSelector(terrain, 0);
terrain->setTriangleSelector(selector);
Here is where I added the animator:

Code: Select all

ISceneNodeAnimator *anim = smgr->createCollisionResponseAnimator(selector, fnode, vector3df(60, 100, 60), vector3df(0, -3, 0), vector3df(0, 50, 0));
Thanks in advance,
Jameson.

P.S. I will be willing to supply more code if needed.
Ion
Posts: 5
Joined: Tue Dec 09, 2008 6:32 am
Location: Leduc, Alberta, Canada
Contact:

Post by Ion »

Ok, I fixed it... I set up my terrain improperly.

Before it was:

Code: Select all

ITerrainSceneNode *terrain = smgr->addTerrainSceneNode("terrain-heightmap.bmp");
terrain->setScale(vector3df(40, 4.4f, 40));
And now it is:

Code: Select all

ITerrainSceneNode *terrain = smgr->addTerrainSceneNode("terrain-heightmap.bmp", 0, -1, vector3df(0, 0, 0), vector3df(0, 0, 0), vector3df(40, 4.4f, 40), SColor(255, 255, 255, 255), 5, ETPS_17, 4);
But I still have 2 little problem. When the character gets close to the edge, it should be able to walk off, right? But it just disallows movement.

And the other problem is that it the walking is still all strange (it blips around in a small area when you walk and stop).
Ion
Posts: 5
Joined: Tue Dec 09, 2008 6:32 am
Location: Leduc, Alberta, Canada
Contact:

Post by Ion »

Main.cpp

Code: Select all

#include <irrlicht.h>
#include <iostream>

#pragma comment(lib, "Irrlicht.lib")

#include "EventReceiver.cpp"

using namespace irr;

using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

int main(){
    EventReceiver receiver;
    
    IrrlichtDevice *device = createDevice(EDT_OPENGL, dimension2d<s32>(800, 600), 32, 0);
    device->setWindowCaption(L"Test");
    device->setEventReceiver(&receiver);
    
    IVideoDriver *driver = device->getVideoDriver();
    ISceneManager *smgr = device->getSceneManager();
    IGUIEnvironment *guienv = device->getGUIEnvironment();
    
//    device->getFileSystem()->addZipFileArchive("map-20kdm2.pk3");
//    
//    IAnimatedMesh *levelMesh = smgr->getMesh("20kdm2.bsp");
//    ISceneNode *levelNode = 0;
//    
//    if(levelMesh){
//        levelNode = smgr->addOctTreeSceneNode(levelMesh->getMesh(0));
//    }
//    
//    ITriangleSelector *selector = 0;
//    if(levelNode){
//        levelNode->setPosition(vector3df(-1350, -130, -1400));
//        selector = smgr->createOctTreeTriangleSelector(levelMesh->getMesh(0), levelNode, 128);
//        levelNode->setTriangleSelector(selector);
//    }
    
    ITerrainSceneNode *terrain = smgr->addTerrainSceneNode("terrain-heightmap.bmp", 0, -1, vector3df(0, 0, 0), vector3df(0, 0, 0), vector3df(40, 4.4f, 40), SColor(255, 255, 255, 255), 5, ETPS_17, 4);
    terrain->setMaterialFlag(EMF_LIGHTING, false);
    terrain->setMaterialTexture(0, driver->getTexture("terrain-texture.jpg"));
    terrain->setMaterialTexture(1, driver->getTexture("detailmap3.jpg"));
    terrain->setMaterialType(EMT_DETAIL_MAP);
    terrain->scaleTexture(1.0f, 20.0f);
    
    ITriangleSelector *selector = smgr->createTerrainTriangleSelector(terrain, 0);
    terrain->setTriangleSelector(selector);
    
    float camDistance = 80;
    ICameraSceneNode *cam = smgr->addCameraSceneNode(); //FPS(0, 100.0f, 300.0f, -1, 0, 0, true);
    cam->setPosition(vector3df(0, 0, 0));
    cam->setFarValue(12000.0f);
    
    //ISceneNodeAnimator *anim = smgr->createCollisionResponseAnimator(selector, cam, vector3df(30, 50, 30), vector3df(0, -3, 0), vector3df(0, 50, 0));
//    selector->drop();
//    cam->addAnimator(anim);
//    anim->drop();
    
    SMaterial material;
    material.setTexture(0, driver->getTexture("faerie2.bmp"));
    material.Lighting = false;
    
    IAnimatedMeshSceneNode *fnode = 0;
    IAnimatedMesh *faerie = smgr->getMesh("faerie.md2");

    fnode = smgr->addAnimatedMeshSceneNode(faerie);
    fnode->setPosition(vector3df(1900 * 2, 355 * 2, 3700 * 2));
    fnode->setRotation(vector3df(0, 150, 0));
    fnode->setMD2Animation(EMAT_STAND);
    fnode->getMaterial(0) = material;
    
    bool isRunning = false;
    bool isStanding = true;
    
    ISceneNodeAnimator *anim = smgr->createCollisionResponseAnimator(selector, fnode, vector3df(30, 50, 30), vector3df(0, -3, 0), vector3df(0, 50, 0));
    selector->drop();
    fnode->addAnimator(anim);
    anim->drop();
    
    material.setTexture(0, 0);
    
    device->getCursorControl()->setVisible(false);
    smgr->addLightSceneNode(0, vector3df(-60, 100, 400), SColorf(1.0f, 1.0f, 1.0f, 1.0f), 600.0f);
    
    ISceneNode *selectedSceneNode = 0;
    ISceneNode *lastSelectedSceneNode = 0;
    
    while(device->run()){
        if(device->isWindowActive()){
            if(receiver.IsKeyDown(KEY_ESCAPE)){
                device->closeDevice();
                device->drop();
                exit(0);
            }
            
            vector3df pos = fnode->getPosition();
            vector3df rot = fnode->getRotation();
            if(receiver.IsKeyDown(KEY_KEY_W)){
                pos.X += 20 * cos((rot.Y) * 3.14 / 180);
                pos.Z -= 20 * sin((rot.Y) * 3.14 / 180);
                if(!isRunning){
                    fnode->setMD2Animation(EMAT_RUN);
                    isRunning = true;
                }
            }else if(receiver.IsKeyDown(KEY_KEY_S)){
                pos.X -= 16 * cos((rot.Y) * 3.14 / 180);
                pos.Z += 16 * sin((rot.Y) * 3.14 / 180);
                if(!isRunning){
                    fnode->setMD2Animation(EMAT_RUN);
                    isRunning = true;
                }
            }else{
                isRunning = false;
            }
                if(!isRunning){
                    fnode->setMD2Animation(EMAT_STAND);
                    isStanding = true;
                }
            if(receiver.IsKeyDown(KEY_KEY_A)){
                rot.Y -= 20;
            }else if(receiver.IsKeyDown(KEY_KEY_D)){
                rot.Y += 20;
            }
            fnode->setPosition(pos);
            fnode->setRotation(rot);
            
            cam->setPosition(vector3df(vector3df(pos.X - 150 * cos((rot.Y) * 3.14 / 180), pos.Y + camDistance, pos.Z + 150 * sin((rot.Y) * 3.14 / 180))));
            cam->setTarget(pos);
            
            driver->beginScene(true, true, 0);
            
            smgr->drawAll();
            guienv->drawAll();
            
            lastSelectedSceneNode = selectedSceneNode;
            
            driver->endScene();
        }
    }
    
    device->drop();
    
    return 0;
}
EventReceiver.cpp

Code: Select all

#include <irrlicht.h>

using namespace irr;

using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

class EventReceiver : public IEventReceiver{
public:
    virtual bool OnEvent(const SEvent &event){
        if(event.EventType == EET_KEY_INPUT_EVENT){
            KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
        }
        return false;
    }
    
    bool IsKeyDown(EKEY_CODE keyCode){
        return KeyIsDown[keyCode];
    }
    
    EventReceiver(){
        for(u32 i = 0; i < KEY_KEY_CODES_COUNT; i++){
            KeyIsDown[i] = false;
        }
    }
private:
    bool KeyIsDown[KEY_KEY_CODES_COUNT];
};
Frank Dodd
Posts: 208
Joined: Sun Apr 02, 2006 9:20 pm

Post by Frank Dodd »

Hi, Lately I have been doing my terrain 'collision' simply by using getHeight for the camera position. its a fast and fairly simple way to do it although you have to do a proportion of camera control yourself of course, judging if you can climb a steep slope for example.
Ion
Posts: 5
Joined: Tue Dec 09, 2008 6:32 am
Location: Leduc, Alberta, Canada
Contact:

Post by Ion »

Oh, that is a good idea Frank. It would make jumping a bit more difficult, too. I ended up realizing it was Dev C++ that was at fault. I switched to VC++ 2008, it works SO much faster! But thanks for the help!
Post Reply