source: GTP/trunk/App/Demos/Vis/FriendlyCulling/Converter/ObjConverter.cpp @ 3260

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