Page 1 of 1

[RESOLVED]Minecraft alike game in Irrlicht

Posted: Sat Feb 18, 2017 3:57 pm
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));
                }
            }
        }
    }

Re: Minecraft alike game in Irrlicht

Posted: Sat Feb 18, 2017 7:18 pm
by CuteAlien
Hm, search the forum for "minecraft" - there are a few threads discussing this. Maybe one of them helps.

Re: Minecraft alike game in Irrlicht

Posted: Sun Feb 19, 2017 3:17 pm
by fanaticguy
Thanks for an answer. Is creating a new SMesh object and appending it with meshbuffers a way to go?

Re: Minecraft alike game in Irrlicht

Posted: Sun Feb 19, 2017 8:06 pm
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.

Re: Minecraft alike game in Irrlicht

Posted: Mon Feb 20, 2017 12:55 am
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/

Re: [RESOLVED]Minecraft alike game in Irrlicht

Posted: Sun Feb 26, 2017 12:45 pm
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

Re: [RESOLVED]Minecraft alike game in Irrlicht

Posted: Sat Mar 04, 2017 7:35 am
by SLC
If I remember correctly, MineTest is using Irrlicht. So you might find some inspiration there.