[Solved]: Define polygon face using mixed triangle quad...

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
thanhle
Posts: 325
Joined: Wed Jun 12, 2013 8:09 am

[Solved]: Define polygon face using mixed triangle quad...

Post by thanhle »

Dear guys,
I'm having some trouble creating a custom mesh loader. I'm using version 1.8.1.

I need to confirm the following:

1) Can I specify indices as triangle as well Quad or arbitrary polygon indices in the same indices list inside SMeshBuffer?
The problem I have in loading a mesh is that it has different polygon faces. 3, 4 or n vertices sides polygons.
If I create triangle indices then I have no idea how to automate the clockwise winding.

The structure of the mesh is attached below.

2) Or The indices must represent triangles? such that number of indices = number of triangles*3?

3) Third question. Is there function to automatically fix the winding?

Thanks guys

Code: Select all

 
ifstream iFile(filename);
            std::string line;
 
            std::vector<std::vector<std::string>> vecValues;
 
            while (getline(iFile, line)) {
                /* Printing goes here. */
                if (line == "*") break;
            }
            getline(iFile, line);
 
            std::vector<vector3df> listPos;
            int posCount = std::stoi(line);
 
            for (int i = 0; i < posCount; ++i)
            {
                getline(iFile, line);
                std::vector<std::string> out = split(line, ' ');
                listPos.push_back(vector3df(std::stof(out[0]), std::stof(out[1]), std::stof(out[2])));
            }
 
            getline(iFile, line); //A zero here.
            getline(iFile, line);
 
            std::vector<std::vector< int>> listLinePair;
            int lineListPairCount = std::stoi(line);
            for (int i = 0; i < lineListPairCount; ++i)
            {
                getline(iFile, line);
                std::vector<std::string> out = split(line, ' ');
                std::vector<int> vals;
                for (int j = 0; j < out.size(); ++j)
                {
                    vals.push_back(std::stoi(out[j]));
                }
                listLinePair.push_back(vals);
            }
 
            std::vector<std::vector<int>> lisFacesIndexes;  //Positive and -ve are the directions of the line joins
            getline(iFile, line);
            int linefaceCount = std::stoi(line);
            for (int i = 0; i < linefaceCount; ++i)
            {
                getline(iFile, line);
                std::vector<std::string> out = split(line, ' ');
                
                std::vector<int> vals;
                for (int j = 0; j < out.size(); ++j)
                {
                    vals.push_back(std::stoi(out[j]));
                }
                lisFacesIndexes.push_back(vals);
            }
 
            /* While there is still a line. */
            while (getline(iFile, line)) {
                /* Printing goes here. */
 
            }
 
            iFile.close();
    
            irr::scene::SMesh* Mesh = new irr::scene::SMesh();
 
            SMeshBuffer *buf = 0;
            buf = new SMeshBuffer();
            Mesh->addMeshBuffer(buf);
            buf->drop();
 
            buf->Vertices.reallocate(posCount);
            buf->Vertices.set_used(posCount);
        
            float scaleFactor = 0.01;
            for (int i = 0; i < posCount; ++i)
            {
                vector3df p = scaleFactor*listPos[i];
                buf->Vertices[i] = video::S3DVertex(p.X, p.Z, p.Y, 1, 1, 1,
                    video::SColor(255, 255, 255, 255),1, 1);
 
            }
 
                        //Perform adding indices here.
                      for (int i = 0; i < linefaceCount; ++i)
            {
            
                int faceIndexesCount = lisFacesIndexes[i].size();
                std::vector<int> vecFaceIndex = lisFacesIndexes[i];
                int previousIndex = -1;
                int beginIndex = -1;
                int verticeCount = 0;
                int totalVertice = 0;
 
              std::vector< vector<int>> lstTriIndexes;
        std::vector<int> vec;
        for (int j = faceIndexesCount - 1; j >= 1; --j)
                    {
                        int pairValJ = abs(vecFaceIndex[j]) - 1;
                        std::vector<int> lstIndexes = listLinePair[pairValJ];
                        if (vecFaceIndex[j] > 0)
                        {
                            for (int k = lstIndexes.size() - 1; k >= 0; --k)
                            {
                                int index = lstIndexes[k];
 
                                if (previousIndex != index)
                                {
                                    System::Diagnostics::Debug::WriteLine(index.ToString());
                                    totalVertice++;
                                    verticeCount++;
                                    vec.push_back(index);
                                    previousIndex = index;
                                }
                                if (verticeCount == 3) //Triangle created. Make new one
                                {
                                    lstTriIndexes.push_back(vec);
                                    vec = vector < int >() ;
                                
                                    verticeCount = 0;
                                    previousIndex = -1;
                                }
                            }
                        }
                        else
                        {
                            for (int k = 0; k < lstIndexes.size(); ++k)  //Winding back  anti clockwise
                            {
                                int index = lstIndexes[k];
                                if (previousIndex != index)
                                {
                                    totalVertice++;
                                    verticeCount++;
                                    vec.push_back(index);
                                    previousIndex = index;
                                }
 
                                if (verticeCount == 3) //Triangle created. Make new one
                                {
                                    lstTriIndexes.push_back(vec);
                                    vec = vector < int >();
                                    verticeCount = 0;
                                    previousIndex = -1;
                                }
                            }
                        }
                    }
            
                for (int j = 0; j < lstTriIndexes.size(); ++j)
                {
                    vector<int> v = lstTriIndexes[j];
                    if (j < lstTriIndexes.size() - 1)
                    {
                        for (int k = 0; k < v.size(); ++k)
                        {
                            buf->Indices.push_back(v[k]);
                        }
                    }
                    else
                    {
                        buf->Indices.push_back(v[2]);
                        buf->Indices.push_back(v[0]);
                        buf->Indices.push_back(v[1]);
                    
                    }
                }
            }
 
            buf->recalculateBoundingBox();
    
            Mesh->recalculateBoundingBox();
            IMeshSceneNode* myNode = smgr->addMeshSceneNode(Mesh);
    
            smgr->getMeshManipulator()->recalculateNormals(myNode->getMesh(), true, true);
            smgr->getMeshManipulator()->recalculateTangents(myNode->getMesh(), false, false,false);
            
 
            myNode->setMaterialFlag(video::EMF_BACK_FACE_CULLING, true);
            myNode->setMaterialFlag(video::EMF_LIGHTING, true);
            myNode->setMaterialFlag(video::EMF_GOURAUD_SHADING, true);
            myNode->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true);
 
            myNode->setDebugDataVisible(E_DEBUG_SCENE_TYPE::EDS_NORMALS);
            myNode->setMaterialTexture(0, smgr->getVideoDriver()->getTexture("media/wall.bmp"));
 
 

Simple mesh...

Code: Select all

 
8 //No of vertices
6000.000000 -750.000000 300.000000
6000.000000 750.000000 300.000000
0.000000 750.000000 300.000000
0.000000 -750.000000 300.000000
0.000000 750.000000 0.000000
6000.000000 750.000000 0.000000
6000.000000 -750.000000 0.000000
0.000000 -750.000000 0.000000
0 //Not in used
12 //No of lines joining between two vertices
6 7
5 6
4 5
7 4
3 0
0 1
1 2
2 3
7 3
2 4
1 5
0 6
6 //Number of faces.
//nlines lineid1 lineId2...lineIDnLines
4 4 3 2 1
4 5 6 7 8
4 -4 9 -8 10
4 -3 -10 -7 11
4 -2 -11 -6 12
4 -1 -12 -5 -9
 
//Difficultmesh.. Eg. faces section

Code: Select all

 
4 -283 -312 -234 -278
4 -192 -15 -175 313
4 -198 -313 -179 -300
4 -279 314 -194 -287
4 -118 -23 -199 -314
5 315 316 317 318 319
5 320 321 322 323 -101
5 -99 324 -306 -309 -111
9 325 -42 -294 -297 -296 -291 -292 -45 -18
4 -212 326 -280 -109
4 -308 -326 327 -112
3 328 329 330
4 331 332 333 334
5 335 336 337 338 339
3 340 341 342
4 -240 -135 -267 343
4 -299 -261 -288 -196
5 344 345 346 347 348
3 349 350 351
6 352 353 354 355 356 357
4 358 -3 359 -47
4 360 -4 -358 -48
4 -360 -49 361 -1
0
0
 
Last edited by thanhle on Sat Jan 10, 2015 4:00 pm, edited 3 times in total.
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Define polygon face using mixed triangle quad and polygo

Post by mongoose7 »

Only triangles can be rendered, so you have to replace the quads with triangles. If (1 2 3 4) is the correct winding for a quad, the triangles should be (1 2 3) (1 3 4). I don't believe there is a function to correct the winding as this is a sematical issue, not a syntactical one (you have to have a notion of inside and outside, which doesn't exist for a triangle on its own).
thanhle
Posts: 325
Joined: Wed Jun 12, 2013 8:09 am

Re: Define polygon face using mixed triangle quad and polygo

Post by thanhle »

Thanks for input Mongoose,
Since this format is not created by me so I don't know the exact way to unfold the windings.

I guest I'll need to hack up an algorithm to unfold the winding for this format.

Cheers
thanh
thanhle
Posts: 325
Joined: Wed Jun 12, 2013 8:09 am

Re: Define polygon face using mixed triangle quad and polygo

Post by thanhle »

Hi Mongoose,
I got the mesh loaded. But I think the winding is still wrong as I tried to load the texture. It said texture is loaded but it is not shown correctly.

I used the below to compute the normal. It generated the correct normal line as shown in the pic below. This is similar to the inbuilt box mesh normal.

smgr->getMeshManipulator()->recalculateNormals(myNode->getMesh(), true, true);
smgr->getMeshManipulator()->recalculateTangents(myNode->getMesh(), false, false,false);

I have updated my code above.

Image

I need another confirmation :).

if (1 2 3 4) is the correct winding for a quad.
Can I use (1 2 3) then (3 4 1) ? Or do I have to begin with (1 3 4) like you mentioned?

For the case in the picture. If the quad is (3 0 6 7) can I start with (0 6 7) then (7 3 0) ?
Or can I start with (7 3 0) then (0 6 7) ?

Thanks
thanh
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Define polygon face using mixed triangle quad and polygo

Post by CuteAlien »

Enable backface-culling in the material. Then you see the places where it works correct/wrong very quickly.

edit: Basically think about the camera looking at it - then the polygon index order has to be clockwise for each polygon.
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
thanhle
Posts: 325
Joined: Wed Jun 12, 2013 8:09 am

Re: Define polygon face using mixed triangle quad and polygo

Post by thanhle »

Thanks CutieAlien,
I've fixed the winding. But texture doesn't seems to load. I need to fix this :).

I found out that for index order of quad to triangle must follow a rule for shading to work correctly.
If the quad is (3 0 6 7). Tri1 = (3 0 6), tri2 must be equals to (3 6 7) in order for flat shading to work correctly. E.g. both triangle must starting with vertice 3.

Goroud shading works without following this rule.

Regards
thanh
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: Define polygon face using mixed triangle quad and polygo

Post by hendu »

Irr does not support anything except triangles in mesh buffers, my fork has the support (so quads, points etc can be used there).
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Define polygon face using mixed triangle quad and polygo

Post by mongoose7 »

Have you set texture coordinates?
thanhle
Posts: 325
Joined: Wed Jun 12, 2013 8:09 am

Re: Define polygon face using mixed triangle quad and polygo

Post by thanhle »

Hi Mongoose,
As I don't know the correct way to create the texture coordinate when read in the custom mesh.
I will try to code an interface to do that.
Do you have any tip for creating texture coordinate on the fly?

For example if I have a Quad with vertice (1234). E.g. I will use triangle selector to find the nearest vertice to obtain these.

Can I manually define texture coordinate for them. E.g. if I only want a texture on the bounded region.

thanks
thanh
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Define polygon face using mixed triangle quad and polygo

Post by mongoose7 »

1. You are writing a loader so you do not in general know the shape of the object.
2. To algorithmically derive texture coordinates on-the-fly requires data on the size of the object, which is not known until the end.

Perhaps set (u, v) = (.5, .5) + (x, y)/B/2, where B is large enough so that u and v are less than 1. This is just front projection.

Note that the common 3D file formats contain texture coordinates.
Foaly
Posts: 142
Joined: Tue Apr 15, 2014 8:45 am
Location: Germany

Re: Define polygon face using mixed triangle quad and polygo

Post by Foaly »

You could write an importer for blender (which supports n-gons).
There you have many ways of creating texture coordinates.
After that, you just export it in a format which Irrlicht can load
thanhle
Posts: 325
Joined: Wed Jun 12, 2013 8:09 am

]Solved!] Define polygon face using mixed triangle quads...

Post by thanhle »

Thanks Mongoose,
that gave me an idea.

I use the method to determine minX, maxX, minY and maxY.
XSpan = maxX - minX
YSpan = maxY - minY;

Then just do below inside a loop.

TCoords.set((v.X - minX) /XSpan, (v.Y - minY) /YSpan)

That give me a front and a back face.

I think I use a little algebra to stitch the other faces. Maybe that is a cube map?

Cheers
thanh
Post Reply