OSDN Git Service

fix.
[meshio/meshio.git] / src / pmd.cpp
1 #include "pmd.h"
2 #include <iostream>
3 #include "text.h"
4
5 namespace meshio {
6 namespace pmd {
7
8 std::wstring 
9         Material::getTexture()const
10         {
11                 return text::trim(text::to_WideChar(CP_OEMCP, 
12                                         std::string(texture, texture+20)));
13         }
14
15 std::wstring 
16         Bone::getName()const
17         {
18                 return text::trim(text::to_WideChar(CP_OEMCP, 
19                                         std::string(name, name+20)));
20         }
21
22 std::wstring 
23         Morph::getName()const
24         {
25                 return text::trim(text::to_WideChar(CP_OEMCP, 
26                                         std::string(name, name+20)));
27         }
28
29 void
30         Morph::append(int index, float x, float y, float z)
31         {
32                 indices.push_back(index);
33                 pos_list.push_back(Vector3(x, y, z));
34         }
35
36 std::wstring 
37         BoneGroup::getName()const
38         {
39                 return text::trim(text::to_WideChar(CP_OEMCP, 
40                                         std::string(name, name+50)));
41         }
42
43 std::wstring 
44         IO::getName()const
45         {
46                 return text::trim(text::to_WideChar(CP_OEMCP, 
47                                         std::string(name, name+20)));
48         }
49
50 std::wstring 
51         IO::getEnglishName()const
52         {
53                 return text::trim(text::to_WideChar(CP_OEMCP, 
54                                         std::string(english_name, english_name+20)));
55         }
56
57 std::wstring 
58         RigidBody::getName()const
59         {
60                 return text::trim(text::to_WideChar(CP_OEMCP, 
61                                         std::string(name, name+20)));
62         }
63
64 std::wstring 
65         Constraint::getName()const
66         {
67                 return text::trim(text::to_WideChar(CP_OEMCP, 
68                                         std::string(name, name+20)));
69         }
70
71 // 38bytes
72 template<class READER>
73         void
74         read(READER &reader, Vertex &v)
75         {
76                 unsigned int pos=reader.getPos();
77                 reader.get(v.pos);
78                 reader.get(v.normal);
79                 reader.get(v.uv);
80                 reader.get(v.bone0);
81                 reader.get(v.bone1);
82                 reader.get(v.weight0);
83                 reader.get(v.edge_flag);
84                 assert(reader.getPos()-pos==38);
85         }
86
87
88 // 70bytes
89 template<class READER>
90         void
91         read(READER &reader, Material &m)
92         {
93                 unsigned int pos=reader.getPos();
94                 reader.get(m.diffuse);
95                 reader.get(m.shinness);
96                 reader.get(m.specular);
97                 reader.get(m.ambient);
98                 reader.get(m.toon_index);
99                 reader.get(m.flag);
100                 reader.get(m.vertex_count);
101                 text::copyStringAndFillZero(m.texture, reader.getString(20));
102                 assert(reader.getPos()-pos==70);
103         }
104
105 // 39bytes
106 template<class READER>
107         void
108         read(READER &reader, Bone &b)
109         {
110                 unsigned int pos=reader.getPos();
111                 text::copyStringAndFillZero(b.name, reader.getString(20));
112                 reader.get(b.parent_index);
113                 reader.get(b.tail_index);
114                 b.type=static_cast<BONE_TYPE>(reader.getUchar());
115                 reader.get(b.ik_index);
116                 reader.get(b.pos);
117                 assert(reader.getPos()-pos==39);
118         }
119
120 // 11+2xIK_COUNT bytes
121 template<class READER>
122         void
123         read(READER &reader, IK &ik)
124         {
125                 // 11bytes
126                 reader.get(ik.index);
127                 reader.get(ik.target);
128                 reader.get(ik.length);
129                 reader.get(ik.iterations);
130                 reader.get(ik.weight);
131                 // 2 x length bytes
132                 for(unsigned short j=0; j<ik.length; ++j){
133                         ik.children.push_back(reader.getUshort());
134                 }
135         }
136
137 // 25+12xMORPH_COUNT bytes
138 template<class READER>
139         void
140         read(READER &reader, Morph &m)
141         {
142                 // 25bytes
143                 text::copyStringAndFillZero(m.name, reader.getString(20));
144                 reader.get(m.vertex_count);
145                 m.type=static_cast<MORPH_TYPE>(reader.getUchar());
146                 // 12 x vertex_count bytes
147                 for(unsigned short i=0; i<m.vertex_count; ++i){
148                         m.indices.push_back(reader.getUint());
149                         m.pos_list.push_back(Vector3());
150                         reader.get(m.pos_list.back());
151                 }
152         }
153
154 // 83bytes
155 template<class READER>
156         void
157         read(READER &reader, RigidBody &r)
158         {
159                 unsigned int pos=reader.getPos();
160                 text::copyStringAndFillZero(r.name, reader.getString(20));
161                 reader.get(r.boneIndex);
162                 reader.get(r.group);
163                 reader.get(r.target);
164                 r.shapeType=static_cast<SHAPE_TYPE>(reader.getUchar());
165                 reader.get(r.w);
166                 reader.get(r.h);
167                 reader.get(r.d);
168                 reader.get(r.position);
169                 reader.get(r.rotation);
170                 reader.get(r.weight);
171                 reader.get(r.linearDamping);
172                 reader.get(r.angularDamping);
173                 reader.get(r.restitution);
174                 reader.get<float>(r.friction);
175                 r.processType=static_cast<PROCESS_TYPE>(reader.getUchar());
176                 assert(reader.getPos()-pos==83);
177         }
178
179 // 124bytes
180 template<class READER>
181         void
182         read(READER &reader, Constraint &c)
183         {
184                 unsigned int base_pos=reader.getPos();
185                 text::copyStringAndFillZero(c.name, reader.getString(20));
186                 reader.get(c.rigidA);
187                 reader.get(c.rigidB);
188                 reader.get(c.pos);
189                 reader.get(c.rot);
190                 reader.get(c.constraintPosMin);
191                 reader.get(c.constraintPosMax);
192                 reader.get(c.constraintRotMin);
193                 reader.get(c.constraintRotMax);
194                 reader.get(c.springPos);
195                 reader.get(c.springRot);
196                 assert(reader.getPos()-base_pos==124);
197         }
198
199 class Impl
200 {
201         IO &io_;
202         binary::IReader &reader_;
203
204 public:
205         Impl(IO &io, binary::IReader &reader)
206                 : io_(io), reader_(reader)
207                 {}
208
209         bool parse()
210         {
211                 if(!parseHeader()){
212                         return false;
213                 }
214                 if(!parseVertices()){
215                         return false;
216                 }
217                 if(!parseIndices()){
218                         return false;
219                 }
220                 if(!parseMaterials()){
221                         return false;
222                 }
223                 if(!parseBones()){
224                         return false;
225                 }
226                 if(!parseIK()){
227                         return false;
228                 }
229                 if(!parseMorph()){
230                         return false;
231                 }
232                 if(!parseFaceList()){
233                         return false;
234                 }
235                 if(!parseBoneGroupList()){
236                         return false;
237                 }
238                 if(!parseBoneList()){
239                         return false;
240                 }
241                 if(reader_.isEnd()){
242                         return true;
243                 }
244
245                 ////////////////////////////////////////////////////////////
246                 // extended data
247                 ////////////////////////////////////////////////////////////
248                 // english
249                 ////////////////////////////////////////////////////////////
250                 if(reader_.getChar()){
251                         if(!parseEnglishName()){
252                                 return false;
253                         }
254                         if(!parseEnglishBone()){
255                                 return false;
256                         }
257                         if(!parseEnglishMorph()){
258                                 return false;
259                         }
260                         if(!parseEnglishBoneList()){
261                                 return false;
262                         }
263                 }
264                 if(reader_.isEnd()){
265                         return true;
266                 }
267
268                 // toone texture
269                 ////////////////////////////////////////////////////////////
270                 if(!parseToonTextures()){
271                         return false;
272                 }
273                 if(reader_.isEnd()){
274                         return true;
275                 }
276
277                 // physics
278                 ////////////////////////////////////////////////////////////
279                 if(!parseRigid()){
280                         return false;
281                 }
282                 if(!parseConstraint()){
283                         return false;
284                 }
285
286                 // end
287                 assert(reader_.isEnd());
288
289                 return true;
290         }
291
292 private:
293         bool parseConstraint()
294         {
295                 unsigned int count=reader_.getUint();
296                 for(unsigned int i=0; i<count; ++i){
297                         io_.constraints.push_back(Constraint());
298                         read(reader_, io_.constraints.back());
299                 }
300                 return true;
301         }
302
303         bool parseRigid()
304         {
305                 unsigned int count=reader_.getUint();
306                 for(unsigned int i=0; i<count; ++i){
307                         io_.rigidbodies.push_back(RigidBody());
308                         read(reader_, io_.rigidbodies.back());
309                 }
310                 return true;
311         }
312
313         bool parseToonTextures()
314         {
315                 for(size_t i=0; i<10; ++i){
316                         reader_.getString(100);
317                 }
318                 return true;
319         }
320
321         bool parseEnglishBoneList()
322         {
323                 for(size_t i=0; i<io_.bone_group_list.size(); ++i){
324                         text::copyStringAndFillZero(
325                                         io_.bone_group_list[i].english_name, 
326                                         reader_.getString(50));
327                 }
328                 return true;
329         }
330
331         bool parseEnglishMorph()
332         {
333                 int count=io_.morph_list.size()-1;
334                 for(int i=0; i<count; ++i){
335                         text::copyStringAndFillZero(
336                                         io_.morph_list[i].english_name, reader_.getString(20));
337                 }
338                 return true;
339         }
340
341         bool parseEnglishBone()
342         {
343                 for(size_t i=0; i<io_.bones.size(); ++i){
344                         text::copyStringAndFillZero(
345                                         io_.bones[i].english_name, reader_.getString(20));
346                 }
347                 return true;
348         }
349
350         bool parseEnglishName()
351         {
352                 text::copyStringAndFillZero(io_.english_name, 
353                                 reader_.getString(20));
354                 text::copyStringAndFillZero(io_.english_comment, 
355                                 reader_.getString(256));
356                 return true;
357         }
358
359         bool parseBoneList()
360         {
361                 unsigned int count=reader_.getUint();
362                 for(unsigned int i=0; i<count; ++i){
363                         unsigned short bone=reader_.getUshort();
364                         unsigned char disp=reader_.getUchar();
365                         io_.bone_display_list.push_back(std::make_pair(bone, disp));
366                 }
367                 return true;
368         }
369
370         bool parseBoneGroupList()
371         {
372                 unsigned int count=reader_.getUchar();
373                 for(unsigned int i=0; i<count; ++i){
374                         io_.bone_group_list.push_back(BoneGroup());
375                         text::copyStringAndFillZero(
376                                         io_.bone_group_list.back().name,
377                                         reader_.getString(50));
378                 }
379                 return true;
380         }
381
382         bool parseFaceList()
383         {
384                 unsigned int count=reader_.getUchar();
385                 for(unsigned int i=0; i<count; ++i){
386                         io_.face_list.push_back(reader_.getUshort());
387                 }
388                 return true;
389         }
390
391         bool parseMorph()
392         {
393                 unsigned int count=reader_.getUshort();
394                 for(unsigned int i=0; i<count; ++i){
395                         io_.morph_list.push_back(Morph());
396                         read(reader_, io_.morph_list.back());
397                 }
398                 return true;
399         }
400
401         bool parseIK()
402         {
403                 unsigned int count=reader_.getUshort();
404                 for(unsigned int i=0; i<count; ++i){
405                         io_.ik_list.push_back(IK());
406                         read(reader_, io_.ik_list.back());
407                 }
408                 return true;
409         }
410
411         bool parseBones()
412         {
413                 unsigned int count=reader_.getUshort();
414                 for(unsigned int i=0; i<count; ++i){
415                         io_.bones.push_back(Bone());
416                         read(reader_, io_.bones.back());
417                 }
418                 return true;
419         }
420
421         bool parseMaterials()
422         {
423                 unsigned int count=reader_.getUint();
424                 for(unsigned int i=0; i<count; ++i){
425                         io_.materials.push_back(new Material());
426                         read(reader_, *io_.materials.back());
427                 }
428                 return true;
429         }
430
431         bool parseIndices()
432         {
433                 unsigned int count=reader_.getUint();
434                 for(unsigned int i=0; i<count; ++i){
435                         io_.indices.push_back(reader_.getUshort());
436                 }
437                 return true;
438         }
439
440         bool parseVertices()
441         {
442                 unsigned int count=reader_.getUint();
443                 for(unsigned int i=0; i<count; ++i){
444                         io_.vertices.push_back(Vertex());
445                         read(reader_, io_.vertices.back());
446                 }
447                 return true;
448         }
449
450         bool parseHeader()
451         {
452                 if(reader_.getString(3)!="Pmd"){
453                         //std::cout << "invalid pmd" << std::endl;
454                         return false;
455                 }
456                 reader_.get(io_.version);
457                 if(io_.version!=1.0){
458                         std::cout << "invalid vesion: " << io_.version <<std::endl;
459                         return false;
460                 }
461                 text::copyStringAndFillZero(io_.name, reader_.getString(20));
462                 text::copyStringAndFillZero(io_.comment, reader_.getString(256));
463
464                 return true;
465         }
466
467 };
468
469 ///////////////////////////////////////////////////////////////////////////////
470 // IO
471 ///////////////////////////////////////////////////////////////////////////////
472 IO::IO()
473 : version(0)
474 {}
475
476 IO::~IO()
477 {
478         for(size_t i=0; i<materials.size(); ++i){
479                 delete materials[i];
480         }
481         materials.clear();
482 }
483
484 bool IO::read(binary::IReader &input)
485 {
486         Impl impl(*this, input);
487         if(!impl.parse()){
488                 return false;
489         }
490
491         ////////////////////////////////////////////////////////////
492         // post process
493         ////////////////////////////////////////////////////////////
494         if(!morph_list.empty()){
495                 // validate morph
496                 assert(morph_list[0].type==MORPH_BASE);
497                 // check base
498                 Morph &base=morph_list[0];
499                 for(size_t i=0; i<base.vertex_count; ++i){
500                         assert(vertices[base.indices[i]].pos==base.pos_list[i]);
501                 }
502                 // check each face
503                 for(size_t i=1; i<morph_list.size(); ++i){
504                         Morph &m=morph_list[i];
505                         assert(m.type!=MORPH_BASE);
506                 }
507         }
508         ////////////////////////////////////////////////////////////
509         // setup bone
510         ////////////////////////////////////////////////////////////
511         for(size_t i=0; i<bones.size(); ++i){
512                 Bone &bone=bones[i];
513                 bone.index=i;
514                 if(bone.parent_index!=0xFFFF){
515                         bone.parent=&bones[bone.parent_index];
516                         bone.parent->children.push_back(&bone);
517                 }
518                 if(bone.tail_index!=0){
519                         bone.tail=bones[bone.tail_index].pos;
520                 }
521         }
522
523         return true;
524 }
525
526 /*
527 bool IO::read(const char *path)
528 {
529         std::vector<char> all;
530         binary::readAll(path, all);
531         if(all.empty()){
532                 return false;
533         }
534         binary::MemoryReader reader(&all[0], all.size());
535         return read(reader);
536 }
537 */
538
539 bool IO::read(const wchar_t *path)
540 {
541         std::vector<char> all;
542         binary::readAll(path, all);
543         std::cerr << all.size() << "bytes" << std::endl;
544         if(all.empty()){
545                 return false;
546         }
547         binary::MemoryReader reader(&all[0], all.size());
548         return read(reader);
549 }
550
551 bool IO::write(binary::IWriter &w)
552 {
553         w.write("Pmd", 3);
554         w.writeValue<float>(version);
555         w.write(name, 20);
556         w.write(comment, 256);
557
558         // vertices
559         //std::cout << "vertices" << std::endl;
560         w.writeValue<DWORD>(vertices.size());
561         for(size_t i=0; i<vertices.size(); ++i){
562                 Vertex &v=vertices[i];
563                 w.writeValue<float>(v.pos.x);
564                 w.writeValue<float>(v.pos.y);
565                 w.writeValue<float>(v.pos.z);
566                 w.writeValue<float>(v.normal.x);
567                 w.writeValue<float>(v.normal.y);
568                 w.writeValue<float>(v.normal.z);
569                 w.writeValue<float>(v.uv.x);
570                 w.writeValue<float>(v.uv.y);
571                 w.writeValue<WORD>(v.bone0);
572                 w.writeValue<WORD>(v.bone1);
573                 w.writeValue<BYTE>(v.weight0);
574                 w.writeValue<BYTE>(v.edge_flag);
575         }
576
577         // faces
578         //std::cout << "faces" << std::endl;
579         w.writeValue<DWORD>(indices.size());
580         if(indices.size()>0){
581                 w.writeArray<WORD>(&indices[0], indices.size());
582         }
583
584         // materials
585         //std::cout << "materials" << std::endl;
586         w.writeValue<DWORD>(materials.size());
587         for(size_t i=0; i<materials.size(); ++i){
588                 Material &m=*materials[i];
589                 w.writeValue<float>(m.diffuse.r);
590                 w.writeValue<float>(m.diffuse.g);
591                 w.writeValue<float>(m.diffuse.b);
592                 w.writeValue<float>(m.diffuse.a);
593                 w.writeValue<float>(m.shinness);
594                 w.writeValue<float>(m.specular.r);
595                 w.writeValue<float>(m.specular.g);
596                 w.writeValue<float>(m.specular.b);
597                 w.writeValue<float>(m.ambient.r);
598                 w.writeValue<float>(m.ambient.g);
599                 w.writeValue<float>(m.ambient.b);
600                 w.writeValue<BYTE>(m.toon_index);
601                 w.writeValue<BYTE>(m.flag);
602                 w.writeValue<DWORD>(m.vertex_count);
603                 w.writeArray<char>(m.texture, 20);
604         }
605
606         // bones
607         //std::cout << "bones" << std::endl;
608         w.writeValue<WORD>(bones.size());
609         for(size_t i=0; i<bones.size(); ++i){
610                 Bone &b=bones[i];
611                 w.writeArray<char>(b.name, 20);
612                 w.writeValue<WORD>(b.parent_index);
613                 w.writeValue<WORD>(b.tail_index);
614                 w.writeValue<BYTE>(b.type);
615                 w.writeValue<WORD>(b.ik_index);
616                 w.writeValue<float>(b.pos.x);
617                 w.writeValue<float>(b.pos.y);
618                 w.writeValue<float>(b.pos.z);
619         }
620
621         // ik
622         //std::cout << "ik" << std::endl;
623         w.writeValue<WORD>(ik_list.size());
624         for(size_t i=0; i<ik_list.size(); ++i){
625                 IK &ik=ik_list[i];
626                 w.writeValue<WORD>(ik.index);
627                 w.writeValue<WORD>(ik.target);
628                 w.writeValue<BYTE>(ik.length);
629                 w.writeValue<WORD>(ik.iterations);
630                 w.writeValue<float>(ik.weight);
631                 WORD parent_index=bones[ik.target].parent_index;
632                 for(size_t j=0; j<ik.length; 
633                                 ++j, parent_index=bones[parent_index].parent_index){
634                         w.writeValue<WORD>(parent_index);
635                 }
636         }
637
638         // morph
639         //std::cout << "morph" << std::endl;
640         w.writeValue<WORD>(morph_list.size());
641         for(size_t i=0; i<morph_list.size(); ++i){
642                 Morph &m=morph_list[i];
643                 w.writeArray<char>(m.name, 20);
644                 w.writeValue<DWORD>(m.indices.size());
645                 w.writeValue<BYTE>(m.type);
646                 for(size_t j=0; j<m.indices.size(); ++j){
647                         w.writeValue<DWORD>(m.indices[j]);
648                         Vector3 &pos=m.pos_list[j];
649                         w.writeValue<float>(pos.x);
650                         w.writeValue<float>(pos.y);
651                         w.writeValue<float>(pos.z);
652                 }
653         }
654
655         // face list
656         //std::cout << "face list" << std::endl;
657         w.writeValue<BYTE>(face_list.size());
658         if(face_list.size()>0){
659                 w.writeArray<WORD>(&face_list[0], face_list.size());
660         }
661
662         // bone naem list
663         //std::cout << "bone name list" << std::endl;
664         w.writeValue<BYTE>(bone_group_list.size());
665         for(size_t i=0; i<bone_group_list.size(); ++i){
666                 // 50bytes
667                 w.writeArray<char>(bone_group_list[i].name, 50);
668         }
669
670         // bone list
671         //std::cout << "bone list" << std::endl;
672         w.writeValue<DWORD>(bone_display_list.size());
673         for(size_t i=0; i<bone_display_list.size(); ++i){
674                 w.writeValue<WORD>(bone_display_list[i].first);
675                 w.writeValue<BYTE>(bone_display_list[i].second);
676         }
677
678         ////////////////////////////////////////////////////////////
679         // extend
680         ////////////////////////////////////////////////////////////
681         w.writeValue<char>(0x01);
682
683         ////////////////////////////////////////////////////////////
684         // english names
685         ////////////////////////////////////////////////////////////
686         w.writeArray<char>(english_name, 20);
687         w.writeArray<char>(english_comment, 256);
688
689         for(size_t i=0; i<bones.size(); ++i){
690                 w.writeArray<char>(bones[i].english_name, 20);
691         }
692
693         for(size_t i=1; i<morph_list.size(); ++i){
694                 w.writeArray<char>(morph_list[i].english_name, 20);
695         }
696
697         for(size_t i=0; i<bone_group_list.size(); ++i){
698                 w.writeArray<char>(bone_group_list[i].english_name, 50);
699         }
700
701         ////////////////////////////////////////////////////////////
702         // toon textures
703         ////////////////////////////////////////////////////////////
704         for(size_t i=0; i<10; ++i){
705                 w.writeArray<char>(toon_textures[i].name, 100);
706         }
707
708         ////////////////////////////////////////////////////////////
709         // rigid bodies
710         ////////////////////////////////////////////////////////////
711         w.writeValue<DWORD>(rigidbodies.size());
712         for(size_t i=0; i<rigidbodies.size(); ++i){
713                 RigidBody &rb=rigidbodies[i];
714                 w.writeArray<char>(rb.name, 20);
715                 w.writeValue<WORD>(rb.boneIndex);
716                 w.writeValue<BYTE>(rb.group);
717                 w.writeValue<WORD>(rb.target);
718                 w.writeValue<BYTE>(rb.shapeType);
719                 w.writeValue<float>(rb.w);
720                 w.writeValue<float>(rb.h);
721                 w.writeValue<float>(rb.d);
722                 w.writeValue<float>(rb.position.x);
723                 w.writeValue<float>(rb.position.y);
724                 w.writeValue<float>(rb.position.z);
725                 w.writeValue<float>(rb.rotation.x);
726                 w.writeValue<float>(rb.rotation.y);
727                 w.writeValue<float>(rb.rotation.z);
728                 w.writeValue<float>(rb.weight);
729                 w.writeValue<float>(rb.linearDamping);
730                 w.writeValue<float>(rb.angularDamping);
731                 w.writeValue<float>(rb.restitution);
732                 w.writeValue<float>(rb.friction);
733                 w.writeValue<BYTE>(rb.processType);
734         }
735
736         ////////////////////////////////////////////////////////////
737         // constraints
738         ////////////////////////////////////////////////////////////
739         w.writeValue<DWORD>(constraints.size());
740         for(size_t i=0; i<constraints.size(); ++i){
741                 Constraint &c=constraints[i];
742                 w.writeArray<char>(c.name, 20);
743                 w.writeValue<DWORD>(c.rigidA);
744                 w.writeValue<DWORD>(c.rigidB);
745                 w.writeValue<float>(c.pos.x);
746                 w.writeValue<float>(c.pos.y);
747                 w.writeValue<float>(c.pos.z);
748                 w.writeValue<float>(c.rot.x);
749                 w.writeValue<float>(c.rot.y);
750                 w.writeValue<float>(c.rot.z);
751                 w.writeValue<float>(c.constraintPosMin.x);
752                 w.writeValue<float>(c.constraintPosMin.y);
753                 w.writeValue<float>(c.constraintPosMin.z);
754                 w.writeValue<float>(c.constraintPosMax.x);
755                 w.writeValue<float>(c.constraintPosMax.y);
756                 w.writeValue<float>(c.constraintPosMax.z);
757                 w.writeValue<float>(c.constraintRotMin.x);
758                 w.writeValue<float>(c.constraintRotMin.y);
759                 w.writeValue<float>(c.constraintRotMin.z);
760                 w.writeValue<float>(c.constraintRotMax.x);
761                 w.writeValue<float>(c.constraintRotMax.y);
762                 w.writeValue<float>(c.constraintRotMax.z);
763                 w.writeValue<float>(c.springPos.x);
764                 w.writeValue<float>(c.springPos.y);
765                 w.writeValue<float>(c.springPos.z);
766                 w.writeValue<float>(c.springRot.x);
767                 w.writeValue<float>(c.springRot.y);
768                 w.writeValue<float>(c.springRot.z);
769         }
770
771         return true;
772 }
773
774 bool IO::write(const char *path)
775 {
776         binary::FileWriter w(path);
777         return write(w);
778 }
779
780 bool IO::write(const wchar_t *path)
781 {
782         binary::FileWriter w(path);
783         return write(w);
784 }
785
786 const Vector2* IO::getUV(int index)const
787 {
788         return &vertices[index].uv;
789 }
790
791 void Bone::setName(const char *src)
792 {
793         strncpy(name, src, 20);
794 }
795
796 void Bone::setEnglishName(const char *src)
797 {
798         strncpy(english_name, src, 20);
799 }
800
801 void BoneGroup::setName(const char *src)
802 {
803         strncpy(name, src, 20);
804 }
805
806 void BoneGroup::setEnglishName(const char *src)
807 {
808         strncpy(english_name, src, 20);
809 }
810
811 void Morph::setName(const char *src)
812 {
813         strncpy(name, src, 20);
814 }
815
816 void Morph::setEnglishName(const char *src)
817 {
818         strncpy(english_name, src, 20);
819 }
820
821 void RigidBody::setName(const char *src)
822 {
823         strncpy(name, src, 20);
824 }
825
826 void Constraint::setName(const char *src)
827 {
828         strncpy(name, src, 20);
829 }
830
831 void Material::setTexture(const char *src)
832 {
833         strncpy(texture, src, 20);
834 }
835
836
837 } // namespace
838 } // namespace
839