source: GTP/trunk/App/Demos/Vis/FriendlyCulling/Converter/ObjConverter2.cpp @ 3371

Revision 3371, 14.1 KB checked in by mattausch, 15 years ago (diff)

fehler tritt nicht auf!!

Line 
1#include "ObjConverter2.h"
2#include "SimpleTri.h"
3#include "SimpleVec.h"
4#include "gzstream.h"
5#include <iostream>
6
7
8using namespace std;
9
10
11static void LoadIndices(char *str,
12                                                const VertexArray &vertices,
13                                                const VertexArray &normals,
14                                                const TexcoordArray &texcoords,
15                                                VertexArray &faceVertices,
16                                                VertexArray &faceNormals,
17                                                TexcoordArray &faceTexcoords
18                                                )
19{
20        vector<string> triples;
21
22        char *next_token;
23
24        // extract the triples of the form v/t/n v/t/n ...
25        char *pch = strtok_s(str + 1, " ", &next_token);
26
27        while (pch)
28        {
29                string s(pch);
30                triples.push_back(s);
31               
32                pch = strtok_s(NULL, " ", &next_token);   
33        }
34
35        // throw away last symbol (\n)
36        triples.back().resize(triples.back().size() - 1);
37
38        vector<int> indices;
39        vector<int> nIndices;
40        vector<int> tIndices;
41
42        char seps[] = " ";
43        char seps2[] = "/";
44
45        for (size_t i = 0; i < triples.size(); ++ i)
46        {
47                //cout << "triple " << i << " " << triples[i] << endl;
48                size_t found;
49                found = triples[i].find_first_of(seps2);
50                size_t prevfound = 0;
51
52                // extract vertex, normal, texture indices
53                string str = triples[i].substr(prevfound, found);
54
55                int index = (int)strtol(str.c_str(), NULL, 10) - 1;
56                int tIndex = index;
57                int nIndex = index;     
58               
59                // try to extract texture and normal indices
60                prevfound = found + 1;
61                found = triples[i].find_first_of(seps2, prevfound); 
62
63                if (found != string::npos)
64                {
65                        str = triples[i].substr(prevfound, found);
66
67                        int idx = (int)strtol(str.c_str(), NULL, 10) - 1;
68                        if (idx > 0) tIndex = idx;
69                }
70               
71                if (found != string::npos)
72                {
73                        str = triples[i].substr(found + 1);
74
75                        int idx = (int)strtol(str.c_str(), NULL, 10) - 1;
76                        if (idx > 0) nIndex = idx;
77                }
78
79                // store indices
80                if (index >= 0)
81                {
82                        indices.push_back(index);
83                        nIndices.push_back(nIndex);
84                        tIndices.push_back(tIndex);
85
86                        //cout << index << " " << tIndex << " " << nIndex << endl;
87                }
88
89                int idx[3];
90                // new triangle found
91                if (indices.size() > 2)
92                {
93                        // change orientation of faces?
94#if 1
95                        idx[0] = 0;
96                        idx[1] = (int)indices.size() - 2;
97                        idx[2] = (int)indices.size() - 1;
98#else
99                        idx[2] = 0;
100                        idx[1] = (int)indices.size() - 2;
101                        idx[0] = (int)indices.size() - 1;
102#endif
103
104                        for (int j = 0; j < 3; ++ j)
105                                faceVertices.push_back(vertices[indices[idx[j]]]);
106
107
108                        if (!normals.empty())
109                        {
110                                for (int j = 0; j < 3; ++ j)
111                                        faceNormals.push_back(Normalize(normals[nIndices[idx[j]]]));
112                        }
113                        else
114                        {
115                                // no face normals? => create normals
116                                const SimpleTri tri(vertices[indices[idx[0]]],
117                                                        vertices[indices[idx[1]]],
118                                                                        vertices[indices[idx[2]]]);
119
120                                const SimpleVec n = tri.GetNormal();
121
122                                faceNormals.push_back(n);
123                                faceNormals.push_back(n);
124                                faceNormals.push_back(n);
125                        }
126
127                        if (!texcoords.empty())
128                        {
129                                for (int j = 0; j < 3; ++ j)
130                                {
131                                        const int tidx = min((int)texcoords.size() - 1, tIndices[idx[j]]);
132                                        faceTexcoords.push_back(texcoords[tidx]);
133                                }
134                        }
135                }
136        }
137}
138
139
140ObjConverter2::ObjConverter2()
141{}
142
143
144ObjConverter2::~ObjConverter2()
145{
146        for (size_t i = 0; i < mGeometry.size(); ++ i)
147                delete mGeometry[i];
148       
149        mGeometry.clear();
150}
151
152
153void ObjConverter2::LoadShape(const VertexArray &faceVertices,
154                                                          const VertexArray &faceNormals,
155                                                          const vector<Texcoord> &faceTexcoords,
156                                                          Material *mat)
157{
158        int numElements = (int)faceVertices.size();
159        Geometry *geom = new Geometry();
160
161        // convert the triangles to geometry
162        geom->mVertices = new SimpleVec[numElements];
163        geom->mNormals = new SimpleVec[numElements];
164        geom->mTexcoords = new Texcoord[numElements];
165
166        geom->mVertexCount = numElements;
167        geom->mTexcoordCount = (int)faceTexcoords.size();
168
169        geom->mMaterial = mat;
170
171        cout << "creating new geometry with " << numElements << " vertices" << endl;
172
173        for (int i = 0; i < numElements; ++ i)
174        {
175#if 1
176                // convert to our camera system: change y and z
177                geom->mVertices[i].x = faceVertices[i].x;
178                geom->mVertices[i].y = -faceVertices[i].z;
179                geom->mVertices[i].z = faceVertices[i].y;
180       
181                geom->mNormals[i].x = faceNormals[i].x;
182                geom->mNormals[i].y = -faceNormals[i].z;
183                geom->mNormals[i].z = faceNormals[i].y;
184
185#else
186
187                geom->mVertices[i].x = faceVertices[i].x;
188                geom->mVertices[i].y = faceVertices[i].y;
189                geom->mVertices[i].z = faceVertices[i].z;
190       
191                geom->mNormals[i].x = faceNormals[i].x;
192                geom->mNormals[i].y = faceNormals[i].y;
193                geom->mNormals[i].z = faceNormals[i].z;
194
195#endif
196
197                if (i < geom->mTexcoordCount)
198                {
199                        geom->mTexcoords[i].first = faceTexcoords[i].first;
200                        geom->mTexcoords[i].second = faceTexcoords[i].second;
201                }
202        }
203
204        mGeometry.push_back(geom);
205}
206
207
208bool ObjConverter2::Convert(const string &filename,
209                                                        const std::string &outputFilename)
210{
211        mNumShapes = 0;
212       
213        for (size_t i = 0; i < mGeometry.size(); ++ i)
214                delete mGeometry[i];
215       
216        mGeometry.clear();
217
218        if (!ReadFile(filename))
219        {
220                cerr << "could not read file" << endl;
221                return false;
222        }
223
224        if (!WriteFile(outputFilename))
225        {
226                cerr << "could not write file" << endl;
227                return false;
228        }
229
230        return true;
231}
232
233
234bool ObjConverter2::Convert2(const vector<string> &filenames,
235                                                         const std::string &outputFilename)
236{
237        mNumShapes = 0;
238
239        vector<string>::const_iterator it, it_end = filenames.end();
240
241        ofstream outstr("mydebug.log");
242
243        for (it = filenames.begin(); it != it_end; ++ it)
244        {
245                const string filename = *it;
246
247                cout << "\n==================\n loading file " << filename << endl;
248
249                outstr << "loading file: " << filename << endl;
250                outstr << flush;
251
252                if (!ReadFile(filename))
253                {
254                        cerr << "could not read file ... skipping " << filename << endl;
255                        //return false;
256                }
257        }
258
259        cout << "\n*******************\nwriting file " << outputFilename << endl;
260
261        if (!WriteFile(outputFilename))
262        {
263                cerr << "could not write file" << endl;
264                return false;
265        }
266
267        return true;
268}
269
270
271
272bool ObjConverter2::ReadFile(const string &filename)
273{
274        FILE *file;
275
276        if ((file = fopen(filename.c_str(), "r")) == NULL)
277        {       
278                return false;
279        }
280       
281        Material *currentMat = NULL;
282        VertexArray faceVertices;
283        VertexArray faceNormals;
284        vector<Texcoord> faceTexcoords;
285
286        VertexArray vertices;
287        VertexArray normals;
288        vector<Texcoord> texcoords;
289
290        vector<int> indices;
291
292        int line = 0;
293        const int len = 10000;
294        char str[len];
295
296        while (fgets(str, len, file) != NULL)
297        {
298                //cout << "line: " << line << endl;
299                switch (str[0])
300                {
301                case 'v': // vertex or normal
302                        {
303                                // still an object to load
304                                if (!faceVertices.empty())
305                                {
306                                        ++ mNumShapes;
307
308                                        //if (!currentMat){ cerr << "no mat!!" << endl; std::cin.get(); }
309                                        LoadShape(faceVertices, faceNormals, faceTexcoords, currentMat);
310
311                                        faceVertices.clear();
312                                        faceNormals.clear();
313                                        faceTexcoords.clear();
314
315                                        currentMat = NULL;
316                                }
317
318                                float x, y, z;
319
320                                switch (str[1])
321                                {
322                                case 'n' :
323                                        sscanf(str + 2, "%f %f %f", &x, &y, &z);
324                                        normals.push_back(SimpleVec(x, y, z));
325                                        break;
326                                case 't':
327                                        sscanf(str + 2, "%f %f", &x, &y);
328                                        texcoords.push_back(pair<float, float>(x, y));
329                                        break;
330                                default:
331                                        sscanf(str + 1, "%f %f %f", &x, &y, &z);
332                                        //const float scale = 5e-3f;
333                                        const float scale = 5.0f;
334                                        vertices.push_back(SimpleVec(x * scale, y * scale, z* scale));
335                                }
336                                break;
337                        }
338                case 'f':
339                        {
340                                //////////
341                                //-- indices in the current line
342
343                                //cout << "f: " << vertices.size() << " n: " << normals.size() << " " << texcoords.size() << endl;
344
345                                LoadIndices(str,
346                                                vertices, normals, texcoords,
347                                                faceVertices, faceNormals, faceTexcoords);
348
349                                break;
350                        }   // end face
351                /*case 'g': // load a new shape
352                        {
353                                if (!faceVertices.empty())
354                                {
355                                        ++ mNumShapes;
356
357                                        LoadShape(faceVertices, faceNormals, faceTexcoords, currentMat);
358
359                                        faceVertices.clear();
360                                        faceNormals.clear();
361                                        faceTexcoords.clear();
362
363                                        currentMat = NULL;
364                                }
365                        }
366                        break;*/
367                case 'u': // usemtl => material
368                        {
369                                string matName(str + 7);
370                                // throw away linebreak character
371                                matName.resize(matName.size() - 1);
372
373                                currentMat = mMaterialTable[matName];
374                                //cout << "matname: " << matName << endl;
375                                //cout << "currentMat: " << currentMat << endl;
376                        }
377                        break;
378                case 'm': // material library
379                        {
380                                string matLibName(model_path + string(str + 7));
381                                // throw away linebreak character
382                                matLibName.resize(matLibName.size() - 1);
383                               
384                                cout << "loading mat library " << matLibName << endl;
385
386                                // load the materials
387                                if (!LoadMaterials(matLibName))
388                                {
389                                        cerr << "loading material library failed" << endl;
390                                        return false;
391                                }
392                        }
393
394                default:
395                        // throw away line
396                        break;
397                }
398
399                ++ line;
400        }
401
402        // convert the rest of the vertives
403        if (!faceVertices.empty())
404        {
405                ++ mNumShapes;
406
407                LoadShape(faceVertices, faceNormals, faceTexcoords, currentMat);
408
409                faceVertices.clear();
410                faceNormals.clear();
411                faceTexcoords.clear();
412        }
413
414        fclose(file);
415       
416        return true;
417}
418
419
420void ObjConverter2::WriteGeometry(ogzstream &str, Geometry *geom)
421{
422        int vertexCount = geom->mVertexCount;
423        str.write(reinterpret_cast<char *>(&vertexCount), sizeof(int));
424 
425        str.write(reinterpret_cast<char *>(geom->mVertices), sizeof(SimpleVec) * vertexCount);
426        str.write(reinterpret_cast<char *>(geom->mNormals), sizeof(SimpleVec) * vertexCount);
427
428        int texCoordCount = geom->mTexcoordCount;
429        str.write(reinterpret_cast<char *>(&texCoordCount), sizeof(int));
430
431        if (texCoordCount)
432                str.write(reinterpret_cast<char *>(geom->mTexcoords), sizeof(float) * texCoordCount * 2);
433}
434
435
436bool ObjConverter2::WriteFile(const string &filename)
437{
438        ogzstream ofile(filename.c_str());
439        if (!ofile.is_open()) return false;
440       
441
442        /////////
443        //-- write textures
444
445        int textureCount = (int)mTextures.size();
446
447        ofile.write(reinterpret_cast<char *>(&textureCount), sizeof(int));
448
449        TextureArray::const_iterator tit, tit_end = mTextures.end();
450       
451        for (tit = mTextures.begin(); tit != tit_end; ++ tit)
452        {
453                const string texName = (*tit);
454
455                int texnameSize = (int)texName.length() + 1;
456                ofile.write(reinterpret_cast<char *>(&texnameSize), sizeof(int));
457
458                ofile.write(texName.c_str(), sizeof(char) * texnameSize);
459
460                int boundS = 1, boundT = 1;
461
462                ofile.write(reinterpret_cast<char *>(&boundS), sizeof(int));
463                ofile.write(reinterpret_cast<char *>(&boundT), sizeof(int));
464        }
465
466
467        ///////////
468        //-- write shapes
469
470        ofile.write(reinterpret_cast<char *>(&mNumShapes), sizeof(int));
471
472        vector<Geometry *>::const_iterator it, it_end = mGeometry.end();
473
474        for (it = mGeometry.begin(); it != it_end; ++ it)
475        {
476                WriteGeometry(ofile, *it);
477
478               
479                /////////
480                //-- material
481
482                Material *mat = (*it)->mMaterial;
483
484                if (!mat) cerr << "error: no material specified!!" << endl;
485
486                ofile.write(reinterpret_cast<char *>(&mat->texture), sizeof(int));
487
488                bool alphaTestEnabled = false;
489                bool cullFaceEnabled = true;
490                //bool cullFaceEnabled = false;
491               
492                ofile.write(reinterpret_cast<char *>(&alphaTestEnabled), sizeof(bool));
493                ofile.write(reinterpret_cast<char *>(&cullFaceEnabled), sizeof(bool));
494
495                // material
496                bool hasMaterial = true;
497                ofile.write(reinterpret_cast<char *>(&hasMaterial), sizeof(bool));
498       
499                SimpleVec ambient, diffuse, spec, emm;
500
501                ambient.x = ambient.y = ambient.z = 0.2f;
502                //diffuse.x = diffuse.y = diffuse.z = 1.0f;
503                diffuse.x = mat->rgb[0]; diffuse.y =mat->rgb[1]; diffuse.z = mat->rgb[2];
504                spec.x = spec.y = spec.z = .0f;
505                emm = spec;
506
507                // only write rgb part of the material
508                ofile.write(reinterpret_cast<char *>(&ambient), sizeof(SimpleVec));
509                ofile.write(reinterpret_cast<char *>(&diffuse), sizeof(SimpleVec));
510                ofile.write(reinterpret_cast<char *>(&spec), sizeof(SimpleVec));
511                ofile.write(reinterpret_cast<char *>(&emm), sizeof(SimpleVec));
512        }
513
514
515        int entityCount = mNumShapes;
516        ofile.write(reinterpret_cast<char *>(&entityCount), sizeof(int));
517
518
519        //////////
520        //-- write scene entities
521
522        // all shapes belong to this scene entity
523        for (int i = 0; i < mNumShapes; ++ i)
524        {
525                // no transformation
526                bool hasTrafo = false;
527                ofile.write(reinterpret_cast<char *>(&hasTrafo), sizeof(bool));
528
529                // a dummy lod
530                int numLODs = 1;
531                ofile.write(reinterpret_cast<char *>(&numLODs), sizeof(int));
532
533                float dist = 0;
534                ofile.write(reinterpret_cast<char *>(&dist), sizeof(float));
535
536                int numShapes = 1;
537                ofile.write(reinterpret_cast<char *>(&numShapes), sizeof(int));
538
539                int shapeId = i;
540                ofile.write(reinterpret_cast<char *>(&shapeId), sizeof(int));
541        }
542
543        ofile.close();
544
545        return true;
546}
547
548
549bool ObjConverter2::LoadMaterials(const std::string &matFileName)
550{
551        FILE *file;
552        if ((file = fopen(matFileName.c_str(), "r")) == NULL) return false;
553       
554        int line = 0;
555        const int len = 10000;
556        char str[len];
557
558        Material *currentMat = NULL;
559
560
561        while (fgets(str, len, file) != NULL)
562        {
563                //sscanf(str + 1, "%f %f %f", &x, &y, &z);
564                vector<string> strings;
565
566                char *next_token;
567
568                // extract the triples of the form v/t/n v/t/n ...
569                char *pch = strtok_s(str, " \n", &next_token);
570
571                while (pch)
572                {
573                        string s(pch);
574                        strings.push_back(s);
575
576                        pch = strtok_s(NULL, " \n", &next_token);       
577                }
578               
579                if ((strings.size() == 2) && (strcmp(strings[0].c_str(),"newmtl") == 0))
580                {
581                        currentMat = new Material();
582                        mMaterialTable[strings[1].c_str()] = currentMat;
583                }
584
585                if ((strings.size() == 2) &&
586                        ((strcmp(strings[0].c_str(),"map_Kd") == 0) || (strcmp(strings[0].c_str(),"map_Ka") == 0)))
587                {
588                        TextureTable::const_iterator it = mTextureTable.find(strings[1]);
589
590                        int id;
591
592                        if (it == mTextureTable.end()) // parameter not found
593                        {
594                                mTextures.push_back(strings[1]);
595                                id = (int)mTextures.size();
596                                mTextureTable[strings[1]] = id;
597                        }
598                        else
599                        {
600                                id = (*it).second;
601                        }
602
603                        currentMat->texture = id;
604                }
605
606                if ((strings.size() == 4) && (strcmp(strings[0].c_str(),"Kd") == 0))
607                {
608                        currentMat->rgb[0] = (float)atof(strings[1].c_str());
609                        currentMat->rgb[1] = (float)atof(strings[2].c_str());
610                        currentMat->rgb[2] = (float)atof(strings[3].c_str());
611                }
612
613                ++ line;
614        }
615
616        fclose(file);
617
618        return true;
619}
Note: See TracBrowser for help on using the repository browser.