[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.
Post Reply
randomMesh
Posts: 1186
Joined: Fri Dec 29, 2006 12:04 am

[Solved] Need help computing indices

Post by randomMesh »

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:

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:

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..."
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Need help computing indices

Post by CuteAlien »

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.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
randomMesh
Posts: 1186
Joined: Fri Dec 29, 2006 12:04 am

Re: Need help computing indices

Post by randomMesh »

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..."
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: [Solved] Need help computing indices

Post by Mel »

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
Post Reply