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

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

fehler tritt nicht auf!!

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