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

Revision 3076, 10.2 KB checked in by mattausch, 16 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
11static void LoadIndices(char *str,
12                                                const VertexArray &vertices,
13                                                const VertexArray &normals,
14                                                const vector<pair<float, float> > &texcoords,
15                                                VertexArray &faceVertices,
16                                                VertexArray &faceNormals,
17                                                vector<Texcoord> &faceTexcoords
18                                                )
19{
20        vector<char *> substrings;
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 != NULL)
28        {
29                substrings.push_back(pch);
30                pch = strtok_s(NULL, " ", &next_token);   
31        }
32
33        vector<int> indices;
34        vector<int> nIndices;
35        vector<int> tIndices;
36
37        for (size_t i = 0; i < substrings.size(); ++ i)
38        {
39                // vertex, normal, texture indices
40                char *str = strtok_s(substrings[i], "/", &next_token);   
41                int index = (int)strtol(str, NULL, 10) - 1;
42
43                int tIndex = index;
44                int nIndex = index;
45
46                str = strtok_s(substrings[i], "/", &next_token);         
47
48                if (str != NULL)
49                {
50                        int idx = (int)strtol(str, NULL, 10) - 1;
51                        if (idx) tIndex = idx;
52                }
53                str = strtok_s(substrings[i], "/", &next_token);         
54
55                if (str != NULL)
56                {
57                        int idx = (int)strtol(str, NULL, 10) - 1;
58                        if (idx) nIndex = idx;
59                }
60
61                // store indices
62                if (index >= 0)
63                {
64                        indices.push_back(index);
65                        nIndices.push_back(nIndex);
66                        tIndices.push_back(tIndex);
67                }
68
69                // new triangle found
70                if (indices.size() > 2)
71                {
72                        // change orientation of faces?
73#if 1
74                        int idx1 = 0;
75                        int idx2 = (int)indices.size() - 2;
76                        int idx3 = (int)indices.size() - 1;
77#else
78                        int idx3 = 0;
79                        int idx2 = (int)indices.size() - 2;
80                        int idx1 = (int)indices.size() - 1;
81#endif
82                        faceVertices.push_back(vertices[indices[idx1]]);
83                        faceVertices.push_back(vertices[indices[idx2]]);
84                        faceVertices.push_back(vertices[indices[idx3]]);
85
86                        if (!normals.empty())
87                        {
88                                faceNormals.push_back(normals[nIndices[idx1]]);
89                                faceNormals.push_back(normals[nIndices[idx2]]);
90                                faceNormals.push_back(normals[nIndices[idx3]]);
91                        }
92                        else
93                        {
94                                // no face normals?
95                                const SimpleTri tri(vertices[indices[idx1]], vertices[indices[idx2]], vertices[indices[idx3]]);
96                                const SimpleVec n = tri.GetNormal();
97
98                                faceNormals.push_back(n);
99                                faceNormals.push_back(n);
100                                faceNormals.push_back(n);
101                        }
102
103                        if (!texcoords.empty())
104                        {
105                                faceTexcoords.push_back(texcoords[tIndices[idx1]]);
106                                faceTexcoords.push_back(texcoords[tIndices[idx2]]);
107                                faceTexcoords.push_back(texcoords[tIndices[idx3]]);
108                        }
109                }
110        }
111}
112
113
114ObjConverter::ObjConverter()
115{}
116
117
118ObjConverter::~ObjConverter()
119{
120        for (size_t i = 0; i < mGeometry.size(); ++ i)
121        {
122                delete [] mGeometry[i]->mVertices;
123                delete [] mGeometry[i]->mNormals;
124                delete [] mGeometry[i]->mTexcoords;
125
126                delete mGeometry[i];
127        }
128       
129        mGeometry.clear();
130}
131
132
133void ObjConverter::LoadShape(const VertexArray &faceVertices,
134                                                         const VertexArray &faceNormals,
135                                                         const vector<Texcoord> &faceTexcoords)
136{
137        int numElements = (int)faceVertices.size();
138        Geometry *geom = new Geometry();
139
140        // convert the triangles to geometry
141        geom->mVertices = new SimpleVec[numElements];
142        geom->mNormals = new SimpleVec[numElements];
143        geom->mTexcoords = new Texcoord[numElements];
144
145        geom->mVertexCount = numElements;
146        geom->mTexcoordCount = (int)faceTexcoords.size();
147
148        cout << "number of vertices=" << numElements << endl;
149
150        for (int i = 0; i < numElements; ++ i)
151        {
152#if 0
153                // convert to our camera system: change y and z
154                geom->mVertices[i].x = faceVertices[i].x;
155                geom->mVertices[i].y = -faceVertices[i].z;
156                geom->mVertices[i].z = faceVertices[i].y;
157       
158                geom->mNormals[i].x = faceNormals[i].x;
159                geom->mNormals[i].y = -faceNormals[i].z;
160                geom->mNormals[i].z = faceNormals[i].y;
161#else
162                geom->mVertices[i].x = faceVertices[i].x;
163                geom->mVertices[i].y = faceVertices[i].y;
164                geom->mVertices[i].z = faceVertices[i].z;
165       
166                geom->mNormals[i].x = faceNormals[i].x;
167                geom->mNormals[i].y = faceNormals[i].y;
168                geom->mNormals[i].z = faceNormals[i].z;
169
170#endif
171                if (i < geom->mTexcoordCount)
172                {
173                        geom->mTexcoords[i].first = faceTexcoords[i].first;
174                        geom->mTexcoords[i].second = faceTexcoords[i].second;
175                }
176        }
177
178        mGeometry.push_back(geom);
179}
180
181
182bool ObjConverter::Convert(const string &filename, const std::string &outputFilename)
183{
184        mNumShapes = 0;
185       
186        for (size_t i = 0; i < mGeometry.size(); ++ i)
187        {
188                delete [] mGeometry[i]->mVertices;
189                delete [] mGeometry[i]->mNormals;
190                delete [] mGeometry[i]->mTexcoords;
191
192                delete mGeometry[i];
193        }
194       
195        mGeometry.clear();
196
197        if (!ReadFile(filename))
198        {
199                cerr << "could not read file" << endl;
200                return false;
201        }
202
203        if (!WriteFile(outputFilename))
204        {
205                cerr << "could not write file" << endl;
206                return false;
207        }
208
209
210        return true;
211}
212
213
214bool ObjConverter::ReadFile(const string &filename)
215{
216        FILE *file;
217
218        if ((file = fopen(filename.c_str(), "r")) == NULL)
219        {       
220                return false;
221        }
222       
223        VertexArray faceVertices;
224        VertexArray faceNormals;
225        vector<Texcoord> faceTexcoords;
226
227        VertexArray vertices;
228        VertexArray normals;
229        vector<Texcoord> texcoords;
230
231        vector<int> indices;
232
233        int line = 0;
234
235        const int len = 10000;
236        char str[len];
237
238        while (fgets(str, len, file) != NULL)
239        {
240                if (1)//(line % 100) == 0)
241                        cout << "read line " << line << " " << str;
242                switch (str[0])
243                {
244                case 'v': // vertex or normal
245                        {
246                                float x, y, z;
247
248                                switch (str[1])
249                                {
250                                case 'n' :
251                                        sscanf(str + 2, "%f %f %f", &x, &y, &z);
252                                        normals.push_back(SimpleVec(x, y, z));
253                                        break;
254                                case 't':
255                                        sscanf(str + 2, "%f %f", &x, &y);
256                                        texcoords.push_back(pair<float, float>(x, y));
257                                        break;
258                                default:
259                                        sscanf(str + 1, "%f %f %f", &x, &y, &z);
260                                        vertices.push_back(SimpleVec(x, y, z));
261                                        //cout <<"v " << x << " " << y << " "<< z << " ";
262                                }
263                                break;
264                        }
265                case 'f':
266                        {
267                                //////////
268                                //-- indices in the current line
269
270                                LoadIndices(str,
271                                                vertices, normals, texcoords,
272                                                faceVertices, faceNormals, faceTexcoords);
273
274                                if (0 &&
275                                        (((line % 1000) == 999) && !faceVertices.empty()))
276                                {
277                                        ++ mNumShapes;
278
279                                        LoadShape(faceVertices, faceNormals, faceTexcoords);
280
281                                        faceVertices.clear();
282                                        faceNormals.clear();
283                                        faceTexcoords.clear();
284                                }
285
286                                break;
287                        }   // end face
288                case 'g': // load a new shape
289                        {/*
290                                if (!faceVertices.empty())
291                                {
292                                        ++ mNumShapes;
293
294                                        LoadShape(faceVertices, faceNormals, faceTexcoords);
295
296                                        faceVertices.clear();
297                                        faceNormals.clear();
298                                        faceTexcoords.clear();
299                                }*/
300                        }
301                        break;
302                default:
303                        break;
304                }
305
306                ++ line;
307        }
308
309        if (!faceVertices.empty())
310        {
311                ++ mNumShapes;
312
313                LoadShape(faceVertices, faceNormals, faceTexcoords);
314
315                faceVertices.clear();
316                faceNormals.clear();
317                faceTexcoords.clear();
318        }
319
320        fclose(file);
321       
322        return true;
323}
324
325
326void ObjConverter::WriteGeometry(ogzstream &str, Geometry *geom)
327{
328        int vertexCount = geom->mVertexCount;
329        str.write(reinterpret_cast<char *>(&vertexCount), sizeof(int));
330 
331        str.write(reinterpret_cast<char *>(geom->mVertices), sizeof(SimpleVec) * vertexCount);
332        str.write(reinterpret_cast<char *>(geom->mNormals), sizeof(SimpleVec) * vertexCount);
333
334        int texCoordCount = geom->mTexcoordCount;
335        str.write(reinterpret_cast<char *>(&texCoordCount), sizeof(int));
336
337        if (texCoordCount)
338                str.write(reinterpret_cast<char *>(geom->mTexcoords), sizeof(float) * texCoordCount * 2);
339       
340
341        ///////
342        //-- texture
343
344        int texId = -1;
345        //int texId = 0;
346        str.write(reinterpret_cast<char *>(&texId), sizeof(int));
347
348        bool alphaTestEnabled = false;
349        bool cullFaceEnabled = false;
350        //bool cullFaceEnabled = true;
351
352        str.write(reinterpret_cast<char *>(&alphaTestEnabled), sizeof(bool));
353        str.write(reinterpret_cast<char *>(&cullFaceEnabled), sizeof(bool));
354
355        // material
356        bool hasMaterial = true;
357        //bool hasMaterial = false;
358        str.write(reinterpret_cast<char *>(&hasMaterial), sizeof(bool));
359       
360        if (hasMaterial)
361        {
362                SimpleVec ambient, diffuse, black;
363
364                ambient.x = ambient.y = ambient.z = 0.2f;
365                diffuse.x = diffuse.y = diffuse.z = 1.0f;
366                black.x = black.y = black.z = .0f;
367
368                // only write rgb part of the material
369                str.write(reinterpret_cast<char *>(&ambient), sizeof(SimpleVec));
370                str.write(reinterpret_cast<char *>(&diffuse), sizeof(SimpleVec));
371                str.write(reinterpret_cast<char *>(&black), sizeof(SimpleVec));
372                str.write(reinterpret_cast<char *>(&black), sizeof(SimpleVec));
373        }
374}
375
376
377bool ObjConverter::WriteFile(const string &filename)
378{
379        ogzstream ofile(filename.c_str());
380
381        if (!ofile.is_open())
382                return false;
383       
384
385        /////////
386        //-- write textures
387
388        //int textureCount = 1;
389        int textureCount = 0;
390
391        ofile.write(reinterpret_cast<char *>(&textureCount), sizeof(int));
392
393        if (textureCount > 0)
394        {
395                // hack
396                const string texName("wood.jpg");
397
398                int texnameSize = (int)texName.length() + 1;
399                ofile.write(reinterpret_cast<char *>(&texnameSize), sizeof(int));
400
401                ofile.write(texName.c_str(), sizeof(char) * texnameSize);
402
403                int boundS = 1;
404                int boundT = 1;
405
406                ofile.write(reinterpret_cast<char *>(&boundS), sizeof(int));
407                ofile.write(reinterpret_cast<char *>(&boundT), sizeof(int));
408        }
409
410
411        ///////////
412        //-- write shapes
413
414        ofile.write(reinterpret_cast<char *>(&mNumShapes), sizeof(int));
415
416        vector<Geometry *>::const_iterator it, it_end = mGeometry.end();
417
418        for (it = mGeometry.begin(); it != it_end; ++ it)
419        {
420                WriteGeometry(ofile, *it);
421        }
422
423
424        int entityCount = 1;
425        ofile.write(reinterpret_cast<char *>(&entityCount), sizeof(int));
426
427
428        //////////
429        //-- write single scene entity
430
431        // no transformation
432        bool hasTrafo = false;
433        ofile.write(reinterpret_cast<char *>(&hasTrafo), sizeof(bool));
434
435        // a dummy lod
436        int numLODs = 1;
437        ofile.write(reinterpret_cast<char *>(&numLODs), sizeof(int));
438
439        float dist = 0;
440        ofile.write(reinterpret_cast<char *>(&dist), sizeof(float));
441
442        ofile.write(reinterpret_cast<char *>(&mNumShapes), sizeof(int));
443
444        // all shapes belong to this scene entity
445        for (int i = 0; i < mNumShapes; ++ i)
446        {
447                int shapeId = i;
448                ofile.write(reinterpret_cast<char *>(&shapeId), sizeof(int));
449        }
450
451        return true;
452}
Note: See TracBrowser for help on using the repository browser.