Page 1 of 1

[solved] mesh building is painfully slow & mesh flickers.

Posted: Sun Dec 27, 2015 4:10 am
by Cube_
exerpt from main function

Code: Select all

    level = loadMap("data/3.png", &tileset);
    SMesh *mesh = new SMesh();
    SMeshBuffer *buf = NULL;
    buf = new SMeshBuffer;
    std::cout << "building level" << std::endl;
    //This doesn't affect the speed at all, my theory is that buf->append ignores the fact that space is reserved already.
    //even though I'm specifically NOT setting the reserved space as used - 
    //append SHOULD put it in the unused reserved space
    buf->Indices.reallocate(level.size()*level[0].size());
    buf->Vertices.reallocate(level.size()*level[0].size());
    buildMesh(level, buf);
    mesh->addMeshBuffer(buf);
    buf->drop();
    ISceneNode *node = NULL;
 
    std::cout << "creating an octree scene node to speed things up" << std::endl;
    node = smgr->addOctreeSceneNode(mesh, 0, -1, 4096);
    node->setScale(vector3df(10.0f,10.0f,10.0f));
    node->setMaterialTexture(0, driver->getTexture("data/2.png"));
    node->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
    node->setMaterialFlag(video::EMF_WIREFRAME, false);
    node->setMaterialFlag(EMF_LIGHTING, false);
 
    while(iDevice->run())
    {
        driver->beginScene(true, true, SColor(255,140,255,140));
 
        smgr->drawAll();
 
        driver->endScene();
    }
    iDevice->drop();
function called

Code: Select all

void buildMesh(std::vector< std::vector< int > > input, SMeshBuffer *buf)
{
    //This code builds corridors based on tile data.
    //Currently it seems to generate some faces inverted and other faces on the wrong side of the grid
    //However I can't really get a good look since it'll flicker out of existence at weird angles!
    //Also it builds faces inside walls, this affects speed and memory usage but not drawing speed since it's an octree.
    //I actually don't know why though, most of these faces are generated in tiles where the content SHOULD be 1 (wall)
    //as opposed to 0 (AIR), image in post is an example of 1/0 expected (white is air, black is wall)
    int tile1;
    SColor c(255,255,255,255);
    for(int x = 0; x < input.size(); x++)
    {
        for(int y = 0; y < input[0].size(); y++)
        {
            tile1 = 0;
            if (x > 0)
                tile1 = input.at(x-1).at(y);
 
            if (tile1 == 0)
            {
                video::S3DVertex vertices[4] =
                {
                    //These windings should be correct, I'm not sure what Nx, Ny, Nz do so I copied them from known good code, and set them to 1 (this code uses increments of 1, the other code uses increments of 2 and has them set to 2
                    video::S3DVertex(x-0  ,  1  ,  y+0, -1, 1,-1, c, 0,0),
                    video::S3DVertex(x-0  ,  0  ,  y+0, -1,-1,-1, c, 0,1),
                    video::S3DVertex(x-0  ,  1  ,  y+1, -1, 1, 1, c, 1,0),
                    video::S3DVertex(x-0  ,  0  ,  y+1, -1,-1, 1, c, 1,1),
                };
                u16 indices[6] =   {2, 0, 1,
                                    1, 3, 2,};
 
                buf->append(vertices, 4, indices, 6);
            }
 
            tile1 = 0;
            if (x < (input.size() - 1))
                tile1 = input.at(x+1).at(y);
 
            if (tile1 == 0)
            {
                video::S3DVertex vertices[4] =
                {
                    video::S3DVertex(x+1  ,  1  ,  y+0,  1, 1,-1, c, 1,0),
                    video::S3DVertex(x+1  ,  0  ,  y+0,  1,-1,-1, c, 1,1),
                    video::S3DVertex(x+1  ,  1  ,  y+1,  1, 1, 1, c, 0,0),
                    video::S3DVertex(x+1  ,  0  ,  y+1,  1,-1, 1, c, 0,1),
                };
                u16 indices[6] =   {0, 2, 3,
                                    3, 1, 0,};
 
                buf->append(vertices, 4, indices, 6);
            }
 
            tile1 = 0;
            if (y > 0)
                tile1 = input.at(x).at(y-1);
 
            if (tile1 == 0)
            {
                video::S3DVertex vertices[4] =
                {
                    video::S3DVertex(x+0  ,  1  ,  y-1 , -1, 1, 1, c, 1,0),
                    video::S3DVertex(x+1  ,  1  ,  y-1 ,  1, 1, 1, c, 0,0),
                    video::S3DVertex(x+1  ,  0  ,  y-1 ,  1,-1, 1, c, 0,1),
                    video::S3DVertex(x+0  ,  0  ,  y-1 , -1,-1, 1, c, 1,1),
                };
                u16 indices[6] =   {3, 2, 1,
                                    1, 0, 3,};
 
                buf->append(vertices, 4, indices, 6);
            }
 
            tile1 = 0;
            if (y < input.at(0).size() - 1)
                tile1 = input.at(x).at(y+1);
 
            if (tile1 == 0)
            {
                video::S3DVertex vertices[4] =
                {
                    video::S3DVertex(x+0  ,  1  ,  y+0, -1, 1,-1, c, 0,0),
                    video::S3DVertex(x+1  ,  1  ,  y+0,  1, 1,-1, c, 1,0),
                    video::S3DVertex(x+1  ,  0  ,  y+0,  1,-1,-1, c, 1,1),
                    video::S3DVertex(x+0  ,  0  ,  y+0, -1,-1,-1, c, 0,1),
                };
                u16 indices[6] =   {0, 1, 2,
                                    2, 3, 0,};
 
                buf->append(vertices, 4, indices, 6);
            }
        }
    }
}
I'm not entirely certain why the mesh flickers in and out, other irrlicht projects with very similar meshing code do not (namely my main project, I'm trying to improve my slow mesher - it's too slow to be useful, 8.1 seconds for a 32^3 array, I haven't timed this 64^2 array but it's many seconds).

It's not a clipping issue either, first of all the mesh is huge, second of all I haven't ever seen the entire octree node get clipped.
Also it's not (likely) a driver issue - the same driver and irrlicht version can draw Q3 maps and 3D models loaded from elsewhere fine, logically the issue is thus with my code - but I don't know what it is.

Re: mesh building is painfully slow and mesh flickers.

Posted: Sun Dec 27, 2015 5:15 am
by chronologicaldot
Refresh the bounding box. That should fix the camera issue causing it to flicker.
Also, I found that I had to make S3DVertex instances const before I could add them to the buffer array or odd things would happen.

Re: mesh building is painfully slow and mesh flickers.

Posted: Sun Dec 27, 2015 6:45 am
by Cube_
Refresh the bounding box. That should fix the camera issue causing it to flicker.
... aight, got it.

What about the speed issue? I can't figure out why it's slow aside from guessing it's the appending, that's probably the problem but there's no feasible way to solve it as far as I can see, I tried using vectors of vertices and indices so I'd only have to append once - didn't work though.
can't use arrays either, because I can't push_back to an array and I can't do array[x*4][y*4] = vertices because that... plainly doesn't work, for 1 they're 1-4. (not to mention I can almost guarantee I can't append a multidimensional array to the mesh buffer - also not typesafe).
for 2 we're talking 8-12 (wait... aren't we losing 2 spots here? Yes sir, we are).

I could probably do vector->array->meshbuffer but that's just silly.


In any case, a mesh->recalculateBoundingBox(); did the trick for the flickering (although showing the bounding box for everything by setting node->setDebugDataVisible(scene::EDS_BBOX_ALL); shows two bounding boxes from what I can tell, one white for the mesh that's the correct size and one red that's way too large on X-, Y- and Z- (correct size on X+,Y+,Z+)... very peculiar although irrelevant

what REALLY matters is that it doesn't flicker - the speed is a huge problem though.

Re: mesh building is painfully slow and mesh flickers.

Posted: Sun Dec 27, 2015 11:14 pm
by chronologicaldot
Have a look at irrArray. What it actually does is have a u32 allocated and a u32 used. When you use push_back(), it doesn't allocate (unless the array is full), it increments the used. That said, it's safe to have:

Code: Select all

 
const S3DVertex v( stuff );
buffer->Vertices.push_back(v);
 
And this shouldn't cause any slow-down.
Part of your code's speed drop may have to do with the fact that you're repeatedly allocating arrays of four vertices. Since you're using SMeshBuffer, it's safe to directly access the vertices array (since SMeshBuffer only uses S3DVertex and not the other vertex types). That said, add vertices one at a time with push_back()

Re: mesh building is painfully slow and mesh flickers.

Posted: Sun Dec 27, 2015 11:22 pm
by Cube_
okay, I'm adding the vertices one at a time, that sorta works - it compiles and crashes

Code: Select all

                buf->Vertices.push_back(video::S3DVertex(x-0  ,  1  ,  y+1, -1, 1,-1, c, 0,0));
                buf->Vertices.push_back(video::S3DVertex(x+1  ,  1  ,  y+1,  1, 1,-1, c, 1,0));
                buf->Vertices.push_back(video::S3DVertex(x+1  ,  0  ,  y+1,  1,-1,-1, c, 1,1));
                buf->Vertices.push_back(video::S3DVertex(x-0  ,  0  ,  y+1, -1,-1,-1, c, 0,1));
                u16 indices[6] =   {0, 1, 2,
                                    2, 3, 0,};
 
                buf->Indices.push_back(indices);
If I'd have to wager a guess it's probably the indices that cause the crash.

EDIT: my assumption was correct.

Code: Select all

                buf->Vertices.push_back(video::S3DVertex(x-0  ,  1  ,  y+1, -1, 1,-1, c, 0,0));
                buf->Vertices.push_back(video::S3DVertex(x+1  ,  1  ,  y+1,  1, 1,-1, c, 1,0));
                buf->Vertices.push_back(video::S3DVertex(x+1  ,  0  ,  y+1,  1,-1,-1, c, 1,1));
                buf->Vertices.push_back(video::S3DVertex(x-0  ,  0  ,  y+1, -1,-1,-1, c, 0,1));
                //u16 indices[6] =   {0, 1, 2,
                //                    2, 3, 0,};
                buf->Indices.push_back(0);
                buf->Indices.push_back(1);
                buf->Indices.push_back(2);
                buf->Indices.push_back(2);
                buf->Indices.push_back(3);
                buf->Indices.push_back(0);
EDIT2: But, it seems that now everything is messed up, there are 20746 triangles all in the exact same location... odd.
the vertex locations are correct, and the indices are pushed back identically to before, but I don't have a clue what could be wrong - perhaps I should pass them as triplets?

EDIT3: SOLVED IT

Code: Select all

                buf->Vertices.push_back(video::S3DVertex(x+1  ,  1  ,  y+0,  1, 1,-1, c, 1,0));
                buf->Vertices.push_back(video::S3DVertex(x+1  ,  0  ,  y+0,  1,-1,-1, c, 1,1));
                buf->Vertices.push_back(video::S3DVertex(x+1  ,  1  ,  y+1,  1, 1, 1, c, 0,0));
                buf->Vertices.push_back(video::S3DVertex(x+1  ,  0  ,  y+1,  1,-1, 1, c, 0,1));
                buf->Indices.push_back(numVertices+0);
                buf->Indices.push_back(numVertices+1);
                buf->Indices.push_back(numVertices+3);
                buf->Indices.push_back(numVertices+3);
                buf->Indices.push_back(numVertices+2);
                buf->Indices.push_back(numVertices+0);
                numVertices+=4;

Re: [solved] mesh building is painfully slow & mesh flickers

Posted: Mon Dec 28, 2015 1:39 pm
by Kojack

Code: Select all

                    //These windings should be correct, I'm not sure what Nx, Ny, Nz do so I copied them from known good code, and set them to 1 (this code uses increments of 1, the other code uses increments of 2 and has them set to 2
                    video::S3DVertex(x-0  ,  1  ,  y+0, -1, 1,-1, c, 0,0),
Nx, Ny and Nz forms the surface normal. This is a vector that is perpendicular to the vertex. It should be a normalised value (length of 1). The surface normal is used for lighting.
In the first part of your code, the triangles were in the y/z plane (all the x values were the same). So the normals should be either -1,0,0 or 1,0,0 depending on which way the triangles are facing.
The later part of the code has triangles on the x/y plane, so the normals would be 0,0,-1 or 0,0,1.

Re: [solved] mesh building is painfully slow & mesh flickers

Posted: Wed Dec 30, 2015 3:39 am
by Cube_
huh, I guess I'll have to note that down. Although the normal values should be correct - in that they're all -1, 0, or 1. In any case it hardly matters, I'm going for that accurate 80's vibe so no lights :P

Re: [solved] mesh building is painfully slow & mesh flickers

Posted: Wed Dec 30, 2015 3:59 am
by Cube_
very strange - I built a new revision today and now the bounding box is back to the unscaled size (even though I perform a mesh->recalculateBoundingBox();

Code: Select all

    level = loadMap("data/2.png", &tileset);
    SMesh *mesh = new SMesh();
    SMeshBuffer *buf = NULL;
    buf = new SMeshBuffer;
    std::vector< std::vector< int > > wallData = convertMeta(level);
    std::cout << "building level" << std::endl;
    buf->Indices.reallocate(level.size()*level[0].size());
    buf->Vertices.reallocate(level.size()*level[0].size());
    buildMesh(wallData, buf); //this hasn't changed since yesterday when I made the last working build.
    mesh->addMeshBuffer(buf);
    buf->drop();
    ISceneNode *node = NULL;
 
    mesh->recalculateBoundingBox(); //wait, why isn't it working?
    node = smgr->addOctreeSceneNode(mesh, 0, -1, 4096);
    node->setScale(vector3df(10.0f,10.0f,10.0f));
    node->setMaterialTexture(0, driver->getTexture("data/t.png"));
    node->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
    node->setMaterialFlag(video::EMF_WIREFRAME, false);
    node->setMaterialFlag(EMF_LIGHTING, false);
    node->setMaterialFlag(video::EMF_BACK_FACE_CULLING, true);
    node->setDebugDataVisible(irr::scene::EDS_BBOX_ALL);
    std::vector<npc*> npcs;
    std::vector<entity*> entities;
    //buildEntities(npcs, entities, level); //this function is as of right now broken, hence commented out.
    //npcs.reserve(64);
 
    while(iDevice->run())
    {
        driver->beginScene(true, true, SColor(255,140,255,140));
 
        smgr->drawAll();
 
        driver->endScene();
    }
    iDevice->drop();
}
Indeed the relevant section of the meshing code is already in this thread - albeit with appropriate coordinate, winding, normal, and uv changes.
the mesh is of width*height tiles (64*64 in this example) - and the bounding box was correct yesterday.
I am very much perplexed about this.

additionally

Code: Select all

node->getMesh()->getMeshBuffer(0)->recalculateBoundingBox();
just returns |error: 'class irr::scene::ISceneNode' has no member named 'getMesh'|

not particularly useful - so I can't update the bounding box when it's attached to the node, and doing so prior to the node is unreliable since it doesn't actually do it.
I'm at loss.

Re: [solved] mesh building is painfully slow & mesh flickers

Posted: Wed Dec 30, 2015 4:13 am
by Cube_
ADDITIONALLY if I do

Code: Select all

mesh->getMeshBuffer(0)->recalculateBoundingBox();
    mesh->recalculateBoundingBox();
then it MAGICALLY works.

I don't know why, it's voodoo. but it's WORKING voodoo so whatever, I don't have time to figure out why.
(just using either of them does NOT work)

oh and it also solves my problem with the bounding box being too big.
now it's the perfect size.
again, voodoo.

Re: [solved] mesh building is painfully slow & mesh flickers

Posted: Wed Dec 30, 2015 1:33 pm
by Kojack
aaammmsterdddam wrote:huh, I guess I'll have to note that down. Although the normal values should be correct - in that they're all -1, 0, or 1. In any case it hardly matters, I'm going for that accurate 80's vibe so no lights :P
If you aren't doing lighting then it doesn't matter. :)
But in case you later decide to use lighting, it's not values of -1, 0 or 1 that are needed, it's a vector length of 1. In the code I quoted above, the surface normal was [-1, 1,-1]. That's a length of 1.73, not 1. (sqrt(nx*nx+ny*ny+nz*nz) should equal 1). The correct values would have been roughly [-0.577, 0.577, -0.577]. If lighting was enabled, the wrong normal length will make the surface darker or brighter than intended (depending on whether the normal is too short or too long).

Re: [solved] mesh building is painfully slow & mesh flickers

Posted: Wed Dec 30, 2015 6:38 pm
by chronologicaldot
aaammmsterdddam wrote:ADDITIONALLY if I do

Code: Select all

mesh->getMeshBuffer(0)->recalculateBoundingBox();
    mesh->recalculateBoundingBox();
then it MAGICALLY works.
That's because SMesh::recalculateBoundingBox() only adds the mesh buffer bounding boxes to its own. If the mesh buffer bounding boxes are not calculated, then the mesh bounding box will be wrong.

Re: [solved] mesh building is painfully slow & mesh flickers

Posted: Wed Dec 30, 2015 9:34 pm
by Cube_
chronologicaldot wrote:That's because SMesh::recalculateBoundingBox() only adds the mesh buffer bounding boxes to its own. If the mesh buffer bounding boxes are not calculated, then the mesh bounding box will be wrong.
I just don't get why either one alone doesn't work consistently.

if I just calculate the buffers bounding box I get a tiny red bounding box and a large white one. - mesh flickers.
if I just calculate the mesh bounding box I get a tiny red bounding box and a large white one. - mesh flickers.

presumably the red one is the buffer box and the white one is the mesh box, or vice versa - doesn't matter.

previously they were added together so that I got a bounding box that fit, and then extended past the mesh in X,Y,Z negative.

that was fine.

then I did the same thing and the red bounding box (the one that actually seems to matter) didn't change size, and then I did voodoo and now it's the correct size.

this to me leads to the assumption that they actually do the exact same thing. I any case it still feels like voodoo to me because mesh->recalculateBoundingBox() did work.

or to simplify: I don't get how an identical mesh will get a proper bounding box one day, and the next it doesn't even though I call no additional functions before creating the mesh and I did not change the mesh building algorithm or the metadata used in said algorithm at all.

in any case - it works, that's what matters right now.

Re: [solved] mesh building is painfully slow & mesh flickers

Posted: Thu Dec 31, 2015 6:42 am
by chronologicaldot
Perhaps an object file updated. *shrug* Who knows. Maybe a change in scale or whatnot set it off. Sometimes values of key variables have a tendency to only work by coincidence of everything else lining up right, and then you do something and voila, it stops working. Happens to me a bit. At any rate, you have to call the recalculateBoundingBox() on the buffer and the mesh and that will work (assuming the mesh is built correctly).

Re: [solved] mesh building is painfully slow & mesh flickers

Posted: Thu Dec 31, 2015 12:04 pm
by Cube_
I see - so the reason it worked before was the bug and not that I have to do it twice.
well, voodoo led to correct behavior for once - what a happy accident.

In any case, it doesn't matter much to me if it's right or wrong - just that it works (ordinarily it would but time constraints prevent me from thinking too much about it)