tile based world irrlicht UPDATE - example!!

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
Howker
Posts: 51
Joined: Thu Jan 22, 2009 4:40 pm

tile based world irrlicht UPDATE - example!!

Post by Howker »

Hello. This one is a bit hard to explain...
I made a tile-based world, and sometimes you can look between some tiles and you see a vertical (or horizontal) gap between two columns of tiles. This gap is about 1 px wide and has the same color as the background, so I guess it really is a gap between the tiles, and not a real rendered "line".
This bug only occurs a very few times when moving the camera and then quickly disapears.

EDIT:
I wrote a small test program, with a black tiles and a moving camera, sometimes you can see the lines. Try it please.

Code: Select all

 
#define SCREEN_WIDTH 1024
#define SCREEN_HEIGHT 768
 
const float TILE_RATIO = 0.09f;
const float TILE_HEIGHT = 32 * TILE_RATIO;
const float TILE_WIDTH = 32 * TILE_RATIO;
 
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#pragma comment(lib, "Irrlicht.lib")
#endif
 
#include <irrlicht.h>
 
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace std;
 
class Tile
{
public:
        Tile(IVideoDriver *driver, ISceneManager *smgr, int x, int y);
 
private:
        ISceneManager *m_Smgr;
        IVideoDriver *m_Driver;
        IMeshSceneNode *m_Node;
        int m_X, m_Y, m_Z;
        vector3df m_Pos;
};
 
 
Tile::Tile(IVideoDriver *driver, ISceneManager *smgr, int x, int y) : m_Driver(driver), m_Smgr(smgr), m_X(x), m_Y(y)
{
        float posX = m_X * TILE_WIDTH;
        float posY = (m_Y *TILE_HEIGHT) + 32*TILE_RATIO/2;
        m_Pos = vector3df(posX, posY, 0.0f);
 
        IMesh* m = m_Smgr->getGeometryCreator()->createPlaneMesh(dimension2df(32*TILE_RATIO, 32*TILE_RATIO), dimension2d<u32>(1, 1), 0, dimension2df(1, 1));
        m_Node = m_Smgr->addMeshSceneNode(m);
        m_Node->setPosition(m_Pos);
        m_Node->setRotation(vector3df(270,0,0));
        m_Node->setAutomaticCulling(EAC_OFF);
        m_Node->setMaterialFlag(EMF_BILINEAR_FILTER , true);
}
 
 
int main()
{
        SIrrlichtCreationParameters param;
        param.DriverType = video::EDT_DIRECT3D9;
        param.WindowSize = irr::core::dimension2d<u32>(SCREEN_WIDTH, SCREEN_HEIGHT);
        param.Bits = 32;
        param.Fullscreen = false;
        param.Stencilbuffer = false;
        param.Vsync = true;
        param.AntiAlias = false;
        IrrlichtDevice* device  = createDeviceEx(param); 
 
        video::IVideoDriver* driver = device->getVideoDriver();
        scene::ISceneManager* smgr = device->getSceneManager();
 
        //#######CAMERA#########
        scene::ICameraSceneNode* m_Camera = smgr->addCameraSceneNode();
        m_Camera->setTarget(irr::core::vector3df(0.0f,0.0f,0.0f));
        m_Camera->setPosition(irr::core::vector3df(0.0f, 0.0f, -500.0f));
 
    irr::core::matrix4 projMat;
    projMat.buildProjectionMatrixOrthoLH(SCREEN_WIDTH/11,SCREEN_HEIGHT/11,1,1000);
    m_Camera->setProjectionMatrix(projMat);
 
        //#######################
 
        //#######TILES######### (DONT MIND THE MEMORY LEAKS. THIS IS JUST A TEST)
        for(int x = -100; x < 100; x++)
        {
                for(int y = -20; y < 20; y++)
                {
                        Tile* tile = new Tile(driver, smgr, x, y);
                }
        }
        
        //#######################
 
        int lastFPS = -1;
        u32 then = device->getTimer()->getTime();
        float movementSpeed = 70.0f;
 
        while(device->run())
        {
                const u32 now = device->getTimer()->getTime();
                const f32 frameDeltaTime = (f32)(now - then) / 1000.f;
                then = now;
 
                
                if(m_Camera->getPosition().X > 190)
                        movementSpeed = -movementSpeed;
                if(m_Camera->getPosition().X < -190)
                        movementSpeed = -movementSpeed;
 
                m_Camera->setPosition(irr::core::vector3df(m_Camera->getPosition().X+movementSpeed* frameDeltaTime, 0.0f, -500.0f));
                m_Camera->setTarget(irr::core::vector3df(m_Camera->getPosition().X+movementSpeed*frameDeltaTime, 0.0f, 0.0f));
 
                driver->beginScene(true, true, video::SColor(205,205,205,205));
 
                smgr->drawAll();
 
                driver->endScene();
 
                int fps = driver->getFPS();
 
                if (lastFPS != fps)
                {
                        core::stringw tmp(L"tile test fps: ");
                        tmp += fps;
 
                        device->setWindowCaption(tmp.c_str());
                        lastFPS = fps;
                }
        }
        device->drop();
        
        return 0;
}
 
I hope someone could help me.


*EDIT*
I managed to capture a screenshot:
Image
Last edited by Howker on Sat Dec 17, 2011 6:59 pm, edited 2 times in total.
Howker
Posts: 51
Joined: Thu Jan 22, 2009 4:40 pm

Re: tile "line" bug

Post by Howker »

Nobody? Can anyone atleast show me the right way of creating a tile based world (the 3d way with planes etc.)
Howker
Posts: 51
Joined: Thu Jan 22, 2009 4:40 pm

Re: tile based world irrlicht I need help

Post by Howker »

bump
CuteAlien
Admin
Posts: 9718
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: tile based world irrlicht I need help

Post by CuteAlien »

No idea so far. But maybe give us more information ... how do you make your tiles? Is that above code for a single tile? In that case maybe show how you create more than one. Probably at some place some value-rounding is going wrong. Also not sure if one node per tile is so optimal, I suspect putting all tiles into one special node might be a better solution. Maybe search around the forum - I think I've seen other people work on tile-based worlds in the past, so maybe there's already some code for that out there.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
greenya
Posts: 1012
Joined: Sun Jan 21, 2007 1:46 pm
Location: Ukraine
Contact:

Re: tile "line" bug

Post by greenya »

Howker wrote:Nobody? Can anyone atleast show me the right way of creating a tile based world (the 3d way with planes etc.)
Why do you use billboards? Is there any special need for it?
I think it would be better (for performance and no the gaps) if you use draw2DImage().
P.S.: i believe what we see using billboards it is a calculation precision errors, i am not sure.
Mikhail9
Posts: 54
Joined: Mon Jun 29, 2009 8:41 am

Re: tile based world irrlicht I need help

Post by Mikhail9 »

I'm inclined to agree that this is some sort of position rounding error either in your code or inherent in the billboard scene node. I have created a tiled world this way (by just drawing square scene nodes, not by using billboards) and I didn't have this problem.

However, I did learn quickly that one scene node per tile is a recipe for disaster due to all of the draw calls. It is much better to just build a meshbuffer representing your tiled world and have it drawn in a single draw call.

When you do that, you'll run into the "how do I texture each quad differently from its neighbors?" problem. The answer to that is duplicated vertices, but you lose the smoothing you get from vertex normals. However, that should be fine for a 2D illusion like you seek.
Nalin
Posts: 194
Joined: Thu Mar 30, 2006 12:34 am
Location: Lacey, WA, USA
Contact:

Re: tile based world irrlicht I need help

Post by Nalin »

You are definitely running into floating point inaccuracy issues. Getting it to work well is going to be VERY tough. It gets worse once you use a single image for your tileset and start zooming the camera in and out. You basically have to make sure your scene objects are being drawn on correct half-pixel values, and make sure your camera only moves in pixel increments. For a game I did in C#/XNA, I tried using tile maps at first, but because of these issues I got rid of them all and just saved the level into large 2048 pixel wide chunks.

It would work well if you used single images for each tile and used a bilinear instead of a point filter. That would allow some aliasing around the tiles and would help fill in the 1 pixel gaps when they occur.
Howker
Posts: 51
Joined: Thu Jan 22, 2009 4:40 pm

Re: tile based world irrlicht UPDATE - example!!

Post by Howker »

Thank you for your reply, bilinear filter did not work unfortunately.
Post Reply