Triangles not displayed properly. [SOLVED]

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
Wodzu
Posts: 27
Joined: Wed May 07, 2014 5:41 pm

Triangles not displayed properly. [SOLVED]

Post by Wodzu »

Hi guys.

I am having problem with displaying all the triangles from my mesh. I am fighting with this for many hours without any success, so I would much appreciate your help.

Here is a simplified case of my mesh:

Image

As you see, it is built from four triangles, I've enumerated vertices for convenience. Only X and Y are changing for each vertex, Z is always 0.

Now, I am trying to load this mesh into irrlicht:

Code: Select all

 
vertices.push_back(vector3df( 9, -4, 0));
vertices.push_back(vector3df( 9,  4, 0));
vertices.push_back(vector3df( 0,  0, 0));
vertices.push_back(vector3df(-9,  4, 0));
vertices.push_back(vector3df(-9, -4, 0));
 
indices.push_back(0); // 0->2->1 clockwise winding
indices.push_back(2);
indices.push_back(1);
 
indices.push_back(3); // 3->2->4 clockwise winding
indices.push_back(2);
indices.push_back(4);
 
indices.push_back(2); // 2->3->1 clockwise winding
indices.push_back(3);
indices.push_back(1);
 
indices.push_back(4); // 4->2->0 clockwise winding
indices.push_back(2);
indices.push_back(0);
 
vector3df normal;
for (u32 i = 0; i != indices.size(); i = i + 3) {
     
    color.set(rand() % 255, rand() % 255, rand() % 255, 0);
    u16 p1 = indices[i];
    u16 p2 = indices[i + 1];
    u16 p3 = indices[i + 2];
 
    //Perhaps for smooth lighting I should calculate normal based on each neighbouring vertices.
    normal = core::plane3df(vertices[p1], vertices[p2], vertices[p3]).Normal;
 
    meshBuffer->Vertices.push_back(video::S3DVertex(vertices[p1], normal, color, core::vector2df()));
    meshBuffer->Vertices.push_back(video::S3DVertex(vertices[p2], normal, color, core::vector2df()));
    meshBuffer->Vertices.push_back(video::S3DVertex(vertices[p3], normal, color, core::vector2df()));
 
    meshBuffer->Indices.push_back(p1);
    meshBuffer->Indices.push_back(p2);
    meshBuffer->Indices.push_back(p3);
}
meshBuffer->drop();
vertices.clear();
indices.clear();
 
As you can see in the code snippet, each triangle is constructed in clockwise winding. Also, I've checked and each normal is (0,0,-1). So at first glance, everything should be ok. Depending on the position of my camera I should either see all triangles or not see any. However, I see only some of them, take a look:

Code: Select all

 
    ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS();
    camera->setPosition(vector3df(0, 0, -110));
 
Image

Code: Select all

 
    ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS();
    camera->setPosition(vector3df(0, 0, 110));
 
Image


I do not understand this behaviour, can somone explain to me what is going on? It seems that winding / normal is still not ok. And even more - some triangles are not drawn on any side of my camera.
Maybe I need to sort indices in some other way before putting them to buffer?

Thanks for your help.
Last edited by Wodzu on Wed Feb 04, 2015 6:51 pm, edited 1 time in total.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Triangles not displayed properly.

Post by CuteAlien »

Don't see an error so far. SColor::set has the order a,r,g,b - just mentioning it as I guess you expected r,g,b,a given your rand()'s.
Can you post your complete example (you can use http://ideone.com/)? Then we can test without having to write our own example first - and also might notice if the problem is maybe something completely different than the lines above.
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
Wodzu
Posts: 27
Joined: Wed May 07, 2014 5:41 pm

Re: Triangles not displayed properly.

Post by Wodzu »

CuteAlien wrote:Don't see an error so far. SColor::set has the order a,r,g,b - just mentioning it as I guess you expected r,g,b,a given your rand()'s.
Exactly, I've messed that up, thanks. I was trying to color each triangle separately to help myself in seeing what is wrong, but colors are interpolated between vertices. I wanted to ask in another post how to turn of this interpolation.
CuteAlien wrote:Can you post your complete example (you can use http://ideone.com/)? Then we can test without having to write our own example first - and also might notice if the problem is maybe something completely different than the lines above.
Of course, here it is :)

Code: Select all

 
#include <irrlicht.h>
 
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
 
#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif
 
IAnimatedMesh* createMesh(io::IReadFile* file)
{
    array<vector3df> vertices;
    array<u16> indices; //Each index points to position in vertices.
 
    vertices.push_back(vector3df(9, -4, 0));
    vertices.push_back(vector3df(9, 4, 0));
    vertices.push_back(vector3df(0, 0, 0));
    vertices.push_back(vector3df(-9, 4, 0));
    vertices.push_back(vector3df(-9, -4, 0));
 
    indices.push_back(0);
    indices.push_back(2);
    indices.push_back(1);
 
    indices.push_back(3);
    indices.push_back(2);
    indices.push_back(4);
 
    indices.push_back(2);
    indices.push_back(3);
    indices.push_back(1);
 
    indices.push_back(4);
    indices.push_back(2);
    indices.push_back(0);
 
    SMesh* mesh = new SMesh();
    SMeshBuffer* meshBuffer = new SMeshBuffer();
    mesh->addMeshBuffer(meshBuffer);
 
    video::SColor color(255, 255, 0, 0);
    vector3df normal;
    for (u32 i = 0; i != indices.size(); i = i + 3) {
        u16 p1 = indices[i];
        u16 p2 = indices[i + 1];
        u16 p3 = indices[i + 2];
 
        //Perhaps for smooth lighting I should calculate normal based on each neighbouring vertices.
        normal = core::plane3df(vertices[p1], vertices[p2], vertices[p3]).Normal;
 
        color.set(255, rand() % 255, rand() % 255, rand() % 255);
        meshBuffer->Vertices.push_back(video::S3DVertex(vertices[p1], normal, color, core::vector2df()));
        meshBuffer->Vertices.push_back(video::S3DVertex(vertices[p2], normal, color, core::vector2df()));
        meshBuffer->Vertices.push_back(video::S3DVertex(vertices[p3], normal, color, core::vector2df()));
 
        meshBuffer->Indices.push_back(p1);
        meshBuffer->Indices.push_back(p2);
        meshBuffer->Indices.push_back(p3);
    }
    meshBuffer->drop();
 
    //Wrap mesh in animated mesh.
    SAnimatedMesh* animMesh = 0;
    if (0 != mesh->getMeshBufferCount())
    {
        mesh->recalculateBoundingBox();
        animMesh = new SAnimatedMesh();
        animMesh->Type = EAMT_OBJ;
        animMesh->addMesh(mesh);
        animMesh->recalculateBoundingBox();
    }
 
    mesh->drop();
 
    return animMesh;
}
 
int main()
{
    IrrlichtDevice *device = createDevice(video::EDT_OPENGL, dimension2d<u32>(640, 480), 16, false, false, false, 0);
    if (!device)
        return 1;
 
    IVideoDriver* driver = device->getVideoDriver();
    ISceneManager* smgr = device->getSceneManager();
    IAnimatedMesh* mesh = createMesh(NULL);
    if (!mesh)
    {
        device->drop();
        return 1;
    }
    IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode(mesh);
    node->setMaterialFlag(EMF_LIGHTING, false);
 
    ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS();
    camera->setPosition(vector3df(0, 0, -110));
 
    while (device->run())
    {
        driver->beginScene(true, true, SColor(255, 100, 101, 140));
        smgr->drawAll();
        driver->endScene();
    }
 
    device->drop();
    return 0;
}
 
Thank you CuteAlien:)
Kojack
Posts: 67
Joined: Sun Jan 20, 2008 2:39 am

Re: Triangles not displayed properly.

Post by Kojack »

Looks like when you are pushing the vertices into the meshbuffer, you are pushing them in the order specified by the indices, but then still using indices.
For example, your first triangle has indices of 0,2,1. So you are pushing vertex 2 into array element 1 and vertex 1 into element 2. Then the mesh will try to use the indices as well, causing the actual render order to become the original 0,1,2 vertices.

Do you you want the triangles to share colours at the vertices? At the moment you are making 12 vertices with unique colours, not 5 vertices with shared colours at each corner. I'm not sure if that's intended or not.

Easiest fix (but with 12 vertices and a wasted index buffer since it's just linear) would be to change this bit:

Code: Select all

    meshBuffer->Indices.push_back(i);
    meshBuffer->Indices.push_back(i+1);
    meshBuffer->Indices.push_back(i+2);
Wodzu
Posts: 27
Joined: Wed May 07, 2014 5:41 pm

Re: Triangles not displayed properly.

Post by Wodzu »

Kojack wrote:Looks like when you are pushing the vertices into the meshbuffer, you are pushing them in the order specified by the indices, but then still using indices.
I think I understand now my mistake. I thought that I am pushing 5 vertices to the Vertices but I am pushing 12 of them! And because of that my index buffer is wrong and uselles. Correct me if I am wrong but to properly utilize index buffer i should have two separate loops: one to push 5 vertices and one to push 12 indices.
Kojack wrote: Do you you want the triangles to share colours at the vertices? At the moment you are making 12 vertices with unique colours, not 5 vertices with shared colours at each corner. I'm not sure if that's intended or not.
I wanted to have each triangle in full color, so 3 vertices should have the same color. But now I see that if I use only 5 vertices the triangles will share a color on vertices and this will cause interpolation of color. So in other words, when I use only 5 vertices it will not be possible to have a solid different color for each triangle, right?
Kojack
Posts: 67
Joined: Sun Jan 20, 2008 2:39 am

Re: Triangles not displayed properly.

Post by Kojack »

Correct. You need unique vertices if the triangles have different colours. Either not using an index buffer (I don't know if irrlicht supports that on that mesh type) or renumbering in linear order like my code above should handle making the triangles independent.

It's the same thing with normals on sharp edges, they can't share vertices. For example, a proper cube mesh requires 24 vertices instead of 8, because every corner has 3 normals instead of 1, so needs 3 vertices.
Wodzu
Posts: 27
Joined: Wed May 07, 2014 5:41 pm

Re: Triangles not displayed properly.

Post by Wodzu »

Kojack wrote:It's the same thing with normals on sharp edges, they can't share vertices. For example, a proper cube mesh requires 24 vertices instead of 8, because every corner has 3 normals instead of 1, so needs 3 vertices.
Thanks about mentioning normals, I'd probably fell into the same trap and wonder why my lighting does not as intended.

But for the other hand, index buffer can save a lot of vertices, just looking at this example it is 5 instead of 12. How does that affect performance?
Kojack
Posts: 67
Joined: Sun Jan 20, 2008 2:39 am

Re: Triangles not displayed properly. [SOLVED]

Post by Kojack »

Wodzu wrote:But for the other hand, index buffer can save a lot of vertices, just looking at this example it is 5 instead of 12. How does that affect performance?
Without indexing the vertex cache isn't used. If the indexing has duplicates, then the cache doesn't know they are duplicates. So the vertex shader would be called (either explicitly if you have shaders, or internally if you are running fixed function) 12 times instead of 5. For just the shape you have above, that's a microscopic difference. But if you had tons of these on screen it would start building up.
Post Reply