OSDN Git Service

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