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

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