OSDN Git Service

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