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

Revision 3261, 15.0 KB checked in by mattausch, 15 years ago (diff)

worked on powerplant loading

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