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

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