[RESOLVED]Minecraft alike game in Irrlicht

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
fanaticguy
Posts: 9
Joined: Sat Feb 18, 2017 3:51 pm

[RESOLVED]Minecraft alike game in Irrlicht

Post by fanaticguy »

Hi. I would like to create Minecraft alike game in Irrlich. Im not good in 3D graphics yet so i would like your advice. How should i efficiently draw a lot of cubes to get a high performance? At now I'm doing something like on the code below. This code renders 8000 cubes and gives me 24 FPS so this is not so good i guess. How this should be probably done? Can you give me some snippet or advice?

Code: Select all

f32 size = 3.0f;
    int count = 20;
 
    for(f32 k = 15.0f; k < size * count; k += size) {
        for (f32 j = -15.0f; j < size * count; j += size) {
            for (f32 i = 5.0f; i < size * count; i += size) {
                scene::ISceneNode *n = smgr->addCubeSceneNode(size);
                if (n) {
                    n->setMaterialTexture(0, driver->getTexture(
                            "../stone_diorite_smooth.png"));
                    n->setMaterialFlag(video::EMF_LIGHTING, false);
                    n->setPosition(core::vector3df(i, j, k));
                }
            }
        }
    }
Last edited by fanaticguy on Thu Feb 23, 2017 1:04 pm, edited 2 times in total.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Minecraft alike game in Irrlicht

Post by CuteAlien »

Hm, search the forum for "minecraft" - there are a few threads discussing this. Maybe one of them helps.
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
fanaticguy
Posts: 9
Joined: Sat Feb 18, 2017 3:51 pm

Re: Minecraft alike game in Irrlicht

Post by fanaticguy »

Thanks for an answer. Is creating a new SMesh object and appending it with meshbuffers a way to go?
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Minecraft alike game in Irrlicht

Post by CuteAlien »

I never coded a Minecraft, but I suppose you don't want to have real cubes at all. But calculate the outer layers. I remember some people talked in older threads about a libraray to calculate the corresponding geometry. Which can then be used in meshbuffers. But ... don't remember the name of that lib.
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
Cube_
Posts: 1010
Joined: Mon Oct 24, 2011 10:03 pm
Location: 0x45 61 72 74 68 2c 20 69 6e 20 74 68 65 20 73 6f 6c 20 73 79 73 74 65 6d

Re: Minecraft alike game in Irrlicht

Post by Cube_ »

First of all, having cube scene nodes is far too slow (each node is a draw call and we're looking at (size*count)^3 per chunk (or woe the naive "one chunk world" implementation), assuming this is 32^3 then that's 32768 draw calls! You really want as few as possible, 500 draw calls is great - 5000 might push it... thirty two thousand? Give me a break.

Second of all it's memory inefficient.
Third of all nested loops are slower than a single unwrapped loop, you got the order right from a cache perspective though.


What you'd want to ideally do is check for occlusion based on the input data (so you only generate faces adjacent to air blocks) and generate only the appropriate faces, this gives you one mesh per chunk (i.e push a new face onto the current mesh as needed until we've iterated over the chunk structure) then you would ideally want to optimize the mesh using some algorithm such as greedy meshing - but that's optional.


EDIT: I just now noticed 8000 cubes that'd be 20^3, so fine - that's an odd size from a perspective of memory alignment, you'd usually want it to be a power of 8 (8. 16, 32, 64 ... - 24 might work because it's a multiple of 8 so it'll align properly; but this all depends on the chunk structure) but even here we're looking at 8000 draw calls so I'm not surprised you're getting 24 fps.

I have a chunk test where I have over ten million triangles (unculled, so each voxel has all six faces, 12 tris) in 30 draw calls, it hits 60 fps easily even on pretty conservative hardware (note: not stock irrlicht) - can I give you the source? No. It's really ugly and not a good implementation but I can give you a somewhat general-ish implementation without culling

depending on your needs this should work, this pushes back one full cube per voxel for size voxels (size is width*height*length, in your case 8000 - this code would return one draw call as opposed to eight thousand draw calls and should thus be significantly faster) - you can extract what you need for a face and then factor it out to separate methods, called as needed. Or modify this method to generate faces needed based on input parameters - either way.

Code: Select all

for (int i = 0; i < size; i++)
    {
        //these if statemenets are a REALLY ugly way to unwrap the loops, but it works.
        if (x >= CS) //logic to calculate whether to increment Y and reset X
        {
            x = 0;
            y++;
        }
        if (y >= CS) //logic to calculate whether to increment Z and reset Y
        {
            y = 0;
            z++;
        }
        if (z >= CS)  //logic to calculate whether to reset Z
        {
            z = 0;
        }
 
         //push back 12 vertices, this is optimal for a cube.
         //caveat: since this is a "compressed" cube it becomes much harder to do certain skinning related things
         //in my use it made sense to conserve memory - you may want to use a proper 24 vertex cube since it's more flexible
        buf->Vertices.push_back(video::S3DVertex(x - 0, y + 1, z - 0, -2, 2, -2, c, 0, 0));
        buf->Vertices.push_back(video::S3DVertex(x + 1, y + 1, z - 0, 2, 2, -2, c, 1, 0));
        buf->Vertices.push_back(video::S3DVertex(x + 1, y - 0, z - 0, 2, -2, -2, c, 1, 1));
        buf->Vertices.push_back(video::S3DVertex(x - 0, y - 0, z - 0, -2, -2, -2, c, 0, 1));
        buf->Vertices.push_back(video::S3DVertex(x - 0, y + 1, z + 1, -2, 2, 2, c, 1, 0));
        buf->Vertices.push_back(video::S3DVertex(x + 1, y + 1, z + 1, 2, 2, 2, c, 0, 0));
        buf->Vertices.push_back(video::S3DVertex(x + 1, y - 0, z + 1, 2, -2, 2, c, 0, 1));
        buf->Vertices.push_back(video::S3DVertex(x - 0, y - 0, z + 1, -2, -2, 2, c, 1, 1));
        buf->Vertices.push_back(video::S3DVertex(x - 0, y + 1, z - 0, -2, 2, -2, c, 1, 1));
        buf->Vertices.push_back(video::S3DVertex(x + 1, y + 1, z - 0, 2, 2, -2, c, 0, 1));
        buf->Vertices.push_back(video::S3DVertex(x + 1, y - 0, z - 0, 2, -2, -2, c, 0, 0));
        buf->Vertices.push_back(video::S3DVertex(x - 0, y - 0, z - 0, -2, -2, -2, c, 1, 0));
 
                //push back 36 indices
        buf->Indices.push_back(numVertices + 0);
        buf->Indices.push_back(numVertices + 1);
        buf->Indices.push_back(numVertices + 2);
        buf->Indices.push_back(numVertices + 2);
        buf->Indices.push_back(numVertices + 3);
        buf->Indices.push_back(numVertices + 0);
 
        buf->Indices.push_back(numVertices + 7);
        buf->Indices.push_back(numVertices + 6);
        buf->Indices.push_back(numVertices + 5);
        buf->Indices.push_back(numVertices + 5);
        buf->Indices.push_back(numVertices + 4);
        buf->Indices.push_back(numVertices + 7);
 
        buf->Indices.push_back(numVertices + 4);
        buf->Indices.push_back(numVertices + 0);
        buf->Indices.push_back(numVertices + 3);
        buf->Indices.push_back(numVertices + 3);
        buf->Indices.push_back(numVertices + 7);
        buf->Indices.push_back(numVertices + 4);
 
        buf->Indices.push_back(numVertices + 1);
        buf->Indices.push_back(numVertices + 5);
        buf->Indices.push_back(numVertices + 6);
        buf->Indices.push_back(numVertices + 6);
        buf->Indices.push_back(numVertices + 2);
        buf->Indices.push_back(numVertices + 1);
 
        buf->Indices.push_back(numVertices + 9);
        buf->Indices.push_back(numVertices + 8);
        buf->Indices.push_back(numVertices + 4);
        buf->Indices.push_back(numVertices + 4);
        buf->Indices.push_back(numVertices + 5);
        buf->Indices.push_back(numVertices + 9);
 
        buf->Indices.push_back(numVertices + 11);
        buf->Indices.push_back(numVertices + 10);
        buf->Indices.push_back(numVertices + 6);
        buf->Indices.push_back(numVertices + 6);
        buf->Indices.push_back(numVertices + 7);
        buf->Indices.push_back(numVertices + 11);
        numVertices += 12;
 
        x++; 
    }
EDIT 2:
CuteAlien wrote:I never coded a Minecraft, but I suppose you don't want to have real cubes at all. But calculate the outer layers. I remember some people talked in older threads about a libraray to calculate the corresponding geometry. Which can then be used in meshbuffers. But ... don't remember the name of that lib.
You're probably thinking of polyvox - it didn't meet my requirements, too much overhead at the scale I'm trying to work with.
But here's the website for that in case OP wants to take the slightly easier-ish route
http://www.volumesoffun.com/
"this is not the bottleneck you are looking for"
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: [RESOLVED]Minecraft alike game in Irrlicht

Post by Mel »

Look for something like eficient voxel rendering ^^U

If i ever got a cent for every "i want to create minecraft clone but i am not skilled with 3D" message i see...XD
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
SLC
Posts: 21
Joined: Mon Jan 06, 2014 9:41 pm

Re: [RESOLVED]Minecraft alike game in Irrlicht

Post by SLC »

If I remember correctly, MineTest is using Irrlicht. So you might find some inspiration there.
Post Reply