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

Revision 3128, 10.3 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                geom->mVertices[i].x += 470.398f;
172                geom->mVertices[i].y += 240.364f;
173                geom->mVertices[i].z += 182.5f;
174
175                if (i < geom->mTexcoordCount)
176                {
177                        geom->mTexcoords[i].first = faceTexcoords[i].first;
178                        geom->mTexcoords[i].second = faceTexcoords[i].second;
179                }
180        }
181
182        mGeometry.push_back(geom);
183}
184
185
186bool ObjConverter::Convert(const string &filename, const std::string &outputFilename)
187{
188        mNumShapes = 0;
189       
190        for (size_t i = 0; i < mGeometry.size(); ++ i)
191        {
192                delete [] mGeometry[i]->mVertices;
193                delete [] mGeometry[i]->mNormals;
194                delete [] mGeometry[i]->mTexcoords;
195
196                delete mGeometry[i];
197        }
198       
199        mGeometry.clear();
200
201        if (!ReadFile(filename))
202        {
203                cerr << "could not read file" << endl;
204                return false;
205        }
206
207        if (!WriteFile(outputFilename))
208        {
209                cerr << "could not write file" << endl;
210                return false;
211        }
212
213
214        return true;
215}
216
217
218bool ObjConverter::ReadFile(const string &filename)
219{
220        FILE *file;
221
222        if ((file = fopen(filename.c_str(), "r")) == NULL)
223        {       
224                return false;
225        }
226       
227        VertexArray faceVertices;
228        VertexArray faceNormals;
229        vector<Texcoord> faceTexcoords;
230
231        VertexArray vertices;
232        VertexArray normals;
233        vector<Texcoord> texcoords;
234
235        vector<int> indices;
236
237        int line = 0;
238
239        const int len = 10000;
240        char str[len];
241
242        while (fgets(str, len, file) != NULL)
243        {
244//              if (1)//(line % 100) == 0)
245//                      cout << "read line " << line << " " << str;
246                switch (str[0])
247                {
248                case 'v': // vertex or normal
249                        {
250                                float x, y, z;
251
252                                switch (str[1])
253                                {
254                                case 'n' :
255                                        sscanf(str + 2, "%f %f %f", &x, &y, &z);
256                                        normals.push_back(SimpleVec(x, y, z));
257                                        break;
258                                case 't':
259                                        sscanf(str + 2, "%f %f", &x, &y);
260                                        texcoords.push_back(pair<float, float>(x, y));
261                                        break;
262                                default:
263                                        sscanf(str + 1, "%f %f %f", &x, &y, &z);
264                                        vertices.push_back(SimpleVec(x, y, z));
265                                        //cout <<"v " << x << " " << y << " "<< z << " ";
266                                }
267                                break;
268                        }
269                case 'f':
270                        {
271                                //////////
272                                //-- indices in the current line
273
274                                LoadIndices(str,
275                                                vertices, normals, texcoords,
276                                                faceVertices, faceNormals, faceTexcoords);
277
278                                if (0 &&
279                                        (((line % 1000) == 999) && !faceVertices.empty()))
280                                {
281                                        ++ mNumShapes;
282
283                                        LoadShape(faceVertices, faceNormals, faceTexcoords);
284
285                                        faceVertices.clear();
286                                        faceNormals.clear();
287                                        faceTexcoords.clear();
288                                }
289
290                                break;
291                        }   // end face
292                case 'g': // load a new shape
293                        {/*
294                                if (!faceVertices.empty())
295                                {
296                                        ++ mNumShapes;
297
298                                        LoadShape(faceVertices, faceNormals, faceTexcoords);
299
300                                        faceVertices.clear();
301                                        faceNormals.clear();
302                                        faceTexcoords.clear();
303                                }*/
304                        }
305                        break;
306                default:
307                        break;
308                }
309
310                ++ line;
311        }
312
313        if (!faceVertices.empty())
314        {
315                ++ mNumShapes;
316
317                LoadShape(faceVertices, faceNormals, faceTexcoords);
318
319                faceVertices.clear();
320                faceNormals.clear();
321                faceTexcoords.clear();
322        }
323
324        fclose(file);
325       
326        return true;
327}
328
329
330void ObjConverter::WriteGeometry(ogzstream &str, Geometry *geom)
331{
332        int vertexCount = geom->mVertexCount;
333        str.write(reinterpret_cast<char *>(&vertexCount), sizeof(int));
334 
335        str.write(reinterpret_cast<char *>(geom->mVertices), sizeof(SimpleVec) * vertexCount);
336        str.write(reinterpret_cast<char *>(geom->mNormals), sizeof(SimpleVec) * vertexCount);
337
338        int texCoordCount = geom->mTexcoordCount;
339        str.write(reinterpret_cast<char *>(&texCoordCount), sizeof(int));
340
341        if (texCoordCount)
342                str.write(reinterpret_cast<char *>(geom->mTexcoords), sizeof(float) * texCoordCount * 2);
343       
344
345        ///////
346        //-- texture
347
348        //int texId = -1;
349        int texId = 0;
350        str.write(reinterpret_cast<char *>(&texId), sizeof(int));
351
352        bool alphaTestEnabled = false;
353        bool cullFaceEnabled = false;
354        //bool cullFaceEnabled = true;
355
356        str.write(reinterpret_cast<char *>(&alphaTestEnabled), sizeof(bool));
357        str.write(reinterpret_cast<char *>(&cullFaceEnabled), sizeof(bool));
358
359        // material
360        bool hasMaterial = true;
361        //bool hasMaterial = false;
362        str.write(reinterpret_cast<char *>(&hasMaterial), sizeof(bool));
363       
364        if (hasMaterial)
365        {
366                SimpleVec ambient, diffuse, spec, emm;
367
368                ambient.x = ambient.y = ambient.z = 0.2f;
369                diffuse.x = diffuse.y = diffuse.z = 1.0f;
370                spec.x   = spec.y   = spec.z   =  .0f;
371                emm = spec;
372
373                // only write rgb part of the material
374                str.write(reinterpret_cast<char *>(&ambient), sizeof(SimpleVec));
375                str.write(reinterpret_cast<char *>(&diffuse), sizeof(SimpleVec));
376                str.write(reinterpret_cast<char *>(&spec), sizeof(SimpleVec));
377                str.write(reinterpret_cast<char *>(&emm), sizeof(SimpleVec));
378        }
379}
380
381
382bool ObjConverter::WriteFile(const string &filename)
383{
384        ogzstream ofile(filename.c_str());
385
386        if (!ofile.is_open())
387                return false;
388       
389
390        /////////
391        //-- write textures
392
393        int textureCount = 1;
394        //int textureCount = 0;
395
396        ofile.write(reinterpret_cast<char *>(&textureCount), sizeof(int));
397
398        if (textureCount > 0)
399        {
400                // hack
401                const string texName("wood.jpg");
402
403                int texnameSize = (int)texName.length() + 1;
404                ofile.write(reinterpret_cast<char *>(&texnameSize), sizeof(int));
405
406                ofile.write(texName.c_str(), sizeof(char) * texnameSize);
407
408                int boundS = 1, boundT = 1;
409
410                ofile.write(reinterpret_cast<char *>(&boundS), sizeof(int));
411                ofile.write(reinterpret_cast<char *>(&boundT), sizeof(int));
412        }
413
414
415        ///////////
416        //-- write shapes
417
418        ofile.write(reinterpret_cast<char *>(&mNumShapes), sizeof(int));
419
420        vector<Geometry *>::const_iterator it, it_end = mGeometry.end();
421
422        for (it = mGeometry.begin(); it != it_end; ++ it)
423        {
424                WriteGeometry(ofile, *it);
425        }
426
427
428        int entityCount = 1;
429        ofile.write(reinterpret_cast<char *>(&entityCount), sizeof(int));
430
431
432        //////////
433        //-- write single scene entity
434
435        // no transformation
436        bool hasTrafo = false;
437        ofile.write(reinterpret_cast<char *>(&hasTrafo), sizeof(bool));
438
439        // a dummy lod
440        int numLODs = 1;
441        ofile.write(reinterpret_cast<char *>(&numLODs), sizeof(int));
442
443        float dist = 0;
444        ofile.write(reinterpret_cast<char *>(&dist), sizeof(float));
445
446        ofile.write(reinterpret_cast<char *>(&mNumShapes), sizeof(int));
447
448        // all shapes belong to this scene entity
449        for (int i = 0; i < mNumShapes; ++ i)
450        {
451                int shapeId = i;
452                ofile.write(reinterpret_cast<char *>(&shapeId), sizeof(int));
453        }
454
455        return true;
456}
Note: See TracBrowser for help on using the repository browser.