OSDN Git Service

fix for gcc-4.5 on cygwin
[meshio/meshio.git] / src / mqo.cpp
1 #include "mqo.h"
2 #include "linereader.h"
3 #include <iostream>
4 #include <fstream>
5 #include <sstream>
6 #include <iomanip>
7 #include <vector>
8
9 namespace meshio {
10   namespace mqo {
11
12     //! Tokenizer
13     struct DELIMITER
14     {
15       bool operator()(char c)
16       {
17         switch(c)
18         {
19           case ' ':
20           case '\t':
21           case '(':
22           case ')':
23             return true;
24           default:
25             return false;
26         }
27       }
28     };
29     typedef LineSplitter<DELIMITER> SPLITTER;
30
31
32     //! \8eÀ\91\95
33     class Implementation
34     {
35       Scene &scene;
36       std::vector<Material> &materials;
37       std::vector<Object> &objects;
38
39     public:
40       Implementation(Scene &_scene, std::vector<Material> &_materials,
41           std::vector<Object> &_objects)
42         : scene(_scene), materials(_materials), objects(_objects)
43       {}
44
45       template<class READER> bool 
46         parse(READER reader)
47         {
48           while(!reader.isEnd()){
49             cstr line=reader.getLine();
50             SPLITTER splitter(line);
51             cstr key=splitter.get();
52             if(key=="Scene"){
53               if(!readSceneChunk(reader)){
54                 return false;
55               }
56             }
57             else if(key=="Material"){
58               if(!readMaterialChunk(reader, splitter.getInt())){
59                 return false;
60               }
61             }
62             else if(key=="Object"){
63               if(!readObjectChunk(reader, splitter.getQuated())){
64                 return false;
65               }
66             }
67             else if(key=="Eof"){
68               if(materials.empty()){
69                 // fallback
70                 //materials.push_back(Material());
71               }
72               return true;
73             }
74           }
75           std::cout << "not found 'EOF'" << std::endl;
76           return true;
77         }
78
79
80     private:
81       template<class READER> bool 
82         readObjectChunk(READER &reader, cstr name)
83         {
84           objects.push_back(Object());
85           Object &object=objects.back();
86           object.name=name.str();
87           while(!reader.isEnd()){
88             cstr line=reader.getLine();
89             if(line=="}"){
90               return true;
91             }
92             SPLITTER splitter(line);
93             cstr key=splitter.get();
94             if(key=="depth"){
95               object.depth=splitter.getInt();
96             }
97             else if(key=="folding"){
98               object.folding=splitter.getInt();
99             }
100             else if(key=="scale"){
101               object.scale=splitter.getVector3();
102             }
103             else if(key=="rotation"){
104               object.rotation=splitter.getVector3();
105             }
106             else if(key=="translation"){
107               object.translation=splitter.getVector3();
108             }
109             else if(key=="visible"){
110               object.visible=splitter.getInt();
111             }
112             else if(key=="locking"){
113               object.locking=splitter.getInt();
114             }
115             else if(key=="shading"){
116               object.shading=splitter.getInt();
117             }
118             else if(key=="facet"){
119               object.smoothing=splitter.getFloat();
120             }
121             else if(key=="color"){
122               object.color=splitter.getVector3();
123             }
124             else if(key=="color_type"){
125               object.color_type=splitter.getInt();
126             }
127             else if(key=="vertex"){
128               if(!readObjectVertexChunk(reader, object, splitter.getInt())){
129                 return false;
130               }
131             }
132             else if(key=="face"){
133               if(!readObjectFaceChunk(reader, object, splitter.getInt())){
134                 return false;
135               }
136             }
137             else if(key=="segment"){
138               // ToDo
139               continue;
140             }
141             else if(key=="patch"){
142               // ToDo
143               continue;
144             }
145             else if(key=="mirror"){
146               object.mirror=splitter.getInt();
147             }
148             else{
149               std::cout << "unknown object key: " << key << std::endl;
150             }
151           }
152           std::cout << "fail to readObjectChunk" << std::endl;
153           return false;
154         }
155       template<class READER> bool 
156         readObjectVertexChunk(READER &reader, 
157             Object &object, size_t vertex_count)
158         {
159           while(!reader.isEnd()){
160             cstr line=reader.getLine();
161             if(line=="}"){
162               if(object.vertices.size()!=vertex_count){
163                 std::cout << "invalid vertex count." 
164                   << " expected " << vertex_count
165                   << ", but " << object.vertices.size()
166                   << std::endl;
167                 return false;
168               }
169               return true;
170             }
171             object.vertices.push_back(SPLITTER(line).getVector3());
172           }
173           std::cout << "fail to readObjectVertexChunk" << std::endl;
174           return false;
175         }
176
177       template<class READER> bool 
178         readObjectFaceChunk(READER &reader,
179             Object &object, size_t face_count)
180         {
181           while(!reader.isEnd()){
182             cstr line=reader.getLine();
183             if(line=="}"){
184               if(object.faces.size()!=face_count){
185                 std::cout << "invalid face count."
186                   << " expected " << face_count
187                   << ", but " << object.faces.size()
188                   << std::endl;
189                 return false;
190               }
191               return true;
192             }
193             if(!readObjectFaceLine(object, line)){
194               return false;
195             }
196           }
197           std::cout << "fail to readFaceChunk" << std::endl;
198           return false;
199         }
200
201       bool 
202         readObjectFaceLine(Object &object, cstr line)
203         {
204           object.faces.push_back(Face());
205           Face &face=object.faces.back();
206           SPLITTER splitter(line);
207           face.index_count=splitter.getInt();
208           while(true){
209             cstr key=splitter.get();
210             if(key==""){
211               break;
212             }
213
214             if(key=="V"){
215               for(size_t i=0; i<face.index_count; ++i){
216                 face.indices[i]=splitter.getInt();
217               }
218             }
219             else if(key=="M"){
220               face.material_index=splitter.getInt();
221             }
222             else if(key=="UV"){
223               for(size_t i=0; i<face.index_count; ++i){
224                 face.uv[i]=splitter.getVector2();
225               }
226             }
227             else if(key=="COL"){
228               for(size_t i=0; i<face.index_count; ++i){
229                 face.color[i]=
230                   fRGBA::createFromUInt(splitter.getInt());
231               }
232             }
233             else{
234               std::cout << "unknown face key: " 
235                 << '"' << key << '"'  << std::endl
236                 ;
237               //return false;
238               break;
239             }
240           }
241           return true;
242         }
243
244       template<class READER> bool 
245         readMaterialChunk(READER &reader, size_t material_count)
246         {
247           while(!reader.isEnd()){
248             cstr line=reader.getLine();
249             if(line=="}"){
250               if(materials.size()!=material_count){
251                 std::cout << "invalid material count." 
252                   << " expected " << material_count
253                   << ", but " << materials.size()
254                   << std::endl;
255                 return false;
256               }
257               return true;
258             }
259             readMaterialLine(line);
260           }
261           std::cout << "fail to readMaterialChunk" << std::endl;
262           return false;
263         }
264
265       void 
266         readMaterialLine(cstr line)
267         {
268           materials.push_back(Material());
269           Material &material=materials.back();
270
271           SPLITTER splitter(line);
272           material.name=splitter.getQuated().str();
273           while(true){
274             cstr key=splitter.get();
275             if(key==""){
276               break;
277             }
278             else if(key=="shader"){
279               material.shader=splitter.getInt();
280             }
281             else if(key=="col"){
282               material.color=splitter.getFloatRGBA();
283             }
284             else if(key=="dif"){
285               material.diffuse=splitter.getFloat();
286             }
287             else if(key=="amb"){
288               material.ambient=splitter.getFloat();
289             }
290             else if(key=="emi"){
291               material.emit=splitter.getFloat();
292             }
293             else if(key=="spc"){
294               material.specular=splitter.getFloat();
295             }
296             else if(key=="power"){
297               material.power=splitter.getFloat();
298             }
299             else if(key=="tex"){
300               material.texture=splitter.getQuated().str();
301             }
302             else if(key=="aplane"){
303               material.alphamap=splitter.getQuated().str();
304             }
305             else if(key=="bump"){
306               material.bumpmap=splitter.getQuated().str();
307             }
308             else if(key=="vcol"){
309               material.vcol=splitter.getInt();
310             }
311             else{
312               std::cout << "unknown material key: \"" << key << '"' << std::endl;
313               //assert(false);
314               return;
315             }
316           }
317         }
318
319       template<class READER> bool 
320         readSceneChunk(READER &reader)
321         {
322           while(!reader.isEnd()){
323             cstr line=reader.getLine();
324             if(line=="}"){
325               return true;
326             }
327             SPLITTER splitter(line);
328             cstr key=splitter.get();
329             if(key=="pos"){
330               scene.pos=splitter.getVector3();
331             }
332             else if(key=="lookat"){
333               scene.lookat=splitter.getVector3();
334             }
335             else if(key=="head"){
336               scene.head=splitter.getFloat();
337             }
338             else if(key=="pich") {
339               scene.pitch=splitter.getFloat();
340             }
341             else if(key=="ortho"){
342               scene.ortho=splitter.getInt();
343             }
344             else if(key=="zoom2"){
345               scene.zoom2=splitter.getFloat();
346             }
347             else if(key=="amb"){
348               scene.ambient=splitter.getVector3();
349             }
350             else{
351               std::cout << "unknown scene key: " << key << std::endl;
352             }
353           }
354           std::cout << "fail to readSceneChunk" << std::endl;
355           return false;
356         }
357
358       template<class READER> bool 
359         readChunk(READER &reader)
360         {
361           int level=1;
362           while(!reader.isEnd()){
363             cstr line=reader.getLine();
364             if(line=="}"){
365               level--;
366               if(level==0){
367                 return true;
368               }
369             }
370             else if(line.include('{')){
371               level+=1;
372             }
373           }
374           return false;
375         }
376
377     };
378
379
380     // IO
381     bool IO::read(binary::IReader &input)
382     {
383       LineReader<IsCRLF, IsWhiteSpace, IsEmpty> 
384         reader(input);
385       cstr line=reader.getLine();
386       if(line!="Metasequoia Document"){
387         return false;
388       }
389       line=reader.getLine();
390       if(line!="Format Text Ver 1.0"){
391         return false;
392       }
393
394       return Implementation(scene, materials, objects).parse(reader);
395     }
396
397     bool IO::read(const char *path)
398     {
399       std::vector<char> all;
400       binary::readAll(path, all);
401       if(all.empty()){
402         return false;
403       }
404       binary::MemoryReader reader(&all[0], all.size());
405       return read(reader);
406     }
407
408     bool IO::write(binary::IWriter &writer)
409     {
410       // header
411       writer.printLn("Metasequoia Document");
412       writer.printLn("Format Text Ver 1.0");
413       writer.printLn("");
414
415       // scene
416       writer.printLn("Scene {");
417       writer.printLn("\tpos 0.0000 0.0000 1500.0000");
418       writer.printLn("\tlookat 0.0000 0.0000 0.0000");
419       writer.printLn("\thead -0.5236");
420       writer.printLn("\tpich 0.5236");
421       writer.printLn("\tortho 0");
422       writer.printLn("\tzoom2 5.0000");
423       writer.printLn("\tamb 0.250 0.250 0.250");
424       writer.printLn("}");
425
426       // materials
427       if(materials.size()>0){
428         writer.printLn("Material %d {", materials.size());
429         /*
430         for(size_t i=0; i<materials.size(); ++i){
431           Material &m=materials[i];
432         }
433         */
434         writer.printLn("}");
435       }
436
437       // objects
438       for(size_t i=0; i<objects.size(); ++i){
439         Object &o=objects[i];
440         writer.printLn("Object \"%s\" {", o.name.c_str());
441         writer.printLn("\tdepth 0");
442         writer.printLn("\tfolding 0");
443         writer.printLn("\tscale 1.000000 1.000000 1.000000");
444         writer.printLn("\trotation 0.000000 0.000000 0.000000");
445         writer.printLn("\ttranslation 0.000000 0.000000 0.000000");
446         writer.printLn("\tvisible 15");
447         writer.printLn("\tlocking 0");
448         writer.printLn("\tshading 1");
449         writer.printLn("\tfacet 59.5");
450         writer.printLn("\tcolor 0.898 0.400 0.137");
451         writer.printLn("\tcolor_type 0");
452         // vertex
453         writer.printLn("\tvertex %d {", o.vertices.size());
454         for(size_t j=0; j<o.vertices.size(); ++j){
455           Vector3 &v=o.vertices[j];
456           writer.printLn("\t\t%.4f %.4f %.4f", v.x, v.y, v.z);
457         }
458         writer.printLn("\t}");
459         // face
460         writer.printLn("\tface %d {", o.faces.size());
461         for(size_t j=0; j<o.faces.size(); ++j){
462           Face &f=o.faces[j];
463
464           std::stringstream ss;
465           ss.setf(std::ios_base::fixed, std::ios_base::floatfield);
466           ss 
467             << "\t\t"
468             << f.index_count
469             ;
470           ss << " V(";
471           for(size_t k=0; k<f.index_count; ++k){
472             if(k){
473               ss << ' ';
474             }
475             ss << f.indices[k];
476           }
477           ss << ") UV(";
478           for(size_t k=0; k<f.index_count; ++k){
479             if(k){
480               ss << ' ';
481             }
482             Vector2 &uv=f.uv[k];
483             ss 
484               << std::setprecision(5) << uv.x 
485               << ' ' << std::setprecision(5) << uv.y;
486           }
487           ss << ")";
488
489           writer.printLn(ss.str().c_str());
490         }
491         writer.printLn("\t}");
492         // close
493         writer.printLn("}");
494       }
495       // Eof
496       writer.printLn("Eof");
497
498       return true;
499     }
500
501     bool IO::write(const char *path)
502     {
503       binary::FileWriter writer(path);
504       return write(writer);
505     }
506
507   }
508 }