source: GTP/trunk/App/Demos/Vis/FriendlyCulling/VisibilitySolutionConverter/VisibilitySolutionConverter.cpp @ 3236

Revision 3236, 16.5 KB checked in by mattausch, 15 years ago (diff)
Line 
1#include "VisibilitySolutionConverter.h"
2#include "SimpleTri.h"
3#include "SimpleVec.h"
4#include "gzstream.h"
5#include <iostream>
6
7
8using namespace std;
9
10// MAGIC of all bin exports
11#ifndef MAGIC
12#define MAGIC 0x827923
13#endif
14
15#define BVH_VERSION 2.1
16
17
18static void LoadIndices(char *str,
19                                                const VertexArray &vertices,
20                                                const VertexArray &normals,
21                                                const vector<pair<float, float> > &texCoords,
22                                                VertexArray &faceVertices,
23                                                VertexArray &faceNormals,
24                                                vector<TexCoord> &faceTexCoords
25                                                )
26{
27        vector<string> triples;
28
29        char *next_token;
30
31        // extract the triples of the form v/t/n v/t/n ...
32        char *pch = strtok_s(str + 1, " ", &next_token);
33
34        while (pch)
35        {
36                string s(pch);
37                //s += "\n",
38                triples.push_back(s);
39               
40                pch = strtok_s(NULL, " ", &next_token);   
41        }
42
43        vector<int> indices;
44        vector<int> nIndices;
45        vector<int> tIndices;
46
47        char seps[] = " /\t\n";
48
49        for (size_t i = 0; i < triples.size(); ++ i)
50        {
51                static int dummy = 0;
52
53                size_t found;
54                found = triples[i].find_first_of(seps);
55                size_t prevfound = 0;
56                // vertex, normal, texture indices
57                string str = triples[i].substr(prevfound, found);
58
59                int index = (int)strtol(str.c_str(), NULL, 10) - 1;
60
61                int tIndex = index;
62                int nIndex = index;     
63               
64                prevfound = found;
65                found = triples[i].find_first_of(seps, found + 1); 
66
67                if (found != string::npos)
68                {
69                        str = triples[i].substr(prevfound, found);
70
71                        int idx = (int)strtol(str.c_str(), NULL, 10) - 1;
72                        if (idx > 0) tIndex = idx;
73                }
74
75                if ((found + 1) < triples[i].size())
76                {
77                        str = triples[i].substr(found + 1);
78
79                        int idx = (int)strtol(str.c_str(), NULL, 10) - 1;
80                        if (idx > 0) nIndex = idx;
81                }
82
83                // store indices
84                if (index >= 0)
85                {
86                        indices.push_back(index);
87                        nIndices.push_back(nIndex);
88                        tIndices.push_back(tIndex);
89                }
90
91                // new triangle found
92                if (indices.size() > 2)
93                {
94                        // change orientation of faces?
95#if 1
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]]);
107
108
109                        if (!normals.empty())
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                        {
117                                // no face normals? => create normals
118                                const SimpleTri tri(vertices[indices[idx1]],
119                                                        vertices[indices[idx2]],
120                                                                        vertices[indices[idx3]]);
121
122                                const SimpleVec n = tri.GetNormal();
123
124                                faceNormals.push_back(n);
125                                faceNormals.push_back(n);
126                                faceNormals.push_back(n);
127                        }
128
129                        if (!texCoords.empty())
130                        {
131                                faceTexCoords.push_back(texCoords[tIndices[idx1]]);
132                                faceTexCoords.push_back(texCoords[tIndices[idx2]]);
133                                faceTexCoords.push_back(texCoords[tIndices[idx3]]);
134                        }
135                }
136        }
137}
138
139
140VisibilitySolutionConverter::VisibilitySolutionConverter()
141{}
142
143
144VisibilitySolutionConverter::~VisibilitySolutionConverter()
145{
146        for (size_t i = 0; i < mGeometry.size(); ++ i)
147        {
148                delete [] mGeometry[i]->mVertices;
149                delete [] mGeometry[i]->mNormals;
150                delete [] mGeometry[i]->mTexCoords;
151
152                delete mGeometry[i];
153        }
154       
155        mGeometry.clear();
156}
157
158
159void VisibilitySolutionConverter::LoadShape(const VertexArray &vertices,
160                                                                                        const VertexArray &normals,
161                                                                                        const vector<TexCoord> &texCoords)
162{
163        int numElements = (int)vertices.size();
164        Geometry *geom = new Geometry();
165
166        // convert the triangles to geometry
167        geom->mVertices = new SimpleVec[numElements];
168        geom->mNormals = new SimpleVec[numElements];
169        geom->mTexCoords = new TexCoord[numElements];
170
171        geom->mVertexCount = numElements;
172        geom->mTexcoordCount = (int)texCoords.size();
173
174        cout << "number of vertices=" << numElements << endl;
175
176        for (int i = 0; i < numElements; ++ i)
177        {
178#if 1
179                // convert to our camera system: change y and z
180                geom->mVertices[i].x =  vertices[i].x;
181                geom->mVertices[i].y = -vertices[i].z;
182                geom->mVertices[i].z =  vertices[i].y;
183       
184                geom->mNormals[i].x =  normals[i].x;
185                geom->mNormals[i].y = -normals[i].z;
186                geom->mNormals[i].z =  normals[i].y;
187
188#else
189                geom->mVertices[i].x = vertices[i].x;
190                geom->mVertices[i].y = vertices[i].y;
191                geom->mVertices[i].z = vertices[i].z;
192       
193                geom->mNormals[i].x = normals[i].x;
194                geom->mNormals[i].y = normals[i].y;
195                geom->mNormals[i].z = normals[i].z;
196
197#endif
198
199                if (i < geom->mTexcoordCount)
200                {
201                        geom->mTexCoords[i].first = texCoords[i].first;
202                        geom->mTexCoords[i].second = texCoords[i].second;
203                }
204        }
205
206        mGeometry.push_back(geom);
207}
208
209
210bool VisibilitySolutionConverter::Convert(const std::string &sceneInputFilename,
211                                                                                  const std::string &sceneOutputFilename,
212                                                                                  const std::string &bvhInputFilename,
213                                                                                  const std::string &bvhOutputFilename)
214{
215        mNumShapes = 0;
216       
217        // delete previous geometry
218        for (size_t i = 0; i < mGeometry.size(); ++ i)
219        {
220                delete [] mGeometry[i]->mVertices;
221                delete [] mGeometry[i]->mNormals;
222                delete [] mGeometry[i]->mTexCoords;
223
224                delete mGeometry[i];
225        }
226       
227        mGeometry.clear();
228
229        if (!LoadSolution(bvhInputFilename))
230        {
231                cerr << "could not read file" << endl;
232                return false;
233        }
234
235        if (!ReadScene(sceneInputFilename))
236        {
237                cerr << "could not read file" << endl;
238                return false;
239        }
240
241        if (!WriteScene(sceneOutputFilename))
242        {
243                cerr << "could not write file" << endl;
244                return false;
245        }
246
247        /*if (!WriteBvh(bvhOutputFilename))
248        {
249                cerr << "could not write file" << endl;
250                return false;
251        }*/
252
253        return true;
254}
255
256
257bool VisibilitySolutionConverter::ReadScene(const string &filename)
258{
259        FILE *file;
260
261        if ((file = fopen(filename.c_str(), "r")) == NULL)
262        {       
263                return false;
264        }
265       
266        VertexArray faceVertices;
267        VertexArray faceNormals;
268        vector<TexCoord> faceTexcoords;
269
270        VertexArray vertices;
271        VertexArray normals;
272        vector<TexCoord> texcoords;
273
274        vector<int> indices;
275
276        int line = 0;
277        const int len = 10000;
278        char str[len];
279
280        while (fgets(str, len, file) != NULL)
281        {
282                if (line % 1000000 == 0)
283                        cout << line << " " << str << endl;
284
285                ++ line;
286
287                switch (str[0])
288                {
289                case 'v': // vertex or normal
290                        {
291                                float x, y, z;
292
293                                if (vertices.size() >= 1000000 * 3) continue;
294
295                                switch (str[1])
296                                {
297                                case 'n' :
298                                        sscanf(str + 2, "%f %f %f", &x, &y, &z);
299                                        normals.push_back(SimpleVec(x, y, z));
300                                        break;
301                                case 't':
302                                        sscanf(str + 2, "%f %f", &x, &y);
303                                        texcoords.push_back(pair<float, float>(x, y));
304                                        break;
305                                default:
306                                        sscanf(str + 1, "%f %f %f", &x, &y, &z);
307                                        //const float scale = 5e-3f;
308                                        const float scale = 0.1f;
309                                        vertices.push_back(SimpleVec(x * scale, y * scale, z * scale));
310                                        //cout <<"v " << x << " " << y << " "<< z << " ";
311                                }
312                                break;
313                        }
314                case 'f':
315                        {
316                                //////////
317                                //-- indices in the current line
318
319                                if (faceVertices.size() >= 1000000 * 3) continue;
320
321                                LoadIndices(str,
322                                                vertices, normals, texcoords,
323                                                faceVertices, faceNormals, faceTexcoords);
324
325                                break;
326                        } 
327                        break;
328                default:
329                        // throw away line
330                        break;
331                }
332        }
333
334        if (!faceVertices.empty())
335        {
336                ++ mNumShapes;
337
338                ConstructBvhObjects(faceVertices, faceNormals, faceTexcoords);
339
340                faceVertices.clear();
341                faceNormals.clear();
342                faceTexcoords.clear();
343        }
344
345        fclose(file);
346       
347        return true;
348}
349
350
351static inline float RandomColor(float x)
352{
353        return x + (1.0f - x) * (float)rand() / RAND_MAX;
354}
355
356
357void VisibilitySolutionConverter::WriteGeometry(ogzstream &str, Geometry *geom)
358{
359        int vertexCount = geom->mVertexCount;
360        str.write(reinterpret_cast<char *>(&vertexCount), sizeof(int));
361 
362        str.write(reinterpret_cast<char *>(geom->mVertices), sizeof(SimpleVec) * vertexCount);
363        str.write(reinterpret_cast<char *>(geom->mNormals), sizeof(SimpleVec) * vertexCount);
364
365        int texCoordCount = 0;//geom->mTexcoordCount;
366        str.write(reinterpret_cast<char *>(&texCoordCount), sizeof(int));
367
368        if (texCoordCount)
369        {
370                str.write(reinterpret_cast<char *>(geom->mTexCoords), sizeof(float) * texCoordCount * 2);
371        }
372
373        ///////
374        //-- texture
375
376        int texId = -1;
377        str.write(reinterpret_cast<char *>(&texId), sizeof(int));
378
379        bool alphaTestEnabled = false;
380        bool cullFaceEnabled = true;
381
382        str.write(reinterpret_cast<char *>(&alphaTestEnabled), sizeof(bool));
383        str.write(reinterpret_cast<char *>(&cullFaceEnabled), sizeof(bool));
384
385        // material
386        bool hasMaterial = true;
387       
388        str.write(reinterpret_cast<char *>(&hasMaterial), sizeof(bool));
389       
390        if (hasMaterial)
391        {
392                SimpleVec ambient, diffuse, spec, emm;
393
394                ambient.x = ambient.y = ambient.z = 0.2f;
395                //diffuse.x = diffuse.y = diffuse.z = 1.0f;
396
397                diffuse.x = RandomColor(0.5f);
398                diffuse.y = RandomColor(0.5f);
399                diffuse.z = RandomColor(0.5f);
400
401                spec.x    = spec.y    = spec.z    =  .0f;
402                emm = spec;
403
404                // only write rgb part of the material
405                str.write(reinterpret_cast<char *>(&ambient), sizeof(SimpleVec));
406                str.write(reinterpret_cast<char *>(&diffuse), sizeof(SimpleVec));
407                str.write(reinterpret_cast<char *>(&spec), sizeof(SimpleVec));
408                str.write(reinterpret_cast<char *>(&emm), sizeof(SimpleVec));
409        }
410}
411
412
413bool VisibilitySolutionConverter::WriteScene(const string &filename)
414{
415        ogzstream ofile(filename.c_str());
416
417        if (!ofile.is_open())
418                return false;
419       
420
421        int textureCount = 0;
422        ofile.write(reinterpret_cast<char *>(&textureCount), sizeof(int));
423
424
425        ///////////
426        //-- write shapes
427
428        int numShapes = (int)mGeometry.size();
429        ofile.write(reinterpret_cast<char *>(&numShapes), sizeof(int));
430
431        vector<Geometry *>::const_iterator it, it_end = mGeometry.end();
432
433        for (it = mGeometry.begin(); it != it_end; ++ it)
434        {
435                WriteGeometry(ofile, *it);
436        }
437
438
439        int entityCount = numShapes;
440        ofile.write(reinterpret_cast<char *>(&entityCount), sizeof(int));
441
442
443        //////////
444        //-- write single scene entity for each shape
445
446        // all shapes belong to this scene entity
447        for (int i = 0; i < numShapes; ++ i)
448        {
449                // no transformation
450                bool hasTrafo = false;
451                ofile.write(reinterpret_cast<char *>(&hasTrafo), sizeof(bool));
452
453                // a dummy lod
454                int numLODs = 1;
455                ofile.write(reinterpret_cast<char *>(&numLODs), sizeof(int));
456
457                float dist = 0;
458                ofile.write(reinterpret_cast<char *>(&dist), sizeof(float));
459
460                int shapesPerEnt = 1;
461                ofile.write(reinterpret_cast<char *>(&shapesPerEnt), sizeof(int));
462
463                int shapeId = i;
464                ofile.write(reinterpret_cast<char *>(&shapeId), sizeof(int));
465        }
466
467        return true;
468}
469
470
471void VisibilitySolutionConverter::ConstructBvhObjects(const VertexArray &vertices,
472                                                                                                          const VertexArray &normals,
473                                                                                                          const vector<TexCoord> &texCoords)
474{
475        cout << "vtx: " << vertices.size() << endl;
476
477        for (size_t i = 0; i < mBvhNodes.size(); ++ i)
478        {
479                VertexArray _vertices;
480                VertexArray _normals;
481                vector<TexCoord> _texCoords;
482
483                BvhNode *node = mBvhNodes[i];
484
485                //for (size_t j = 0; j < node->mTriangleIds.size(); ++ j)
486                for (int j = node->first; j < node->last; ++ j)
487                {
488                        const int idx = 3 * mGlobalTriangleIds[j];
489
490                        //cout << "idx: " << idx << " ";
491
492                        if (idx < 1000000 * 3)
493                        {
494                                for (int k = 0; k < 3; ++ k)
495                                {
496                                        _vertices.push_back(vertices[idx + k]);
497                                        _normals.push_back(normals[idx + k]);
498                                        //_texCoords.push_back(texCoords[idx + k]);
499                                }
500                        }
501                }
502
503                if (!_vertices.empty())
504                {
505                        ++ mNumShapes;
506                        LoadShape(_vertices, _normals, _texCoords);
507                }
508        }
509}
510
511
512bool VisibilitySolutionConverter::WriteBvh(const string &filename)
513{
514       
515        return true;
516}
517
518
519bool VisibilitySolutionConverter::ReadBvh(FILE *fr)
520{
521        int buffer[6];
522        fread(buffer, sizeof(int), 6, fr);
523
524        if (buffer[0] != MAGIC)
525        {
526                cerr << "Error: Wrong file type" << endl;
527                return false;
528        }
529
530        if (buffer[1] != (int)(1000 * BVH_VERSION))
531        {
532                cerr << "Error: Wrong BVH version" << endl;
533                return false;
534        }
535
536        // load triangle ids
537        size_t numTriangles = buffer[2];
538
539        for (size_t i = 0; i < numTriangles; ++i)
540        {
541                int id;
542                fread(&id, sizeof(int), 1, fr);
543                mGlobalTriangleIds.push_back(id);
544                //triangles[i] = scene->triangles[id];
545        }
546
547        //if (mRoot) delete mRoot;
548
549        mNumNodes = 0; // this was set to 1 in constructor!
550
551        mRoot = LoadNode(fr, 0);
552
553        if (mNumNodes != buffer[5])
554        {
555                cerr << "Warning: Loaded " << mNumNodes <<
556                            " bvh nodes instead of " << buffer[5] << endl;
557        }
558
559        fclose(fr);
560       
561        return true;
562}
563
564
565BvhNode *VisibilitySolutionConverter::LoadNode(FILE *fr, int depth)
566{
567        ++ mNumNodes;
568       
569        int buffer[4];
570        fread(buffer, sizeof(int), 4, fr);
571
572        if (buffer[2] != -1)
573        {
574                BvhInterior *interior = new BvhInterior();
575               
576                interior->first = buffer[0];
577                interior->last  = buffer[1];
578                interior->axis  = buffer[2];
579                interior->id    = buffer[3];
580                interior->depth = depth;
581
582                BvhNode *front, *back;
583
584                front = LoadNode(fr, depth + 1);
585                back  = LoadNode(fr, depth + 1);
586
587                // front->parent = (BvhNode *)interior;
588                // back->parent = (BvhNode *)interior;
589                interior->front = front;
590                interior->back = back;
591
592                //interior->box = Union(front->box, back->box);
593       
594                return (BvhNode *)interior;
595        }
596        else
597        {
598                // leaf
599                //Debug << "Info: Loading leaf (id: " << numberOfNodes << ", depth: " << depth << ")" << endl;
600                BvhLeaf *leaf = new BvhLeaf();
601                leaf->first = buffer[0];
602                leaf->last  = buffer[1];
603                leaf->axis  = buffer[2];
604                leaf->id  = buffer[3];
605
606                leaf->depth = depth;
607                //UpdateLeafBox(leaf);
608
609                mBvhNodes.push_back(leaf);
610                // leaf->id = numberOfNodes;
611                return (BvhNode *)leaf;
612        }
613}
614
615
616bool VisibilitySolutionConverter::ReadDummyTree(FILE *fr)
617{
618        int buffer[256];
619        fread(buffer, sizeof(int), 3, fr);
620
621        // read dummy bounding box
622        float dummy[6];
623        fread(dummy, sizeof(float) * 6, 1, fr);
624
625        int stack = 1;
626
627        // read dummy tree
628        while (stack)
629        {
630                int axis;
631                fread(&axis, sizeof(int), 1, fr);
632                -- stack;
633
634                if (axis != - 1)
635                {
636                        float dummy;
637                        fread(&dummy, sizeof(float), 1, fr);
638                       
639                        stack += 2;
640                }
641        }
642 
643        return true;
644}
645
646
647
648bool VisibilitySolutionConverter::LoadSolution(const string &filename)
649{
650        FILE *fr = fopen(filename.c_str(), "rb");
651
652        cerr << "Info: Loading visibility solution from file '" + filename + "'" << endl;
653 
654        if (fr == NULL)
655        {
656                cerr << "Error: Cannot open file for reading" << endl;
657                return false;
658        }
659
660        float totalSamples, totalTime;
661
662        fread(&totalSamples, sizeof(float), 1, fr);
663        fread(&totalTime, sizeof(float), 1, fr);
664
665        //viewCellsTree = new ViewCellsTree;
666        //bool ok = viewCellsTree->_LoadFromFile(fr);
667
668        bool ok = ReadDummyTree(fr);
669
670        if (ok)
671        {
672                //AllocateLeafViewCells();
673               
674                //objectsTree = new Bvh(*scene);
675                //ok = objectsTree->_LoadFromFile(fr);
676                ok = ReadBvh(fr);
677
678                /*if (ok)
679                {
680                    AllocatePvsObjects();
681                        ok = LoadPvs(fr);
682                }
683                */
684        }
685
686        fclose(fr);
687       
688        if (ok)
689                cout << "Info: visibility solution loaded" << endl;
690        else
691                cout << "Info: loading visibility solution failed" << endl;
692 
693        return true;
694}
695
696
697#if 0
698bool VisibilitySolution::LoadPvs(FILE *fw)
699
700        int number, entries;
701 
702        fread(&number, sizeof(int), 1, fw);
703
704        if (number == 0)
705        {
706                Message("Info: Warning empty PVSs in visibility solution");
707                return true;
708        }
709
710        if (number != viewCells.size())
711        {
712                Message("Info: Number of view cells does not match when loading PVSs!");
713                return false;
714        }
715
716        for (int i=0; i < number; i++)
717        {
718                fread(&entries, sizeof(int), 1, fw);
719               
720                for (int j=0; j < entries; j++)
721                {
722                        int objectId;
723                        float time;
724                        fread(&objectId, sizeof(int), 1, fw);
725                        fread(&time, sizeof(float), 1, fw);
726                        viewCells[i]->pvs.Insert(objectId, time);
727                }
728        }
729        return true;
730}
731
732
733bool ViewCellsTree::_LoadFromFile(FILE *fr)
734{
735        int buffer[256];
736        fread(buffer, sizeof(int), 3, fr);
737
738        if (buffer[0] != MAGIC)
739        {
740                Message( "Error: Wrong file type");
741                return false;
742        }
743
744        if (buffer[1] != (int)(1000*VIEWCELLS_VERSION))
745        {
746                Message( "Error: Wrong viewcells version" );
747               
748                return false;
749        }
750
751        // get the bounding box
752        fread(&box, sizeof(AxisAlignedBox3), 1, fr);
753
754        stack<ViewCellsTreeNode **> nodeStack;
755        nodeStack.push(&root);
756
757        while(!nodeStack.empty())
758        {
759                ViewCellsTreeNode *&node = *nodeStack.top();
760               
761                nodeStack.pop();
762                node = new ViewCellsTreeNode;
763               
764                fread(&node->axis, sizeof(int), 1, fr);
765               
766                if (!node->IsLeaf())
767                {
768                        fread(&node->position, sizeof(float), 1, fr);
769                       
770                        nodeStack.push(&node->front);
771                        nodeStack.push(&node->back);
772                }
773        }
774 
775        return true;
776}
777#endif
Note: See TracBrowser for help on using the repository browser.