[Solved] Need help computing indices

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.

[Solved] Need help computing indices

Postby randomMesh » Fri May 19, 2017 8:03 pm

Hi,

i try to render a cube in a mesh buffer. It should be possible to remove arbitrary faces during the construction of this buffer, e.g. render the cube with only the right face. (The construction method is called every frame).

Minimal compilable example to render all faces:
cpp Code: Select all
 
#include <irrlicht.h>
 
int main()
{
    irr::IrrlichtDevice* const device = irr::createDevice(
            irr::video::EDT_OPENGL);
    if (!device)
        return 1;
 
    irr::video::IVideoDriver* const driver = device->getVideoDriver();
    irr::scene::ISceneManager* const smgr = device->getSceneManager();
 
    smgr->addCameraSceneNode(0, irr::core::vector3df(0.5, 0.5, -2));
 
    irr::video::SMaterial material;
    material.Lighting = false;
 
    irr::video::ITexture* const texture = driver->getTexture(
            "./irrlicht-svn/media/wall.bmp");
    if (texture)
        material.setTexture(0, texture);
 
    const unsigned int numIndices = 36;
    const unsigned short indices[numIndices] =
    {
        //front
        0, 2, 1,
        0, 3, 2,
 
        //right
        1, 5, 4,
        1, 2, 5,
 
        //back
        4, 6, 7,
        4, 5, 6,
 
        //left
        7, 3, 0,
        7, 6, 3,
 
        //top
        9, 5, 2,
        9, 8, 5,
 
        //bottom
        0, 11, 10,
        0, 10, 7
    };
 
    irr::scene::SMeshBuffer buffer;
 
    irr::video::SColor color(255, 255, 255, 255);
 
    irr::f32 cubeSize = 1.0f;
    irr::f32 xPos = 0.0f;
    irr::f32 yPos = 0.0f;
 
    //0 [front, left, bottom]
    buffer.Vertices.push_back(
            irr::video::S3DVertex(xPos, 0, yPos, -1, -1, -1, color, 0, 1));
 
    //1 [front, right]
    buffer.Vertices.push_back(
            irr::video::S3DVertex(xPos + cubeSize, 0, yPos, 1, -1, -1, color, 1,
                    1));
 
    //2 [front, right, top]
    buffer.Vertices.push_back(
            irr::video::S3DVertex(xPos + cubeSize, 1, yPos, 1, 1, -1, color, 1,
                    0));
 
    //3 [front, left]
    buffer.Vertices.push_back(
            irr::video::S3DVertex(xPos, 1, yPos, -1, 1, -1, color, 0, 0));
 
    //4 [right, back]
    buffer.Vertices.push_back(
            irr::video::S3DVertex(xPos + cubeSize, 0, yPos + 1, 1, -1, 1, color,
                    0, 1));
 
    //5 [right, back, top]
    buffer.Vertices.push_back(
            irr::video::S3DVertex(xPos + cubeSize, 1, yPos + 1, 1, 1, 1, color,
                    0, 0));
 
    //6 [back, left]
    buffer.Vertices.push_back(
            irr::video::S3DVertex(xPos, 1, yPos + cubeSize, -1, 1, 1, color, 1,
                    0));
 
    //7 [back, left, bottom]
    buffer.Vertices.push_back(
            irr::video::S3DVertex(xPos, 0, yPos + cubeSize, -1, -1, 1, color, 1,
                    1));
 
    //8 [top]
    buffer.Vertices.push_back(
            irr::video::S3DVertex(xPos, 1, yPos + cubeSize, -1, 1, 1, color, 0,
                    1));
 
    //9 [top]
    buffer.Vertices.push_back(
            irr::video::S3DVertex(xPos, 1, yPos, -1, 1, -1, color, 1, 1));
 
    //10 [bottom]
    buffer.Vertices.push_back(
            irr::video::S3DVertex(xPos + cubeSize, 0, yPos + cubeSize, 1, -1, 1,
                    color, 1, 0));
 
    //11 [bottom]
    buffer.Vertices.push_back(
            irr::video::S3DVertex(xPos + cubeSize, 0, yPos, 1, -1, -1, color, 0,
                    0));
 
    for (irr::u32 j = 0; j < numIndices; ++j)
    {
        buffer.Indices.push_back(indices[j]);
    }
 
    while (device->run())
    {
        driver->beginScene();
 
        driver->setTransform(irr::video::ETS_WORLD, irr::core::IdentityMatrix);
        driver->setMaterial(material);
        driver->drawMeshBuffer(&buffer);
 
        smgr->drawAll();
 
        driver->endScene();
    }
 
    device->drop();
 
    return 0;
}
 


In order to render only the faces i want to, i tried this:
cpp Code: Select all
 
bool drawFront = false; //will be set with a function
bool drawRight = false;
bool drawBack = false;
bool drawLeft = false;
bool drawTop = true;
bool drawBottom = false;
 
//0 front, left, bottom
if (drawFront || drawLeft || drawBottom)
{
    buffer.Vertices.push_back(irr::video::S3DVertex(
        xPos, 0, yPos, -1, -1, -1, color, 0, 1));
}
 
//1 front, right
if (drawFront || drawRight)
{
    buffer.Vertices.push_back(irr::video::S3DVertex(
        xPos + cubeSize, 0, yPos, 1, -1,    -1, color, 1, 1));
}
 
//2 front, right, top
if (drawFront || drawRight || drawTop)
{
    buffer.Vertices.push_back(irr::video::S3DVertex(
        xPos + cubeSize, 1, yPos, 1, 1, -1, color, 1, 0));
}
 
//3 front, left
if (drawFront || drawLeft)
{
    buffer.Vertices.push_back(irr::video::S3DVertex(
        xPos, 1, yPos, -1, 1, -1, color, 0, 0));
}
 
//4 right, back
if (drawRight || drawBack)
{
    buffer.Vertices.push_back(irr::video::S3DVertex(
        xPos + cubeSize, 0, yPos + 1, 1, -1, 1, color, 0, 1));
}
 
//5 right, back, top
if (drawRight || drawBack || drawTop)
{
    buffer.Vertices.push_back(irr::video::S3DVertex(
        xPos + cubeSize, 1, yPos + 1, 1, 1, 1, color, 0, 0));
}
 
//6 back, left
if (drawBack || drawLeft)
{
    buffer.Vertices.push_back(irr::video::S3DVertex(
        xPos, 1, yPos + cubeSize, -1, 1, 1, color, 1, 0));
}
 
//7 back, left, bottom
if (drawBack || drawLeft || drawBottom)
{
    buffer.Vertices.push_back(irr::video::S3DVertex(
        xPos, 0, yPos + cubeSize, -1, -1, 1, color, 1, 1));
}
 
//8 top
if (drawTop)
{
    buffer.Vertices.push_back(irr::video::S3DVertex(
        xPos, 1, yPos + cubeSize, -1, 1, 1, color, 0, 1));
}
 
//9 top
if (drawTop)
{
    buffer.Vertices.push_back(irr::video::S3DVertex(
        xPos, 1, yPos, -1, 1, -1, color, 1, 1));
}
 
//10 bottom
if (drawBottom)
{
    buffer.Vertices.push_back(irr::video::S3DVertex(
        xPos + cubeSize, 0, yPos + cubeSize, 1, -1, 1, color, 1, 0));
}
 
//11 bottom
if (drawBottom)
{
    buffer.Vertices.push_back(irr::video::S3DVertex(
        xPos + cubeSize, 0, yPos, 1, -1, -1, color, 0, 0));
}
 
 
if (drawFront)
{
    buffer.Indices.push_back(0);
    buffer.Indices.push_back(2);
    buffer.Indices.push_back(1);
 
    buffer.Indices.push_back(0);
    buffer.Indices.push_back(3);
    buffer.Indices.push_back(2);
}
 
if (drawRight)
{
    buffer.Indices.push_back(1);
    buffer.Indices.push_back(5);
    buffer.Indices.push_back(4);
 
    buffer.Indices.push_back(1);
    buffer.Indices.push_back(2);
    buffer.Indices.push_back(5);
}
 
if (drawBack)
{
    buffer.Indices.push_back(4);
    buffer.Indices.push_back(6);
    buffer.Indices.push_back(7);
 
    buffer.Indices.push_back(4);
    buffer.Indices.push_back(5);
    buffer.Indices.push_back(6);
}
 
if (drawLeft)
{
    buffer.Indices.push_back(7);
    buffer.Indices.push_back(3);
    buffer.Indices.push_back(0);
 
    buffer.Indices.push_back(7);
    buffer.Indices.push_back(6);
    buffer.Indices.push_back(3);
}
 
if (drawTop)
{
    buffer.Indices.push_back(9);
    buffer.Indices.push_back(5);
    buffer.Indices.push_back(2);
 
    buffer.Indices.push_back(9);
    buffer.Indices.push_back(8);
    buffer.Indices.push_back(5);
}
 
if (drawBottom)
{
    buffer.Indices.push_back(0);
    buffer.Indices.push_back(11);
    buffer.Indices.push_back(10);
 
    buffer.Indices.push_back(0);
    buffer.Indices.push_back(10);
    buffer.Indices.push_back(7);
}
 


This won't work since the indices are wrong. (Imagine, only bottom face should be rendered, the indices 0, 11, 10 become 0, 2, 1 and so on).

So how to get the indices right?
Last edited by randomMesh on Sun May 21, 2017 7:31 pm, edited 2 times in total.
"Whoops..."
User avatar
randomMesh
 
Posts: 1178
Joined: Fri Dec 29, 2006 12:04 am

Re: Need help computing indices

Postby CuteAlien » Sat May 20, 2017 10:56 am

Easiest way - always push all vertices. You could even make them static (thought you would have to set IVideoDriver::setMinHardwareBufferVertexCount to a lower number or Irrlicht ignores static for such small meshbuffers).

Otherwise you would need to use one more array which remembers which index you used for which vertex (aka you write into it on push_back and read from it when using the indices).
IRC: #irrlicht on irc.freenode.net
Code snippets, patches&stuff: http://www.michaelzeilfelder.de/irrlicht.htm
Free racer created with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
User avatar
CuteAlien
Admin
 
Posts: 8192
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany

Re: Need help computing indices

Postby randomMesh » Sat May 20, 2017 11:07 am

Hi,

thank you for your answer.
CuteAlien wrote:Easiest way - always push all vertices.

I want to avoid this since this isn't the only cube. I try to render lots of them in the same buffer (no, no Minecraft clone. Really. ;) ). I just reduced the code for the sake of readability.

CuteAlien wrote:Otherwise you would need to use one more array which remembers which index you used for which vertex (aka you write into it on push_back and read from it when using the indices).

I have no clue yet how this should look like, but i'll try.
"Whoops..."
User avatar
randomMesh
 
Posts: 1178
Joined: Fri Dec 29, 2006 12:04 am

Re: [Solved] Need help computing indices

Postby Mel » Tue May 30, 2017 2:52 pm

Decompose the problem into a face building problem and use the "drawIndexedTriangleList" method instead of the "drawMeshBuffer" method. If the vertices don't need to be shared, it is even simpler, as the facebuilding method can be independent for every for every face. keep a track of the amount of faces you've built using a "index shift" counter that you increase by 6 every time you create a new quad (or by the amount of indices you need, every time you build a new face) then just provide the vertex array and the index array to the drawIndexedTriangleList method to draw this sort of dynamic mesh.

PRO: can be fully dynamic, CON: it can't be streamed, because doesn't use a meshbuffer, so that possible optimization isn't available. But it is not as if meshbuffer streaming is actually working in Irrlicth...

Actually i don't know if it is possible to remove vertices at will from a meshbuffer, although it could be an option that you could change the amount of triangles you want to output "on the fly" from a meshbuffer, so it could be possible to have a meshbuffer full of vertices, and only draw those primitives you want in each meshbuffer. I.E. add a "setOutputPrimitiveCount" method to the IMeshBuffer objects so it drawn only the amount of triangles you need.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
User avatar
Mel
Competition winner
 
Posts: 2196
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain


Return to Beginners Help

Who is online

Users browsing this forum: No registered users and 1 guest