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

Revision 3146, 10.7 KB checked in by mattausch, 16 years ago (diff)

normal mapping hack not working yet. found problems with ssao if the geometry is not tesselated enough (especially with smoothed
normals: one can see the underlying tesselation!

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                        ++ dummy;
125                        if (!texcoords.empty())
126                        {
127                                faceTexcoords.push_back(texcoords[tIndices[idx1]]);
128                                faceTexcoords.push_back(texcoords[tIndices[idx2]]);
129                                faceTexcoords.push_back(texcoords[tIndices[idx3]]);
130                        }
131                }
132        }
133}
134
135
136ObjConverter::ObjConverter()
137{}
138
139
140ObjConverter::~ObjConverter()
141{
142        for (size_t i = 0; i < mGeometry.size(); ++ i)
143        {
144                delete [] mGeometry[i]->mVertices;
145                delete [] mGeometry[i]->mNormals;
146                delete [] mGeometry[i]->mTexcoords;
147
148                delete mGeometry[i];
149        }
150       
151        mGeometry.clear();
152}
153
154
155void ObjConverter::LoadShape(const VertexArray &faceVertices,
156                                                         const VertexArray &faceNormals,
157                                                         const vector<Texcoord> &faceTexcoords)
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        cout << "number of vertices=" << numElements << endl;
171
172        for (int i = 0; i < numElements; ++ i)
173        {
174#if 1
175                // convert to our camera system: change y and z
176                geom->mVertices[i].x = faceVertices[i].x;
177                geom->mVertices[i].y = -faceVertices[i].z;
178                geom->mVertices[i].z = faceVertices[i].y;
179       
180                geom->mNormals[i].x = faceNormals[i].x;
181                geom->mNormals[i].y = -faceNormals[i].z;
182                geom->mNormals[i].z = faceNormals[i].y;
183
184#else
185                geom->mVertices[i].x = faceVertices[i].x;
186                geom->mVertices[i].y = faceVertices[i].y;
187                geom->mVertices[i].z = faceVertices[i].z;
188       
189                geom->mNormals[i].x = faceNormals[i].x;
190                geom->mNormals[i].y = faceNormals[i].y;
191                geom->mNormals[i].z = faceNormals[i].z;
192
193#endif
194
195                if (i < geom->mTexcoordCount)
196                {
197                        geom->mTexcoords[i].first = faceTexcoords[i].first;
198                        geom->mTexcoords[i].second = faceTexcoords[i].second;
199                }
200        }
201
202        mGeometry.push_back(geom);
203}
204
205
206bool ObjConverter::Convert(const string &filename, const std::string &outputFilename)
207{
208        mNumShapes = 0;
209       
210        for (size_t i = 0; i < mGeometry.size(); ++ i)
211        {
212                delete [] mGeometry[i]->mVertices;
213                delete [] mGeometry[i]->mNormals;
214                delete [] mGeometry[i]->mTexcoords;
215
216                delete mGeometry[i];
217        }
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
234        return true;
235}
236
237
238bool ObjConverter::ReadFile(const string &filename)
239{
240        FILE *file;
241
242        if ((file = fopen(filename.c_str(), "r")) == NULL)
243        {       
244                return false;
245        }
246       
247        VertexArray faceVertices;
248        VertexArray faceNormals;
249        vector<Texcoord> faceTexcoords;
250
251        VertexArray vertices;
252        VertexArray normals;
253        vector<Texcoord> texcoords;
254
255        vector<int> indices;
256
257        int line = 0;
258        const int len = 10000;
259        char str[len];
260
261        while (fgets(str, len, file) != NULL)
262        {
263                switch (str[0])
264                {
265                case 'v': // vertex or normal
266                        {
267                                float x, y, z;
268
269                                switch (str[1])
270                                {
271                                case 'n' :
272                                        sscanf(str + 2, "%f %f %f", &x, &y, &z);
273                                        normals.push_back(SimpleVec(x, y, z));
274                                        break;
275                                case 't':
276                                        sscanf(str + 2, "%f %f", &x, &y);
277                                        texcoords.push_back(pair<float, float>(x, y));
278                                        break;
279                                default:
280                                        sscanf(str + 1, "%f %f %f", &x, &y, &z);
281                                        const float scale = 5e-3f;
282                                        vertices.push_back(SimpleVec(x * scale, y * scale, z* scale));
283                                        //cout <<"v " << x << " " << y << " "<< z << " ";
284                                }
285                                break;
286                        }
287                case 'f':
288                        {
289                                //////////
290                                //-- indices in the current line
291
292                                LoadIndices(str,
293                                                vertices, normals, texcoords,
294                                                faceVertices, faceNormals, faceTexcoords);
295
296                                if (0 &&
297                                        (((line % 1000) == 999) && !faceVertices.empty()))
298                                {
299                                        ++ mNumShapes;
300
301                                        LoadShape(faceVertices, faceNormals, faceTexcoords);
302
303                                        faceVertices.clear();
304                                        faceNormals.clear();
305                                        faceTexcoords.clear();
306                                }
307
308                                break;
309                        }   // end face
310                case 'g': // load a new shape
311                        {/*
312                                if (!faceVertices.empty())
313                                {
314                                        ++ mNumShapes;
315
316                                        LoadShape(faceVertices, faceNormals, faceTexcoords);
317
318                                        faceVertices.clear();
319                                        faceNormals.clear();
320                                        faceTexcoords.clear();
321                                }*/
322                        }
323                        break;
324                default:
325                        // throw away line
326                        break;
327                }
328
329                ++ line;
330        }
331
332        if (!faceVertices.empty())
333        {
334                ++ mNumShapes;
335
336                LoadShape(faceVertices, faceNormals, faceTexcoords);
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 
354        str.write(reinterpret_cast<char *>(geom->mVertices), sizeof(SimpleVec) * vertexCount);
355        str.write(reinterpret_cast<char *>(geom->mNormals), sizeof(SimpleVec) * vertexCount);
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        ///////
365        //-- texture
366
367#ifdef USE_TEXTURE
368        int texId = 0;
369#else
370        int texId = -1;
371#endif
372
373        str.write(reinterpret_cast<char *>(&texId), sizeof(int));
374
375        bool alphaTestEnabled = false;
376        //bool cullFaceEnabled = false;
377        bool cullFaceEnabled = true;
378
379        str.write(reinterpret_cast<char *>(&alphaTestEnabled), sizeof(bool));
380        str.write(reinterpret_cast<char *>(&cullFaceEnabled), sizeof(bool));
381
382        // material
383        bool hasMaterial = true;
384        //bool hasMaterial = false;
385        str.write(reinterpret_cast<char *>(&hasMaterial), sizeof(bool));
386       
387        if (hasMaterial)
388        {
389                SimpleVec ambient, diffuse, spec, emm;
390
391                ambient.x = ambient.y = ambient.z = 0.2f;
392                diffuse.x = diffuse.y = diffuse.z = 1.0f;
393                spec.x    = spec.y    = spec.z    =  .0f;
394                emm = spec;
395
396                // only write rgb part of the material
397                str.write(reinterpret_cast<char *>(&ambient), sizeof(SimpleVec));
398                str.write(reinterpret_cast<char *>(&diffuse), sizeof(SimpleVec));
399                str.write(reinterpret_cast<char *>(&spec), sizeof(SimpleVec));
400                str.write(reinterpret_cast<char *>(&emm), sizeof(SimpleVec));
401        }
402}
403
404
405bool ObjConverter::WriteFile(const string &filename)
406{
407        ogzstream ofile(filename.c_str());
408
409        if (!ofile.is_open())
410                return false;
411       
412
413        /////////
414        //-- write textures
415
416#ifdef USE_TEXTURE
417        int textureCount = 1;
418#else
419        int textureCount = 0;
420#endif
421        ofile.write(reinterpret_cast<char *>(&textureCount), sizeof(int));
422
423        if (textureCount > 0)
424        {
425                // hack
426                const string texName("wood.jpg");
427
428                int texnameSize = (int)texName.length() + 1;
429                ofile.write(reinterpret_cast<char *>(&texnameSize), sizeof(int));
430
431                ofile.write(texName.c_str(), sizeof(char) * texnameSize);
432
433                int boundS = 1, boundT = 1;
434
435                ofile.write(reinterpret_cast<char *>(&boundS), sizeof(int));
436                ofile.write(reinterpret_cast<char *>(&boundT), sizeof(int));
437        }
438
439
440        ///////////
441        //-- write shapes
442
443        ofile.write(reinterpret_cast<char *>(&mNumShapes), sizeof(int));
444
445        vector<Geometry *>::const_iterator it, it_end = mGeometry.end();
446
447        for (it = mGeometry.begin(); it != it_end; ++ it)
448        {
449                WriteGeometry(ofile, *it);
450        }
451
452
453        int entityCount = 1;
454        ofile.write(reinterpret_cast<char *>(&entityCount), sizeof(int));
455
456
457        //////////
458        //-- write single scene entity
459
460        // no transformation
461        bool hasTrafo = false;
462        ofile.write(reinterpret_cast<char *>(&hasTrafo), sizeof(bool));
463
464        // a dummy lod
465        int numLODs = 1;
466        ofile.write(reinterpret_cast<char *>(&numLODs), sizeof(int));
467
468        float dist = 0;
469        ofile.write(reinterpret_cast<char *>(&dist), sizeof(float));
470
471        ofile.write(reinterpret_cast<char *>(&mNumShapes), sizeof(int));
472
473        // all shapes belong to this scene entity
474        for (int i = 0; i < mNumShapes; ++ i)
475        {
476                int shapeId = i;
477                ofile.write(reinterpret_cast<char *>(&shapeId), sizeof(int));
478        }
479
480        return true;
481}
Note: See TracBrowser for help on using the repository browser.