4 * License : The MIT License
5 * Copyright(c) 2010 MikuToga Partners
8 package jp.sourceforge.mikutoga.pmd.model.xml;
10 import java.awt.Color;
11 import java.io.IOException;
12 import java.io.OutputStream;
13 import java.util.List;
15 import jp.sourceforge.mikutoga.corelib.I18nText;
16 import jp.sourceforge.mikutoga.math.MkPos2D;
17 import jp.sourceforge.mikutoga.math.MkPos3D;
18 import jp.sourceforge.mikutoga.math.MkVec3D;
19 import jp.sourceforge.mikutoga.pmd.BoneType;
20 import jp.sourceforge.mikutoga.pmd.Deg3d;
21 import jp.sourceforge.mikutoga.pmd.MorphType;
22 import jp.sourceforge.mikutoga.pmd.Rad3d;
23 import jp.sourceforge.mikutoga.pmd.RigidShapeType;
24 import jp.sourceforge.mikutoga.pmd.TripletRange;
25 import jp.sourceforge.mikutoga.pmd.model.BoneGroup;
26 import jp.sourceforge.mikutoga.pmd.model.BoneInfo;
27 import jp.sourceforge.mikutoga.pmd.model.DynamicsInfo;
28 import jp.sourceforge.mikutoga.pmd.model.IKChain;
29 import jp.sourceforge.mikutoga.pmd.model.JointInfo;
30 import jp.sourceforge.mikutoga.pmd.model.Material;
31 import jp.sourceforge.mikutoga.pmd.model.MorphPart;
32 import jp.sourceforge.mikutoga.pmd.model.MorphVertex;
33 import jp.sourceforge.mikutoga.pmd.model.PmdModel;
34 import jp.sourceforge.mikutoga.pmd.model.RigidGroup;
35 import jp.sourceforge.mikutoga.pmd.model.RigidInfo;
36 import jp.sourceforge.mikutoga.pmd.model.RigidShape;
37 import jp.sourceforge.mikutoga.pmd.model.SerialNumbered;
38 import jp.sourceforge.mikutoga.pmd.model.ShadeInfo;
39 import jp.sourceforge.mikutoga.pmd.model.Surface;
40 import jp.sourceforge.mikutoga.pmd.model.ToonMap;
41 import jp.sourceforge.mikutoga.pmd.model.Vertex;
42 import jp.sourceforge.mikutoga.xml.BasicXmlExporter;
43 import jp.sourceforge.mikutoga.xml.XmlResourceResolver;
46 * XML形式でPMDモデルデータを出力する。
48 public class PmdXmlExporter extends BasicXmlExporter{
50 private static final String TOP_COMMENT =
51 " MikuMikuDance\n model-data(*.pmd) on XML";
52 private static final String SCHEMA_LOCATION =
53 PmdXmlResources.NS_PMDXML + " " + PmdXmlResources.SCHEMA_PMDXML;
56 private static final String CR = "\r"; // 0x0d
58 private static final String LF = "\n"; // 0x0a
60 private static final String CRLF = CR + LF; // 0x0d, 0x0a
62 private static final String PFX_SURFACEGROUP = "sg";
63 private static final String PFX_TOONFILE = "tf";
64 private static final String PFX_VERTEX = "vtx";
65 private static final String PFX_BONE = "bn";
66 private static final String PFX_RIGID = "rd";
67 private static final String PFX_RIGIDGROUP = "rg";
69 private static final String BONETYPE_COMMENT =
71 + "[0 : ROTATE : Rotate : 回転 :]\n"
72 + "[1 : ROTMOV : Rotate/Move : 回転/移動 :]\n"
73 + "[2 : IK : IK : IK :]\n"
74 + "[3 : UNKNOWN : Unknown : 不明 :]\n"
75 + "[4 : UNDERIK : Under IK : IK影響下(回転) :]\n"
76 + "[5 : UNDERROT : Under rotate : 回転影響下 :]\n"
77 + "[6 : IKCONNECTED : IK connected : IK接続先 :]\n"
78 + "[7 : HIDDEN : Hidden : 非表示 :]\n"
79 + "[8 : TWIST : Twist : 捩り :]\n"
80 + "[9 : LINKEDROT : Linked Rotate: 回転連動 :]\n";
82 private static final String MORPHTYPE_COMMENT =
84 + "[1 : EYEBROW : まゆ ]\n"
86 + "[3 : LIP : リップ ]\n"
87 + "[4 : EXTRA : その他 ]\n";
89 private static final String RIGIDBEHAVIOR_COMMENT =
90 "Rigid behavior types:\n"
91 + "[0 : FOLLOWBONE : ボーン追従 ]\n"
92 + "[1 : ONLYDYNAMICS : 物理演算 ]\n"
93 + "[2 : BONEDDYNAMICS : ボーン位置合わせ ]\n";
95 private String generator = null;
99 * 文字エンコーディングはUTF-8が用いられる。
100 * @param stream 出力ストリーム
102 public PmdXmlExporter(OutputStream stream){
108 * Generatorメタ情報を設定する。
109 * @param generatorArg Generatorメタ情報。表示したくないときはnull
111 public void setGenerator(String generatorArg){
112 this.generator = generatorArg;
117 * 任意の文字列がBasicLatin文字のみから構成されるか判定する。
119 * @return null、長さ0もしくはBasicLatin文字のみから構成されるならtrue
121 public static boolean hasOnlyBasicLatin(CharSequence seq){
122 if(seq == null) return true;
123 int length = seq.length();
124 for(int pos = 0; pos < length; pos++){
125 char ch = seq.charAt(pos);
126 if(ch > 0x007f) return false;
133 * @return {@inheritDoc}
134 * @throws IOException {@inheritDoc}
137 public PmdXmlExporter ind() throws IOException{
143 * 文字参照によるエスケープを補佐するためのコメントを出力する。
146 * @throws IOException 出力エラー
148 protected PmdXmlExporter putUnescapedComment(CharSequence seq)
150 if( ! isBasicLatinOnlyOut() ) return this;
151 if(hasOnlyBasicLatin(seq)) return this;
152 sp().putLineComment(seq);
161 * @throws IOException 出力エラー
163 protected PmdXmlExporter putI18nName(I18nText text) throws IOException{
164 for(String lang639 : text.lang639CodeList()){
165 if(lang639.equals(I18nText.CODE639_PRIMARY)) continue;
166 String name = text.getI18nText(lang639);
167 ind().put("<i18nName ");
168 putAttr("lang", lang639).sp();
169 putAttr("name", name);
171 putUnescapedComment(name);
178 * 番号付けされたID(IDREF)属性を出力する。
179 * @param attrName 属性名
180 * @param prefix IDプレフィクス
183 * @throws IOException 出力エラー
185 protected PmdXmlExporter putNumberedIdAttr(CharSequence attrName,
189 put(attrName).put("=\"");
190 put(prefix).put(num);
196 * 番号付けされたID(IDREF)属性を出力する。
197 * @param attrName 属性名
198 * @param prefix IDプレフィクス
199 * @param numbered 番号付けされたオブジェクト
201 * @throws IOException 出力エラー
203 protected PmdXmlExporter putNumberedIdAttr(CharSequence attrName,
205 SerialNumbered numbered )
207 putNumberedIdAttr(attrName, prefix, numbered.getSerialNumber());
213 * @param position 位置情報
215 * @throws IOException 出力エラー
217 protected PmdXmlExporter putPosition(MkPos3D position)
220 putFloatAttr("x", (float) position.getXpos()).sp();
221 putFloatAttr("y", (float) position.getYpos()).sp();
222 putFloatAttr("z", (float) position.getZpos()).sp();
229 * @param rotation 姿勢情報
231 * @throws IOException 出力エラー
233 protected PmdXmlExporter putRadRotation(Rad3d rotation)
235 put("<radRotation ");
236 putFloatAttr("xRad", rotation.getXRad()).sp();
237 putFloatAttr("yRad", rotation.getYRad()).sp();
238 putFloatAttr("zRad", rotation.getZRad()).sp();
244 * 多言語識別名属性のローカルな名前をコメント出力する。
247 * @throws IOException 出力エラー
249 protected PmdXmlExporter putLocalNameComment(I18nText name)
251 String localName = name.getText();
252 ind().putLineComment(localName);
257 * 多言語識別名属性のプライマリな名前を出力する。
258 * @param attrName 属性名
261 * @throws IOException 出力エラー
263 protected PmdXmlExporter putPrimaryNameAttr(CharSequence attrName,
266 String primaryName = name.getPrimaryText();
267 putAttr(attrName, primaryName);
272 * PMDモデルデータをXML形式で出力する。
273 * @param model PMDモデルデータ
274 * @throws IOException 出力エラー
276 public void putPmdModel(PmdModel model) throws IOException{
277 ind().put("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>").ln(2);
279 ind().putBlockComment(TOP_COMMENT).ln(2);
282 ind().put("<!DOCTYPE pmdModel").ln();
283 ind().put(" SYSTEM \"")
284 .put(PmdXmlResources.DTD_PMDXML)
289 I18nText modelName = model.getModelName();
290 ind().putLocalNameComment(modelName).ln();
291 ind().put("<pmdModel").ln();
293 ind().putAttr("xmlns", PmdXmlResources.NS_PMDXML).ln();
294 ind().putAttr("xmlns:xsi", XmlResourceResolver.NS_XSD).ln();
295 ind().putAttr("xsi:schemaLocation", SCHEMA_LOCATION).ln();
296 ind().putAttr("schemaVersion", PmdXmlResources.VER_PMDXML).ln(2);
297 ind().putPrimaryNameAttr("name", modelName).ln();
301 putModelInfo(model).flush();
302 putMetaInfo(model).flush();
303 putMaterialList(model).flush();
304 putToonMap(model).flush();
305 putBoneList(model).flush();
306 putBoneGroupList(model).flush();
307 putIKChainList(model).flush();
308 putMorphList(model).flush();
309 putRigidList(model).flush();
310 putRigidGroupList(model).flush();
311 putJointList(model).flush();
312 putSurfaceGroupList(model).flush();
313 putVertexList(model).flush();
315 ind().put("</pmdModel>").ln(2);
316 ind().put("<!-- EOF -->").ln();
325 * @throws IOException 出力エラー
327 private PmdXmlExporter putModelInfo(PmdModel model)
329 I18nText modelName = model.getModelName();
330 putI18nName(modelName);
333 I18nText description = model.getDescription();
334 for(String lang639 : description.lang639CodeList()){
335 String descText = description.getI18nText(lang639);
336 putDescription(lang639, descText);
345 * @param lang639 言語コード
346 * @param content 詳細内容
348 * @throws IOException 出力エラー
350 private PmdXmlExporter putDescription(CharSequence lang639,
351 CharSequence content)
353 String text = content.toString();
354 text = text.replace(CRLF, LF);
355 text = text.replace(CR, LF);
357 ind().put("<description");
358 if( ! I18nText.CODE639_PRIMARY.equals(lang639) ){
360 putAttr("lang", lang639);
364 putBRedContent(text);
366 ind().put("</description>").ln();
368 if( ! hasOnlyBasicLatin(text) && isBasicLatinOnlyOut() ){
369 putBlockComment(text);
376 * break要素を含む要素内容を出力する。
377 * 必要に応じてXML定義済み実体文字が割り振られた文字、
378 * コントロールコード、および非BasicLatin文字がエスケープされる。
382 * @throws IOException 出力エラー
384 protected BasicXmlExporter putBRedContent(CharSequence content)
386 int length = content.length();
390 for(int idx = 0; idx < length; idx++){
391 char ch = content.charAt(idx);
393 CharSequence seq = content.subSequence(startPos, idx);
394 putContent(seq).put("<br/>").ln();
399 if(startPos < length){
400 CharSequence seq = content.subSequence(startPos, length);
401 putContent(seq).ln();
409 * @param model モデルデータ
411 * @throws IOException 出力エラー
413 private PmdXmlExporter putMetaInfo(PmdModel model) throws IOException{
414 ind().put("<license>").ln();
415 ind().put("</license>").ln(2);
417 ind().put("<credits>").ln();
418 ind().put("</credits>").ln(2);
420 if(this.generator != null){
422 putAttr("name", "generator").sp()
423 .putAttr("content", this.generator);
428 putAttr("name", "siteURL").sp().putAttr("content", "");
431 putAttr("name", "imageURL").sp().putAttr("content", "");
439 * @param model モデルデータ
441 * @throws IOException 出力エラー
443 private PmdXmlExporter putMaterialList(PmdModel model)
445 ind().put("<materialList>").ln(2);
449 for(Material material : model.getMaterialList()){
450 putMaterial(material, ct++);
454 ind().put("</materialList>").ln(2);
461 * @param material マテリアル素材
462 * @param no マテリアル通し番号
464 * @throws IOException 出力エラー
466 private PmdXmlExporter putMaterial(Material material, int no)
469 if(material.getEdgeAppearance()) bool = "true";
471 I18nText name = material.getMaterialName();
472 String primary = name.getPrimaryText();
473 String local = name.getText();
475 if(local != null && local.length() > 0){
476 ind().putLineComment(local).ln();
478 ind().put("<material ");
479 if(primary != null && primary.length() > 0){
480 putAttr("name", primary).sp();
483 putAttr("showEdge", bool);
485 putNumberedIdAttr("surfaceGroupIdRef", PFX_SURFACEGROUP, no);
491 float[] rgba = new float[4];
493 Color diffuse = material.getDiffuseColor();
494 diffuse.getRGBComponents(rgba);
495 ind().put("<diffuse ");
496 putFloatAttr("r", rgba[0]).sp();
497 putFloatAttr("g", rgba[1]).sp();
498 putFloatAttr("b", rgba[2]).sp();
499 putFloatAttr("alpha", rgba[3]).sp();
502 Color specular = material.getSpecularColor();
503 specular.getRGBComponents(rgba);
504 float shininess = material.getShininess();
505 ind().put("<specular ");
506 putFloatAttr("r", rgba[0]).sp();
507 putFloatAttr("g", rgba[1]).sp();
508 putFloatAttr("b", rgba[2]).sp();
509 putFloatAttr("shininess", shininess).sp();
512 Color ambient = material.getAmbientColor();
513 ambient.getRGBComponents(rgba);
514 ind().put("<ambient ");
515 putFloatAttr("r", rgba[0]).sp();
516 putFloatAttr("g", rgba[1]).sp();
517 putFloatAttr("b", rgba[2]).sp();
520 ShadeInfo shade = material.getShadeInfo();
521 String textureFileName = shade.getTextureFileName();
522 String spheremapFileName = shade.getSpheremapFileName();
524 if(shade.isValidToonIndex()){
526 int toonIdx = shade.getToonIndex();
527 putNumberedIdAttr("toonFileIdRef", PFX_TOONFILE, toonIdx);
529 String toonFileName = shade.getToonFileName();
530 if(toonFileName != null && toonFileName.length() > 0){
531 sp().putLineComment(toonFileName);
536 if(textureFileName != null && textureFileName.length() > 0){
537 ind().put("<textureFile ");
538 putAttr("winFileName", textureFileName);
542 if(spheremapFileName != null && spheremapFileName.length() > 0){
543 ind().put("<spheremapFile ");
544 putAttr("winFileName", spheremapFileName);
549 ind().put("</material>").ln(2);
555 * トゥーンファイルマッピング情報を出力する。
556 * @param model モデルデータ
558 * @throws IOException 出力エラー
560 private PmdXmlExporter putToonMap(PmdModel model)
562 ind().put("<toonMap>").ln();
565 ToonMap map = model.getToonMap();
566 for(int index = 0; index <= 9; index++){
567 ind().putToon(map, index).ln();
571 ind().put("</toonMap>").ln(2);
576 * 個別のトゥーンファイル情報を出力する。
578 * @param index インデックス値
580 * @throws IOException 出力エラー
582 private PmdXmlExporter putToon(ToonMap map, int index)
585 putNumberedIdAttr("toonFileId", PFX_TOONFILE, index).sp();
586 putIntAttr("index", index).sp();
587 String toonFile = map.getIndexedToon(index);
588 putAttr("winFileName", toonFile);
590 putUnescapedComment(toonFile);
595 * サーフェイスグループリストを出力する。
596 * @param model モデルデータ
598 * @throws IOException 出力エラー
600 private PmdXmlExporter putSurfaceGroupList(PmdModel model)
602 ind().put("<surfaceGroupList>").ln(2);
606 for(Material material : model.getMaterialList()){
607 List<Surface> surfaceList = material.getSurfaceList();
608 putSurfaceList(surfaceList, ct++);
612 ind().put("</surfaceGroupList>").ln(2);
618 * 個別のサーフェイスグループを出力する。
619 * @param surfaceList サーフェイスのリスト
620 * @param index グループインデックス
622 * @throws IOException 出力エラー
624 private PmdXmlExporter putSurfaceList(List<Surface> surfaceList,
627 ind().put("<surfaceGroup ");
628 putNumberedIdAttr("surfaceGroupId", PFX_SURFACEGROUP, index);
632 for(Surface surface : surfaceList){
637 ind().put("</surfaceGroup>").ln(2);
644 * @param surface サーフェイス
646 * @throws IOException 出力エラー
648 private PmdXmlExporter putSurface(Surface surface)
650 ind().put("<surface ");
652 Vertex vertex1 = surface.getVertex1();
653 Vertex vertex2 = surface.getVertex2();
654 Vertex vertex3 = surface.getVertex3();
656 putNumberedIdAttr("vtxIdRef1", PFX_VERTEX, vertex1).sp();
657 putNumberedIdAttr("vtxIdRef2", PFX_VERTEX, vertex2).sp();
658 putNumberedIdAttr("vtxIdRef3", PFX_VERTEX, vertex3).sp();
666 * @param model モデルデータ
668 * @throws IOException 出力エラー
670 private PmdXmlExporter putVertexList(PmdModel model)
672 ind().put("<vertexList>").ln(2);
675 for(Vertex vertex : model.getVertexList()){
680 ind().put("</vertexList>").ln(2);
689 * @throws IOException 出力エラー
691 private PmdXmlExporter putVertex(Vertex vertex)
694 if(vertex.getEdgeAppearance()) bool = "true";
697 ind().put("<vertex ");
698 putNumberedIdAttr("vtxId", PFX_VERTEX, vertex).sp();
699 putAttr("showEdge", bool);
703 MkPos3D position = vertex.getPosition();
704 ind().putPosition(position).ln();
706 MkVec3D normal = vertex.getNormal();
707 ind().put("<normal ");
708 putFloatAttr("x", (float) normal.getXVal()).sp();
709 putFloatAttr("y", (float) normal.getYVal()).sp();
710 putFloatAttr("z", (float) normal.getZVal()).sp();
713 MkPos2D uvPos = vertex.getUVPosition();
714 ind().put("<uvMap ");
715 putFloatAttr("u", (float) uvPos.getXpos()).sp();
716 putFloatAttr("v", (float) uvPos.getYpos()).sp();
719 BoneInfo boneA = vertex.getBoneA();
720 BoneInfo boneB = vertex.getBoneB();
721 int weight = vertex.getWeightA();
722 ind().put("<skinning ");
723 putNumberedIdAttr("boneIdRef1", PFX_BONE, boneA).sp();
724 putNumberedIdAttr("boneIdRef2", PFX_BONE, boneB).sp();
725 putIntAttr("weightBalance", weight).sp();
729 ind().put("</vertex>").ln(2);
736 * @param model モデルデータ
738 * @throws IOException 出力エラー
740 private PmdXmlExporter putBoneList(PmdModel model)
742 ind().put("<boneList>").ln(2);
745 putBlockComment(BONETYPE_COMMENT).ln();
747 for(BoneInfo bone : model.getBoneList()){
752 ind().put("</boneList>").ln(2);
761 * @throws IOException 出力エラー
763 private PmdXmlExporter putBone(BoneInfo bone)
765 I18nText i18nName = bone.getBoneName();
766 BoneType type = bone.getBoneType();
768 putLocalNameComment(i18nName).putLineComment(type.getGuiName()).ln();
770 putPrimaryNameAttr("name", i18nName).sp();
771 putNumberedIdAttr("boneId", PFX_BONE, bone).sp();
772 putAttr("type", type.name());
776 putI18nName(i18nName);
778 MkPos3D position = bone.getPosition();
779 ind().putPosition(position).ln();
781 BoneInfo ikBone = bone.getIKBone();
782 if(bone.getBoneType() == BoneType.LINKEDROT){
783 ind().put("<rotationRatio ");
784 putIntAttr("ratio", bone.getRotationRatio());
786 }else if(ikBone != null){
787 ind().put("<ikBone ");
788 putNumberedIdAttr("boneIdRef", PFX_BONE, ikBone);
790 String ikBoneName = "Ref:" + ikBone.getBoneName().getText();
791 putLineComment(ikBoneName);
795 StringBuilder chainComment = new StringBuilder();
796 ind().put("<boneChain");
797 BoneInfo prev = bone.getPrevBone();
798 BoneInfo next = bone.getNextBone();
801 putNumberedIdAttr("prevBoneIdRef", PFX_BONE, prev);
802 chainComment.append('[')
803 .append(prev.getBoneName().getPrimaryText())
809 putNumberedIdAttr("nextBoneIdRef", PFX_BONE, next);
810 if(chainComment.length() <= 0) chainComment.append("#");
811 chainComment.append(" =>")
813 .append(next.getBoneName().getPrimaryText())
817 ind().putLineComment(chainComment).ln();
820 ind().put("</bone>").ln(2);
827 * @param model モデルデータ
829 * @throws IOException 出力エラー
831 private PmdXmlExporter putBoneGroupList(PmdModel model)
833 ind().put("<boneGroupList>").ln(2);
836 for(BoneGroup group : model.getBoneGroupList()){
837 if(group.isDefaultBoneGroup()) continue;
842 ind().put("</boneGroupList>").ln(2);
849 * @param group ボーングループ情報
851 * @throws IOException 出力エラー
853 private PmdXmlExporter putBoneGroup(BoneGroup group)
855 I18nText i18nName = group.getGroupName();
857 putLocalNameComment(i18nName).ln();
858 ind().put("<boneGroup ");
859 putPrimaryNameAttr("name", i18nName);
863 putI18nName(i18nName);
865 for(BoneInfo bone : group){
866 ind().put("<boneGroupMember ");
867 putNumberedIdAttr("boneIdRef", PFX_BONE, bone);
869 String boneName = "Ref:" + bone.getBoneName().getText();
870 putLineComment(boneName).ln();
874 ind().put("</boneGroup>").ln(2);
881 * @param model モデルデータ
883 * @throws IOException 出力エラー
885 private PmdXmlExporter putIKChainList(PmdModel model)
887 ind().put("<ikChainList>").ln(2);
890 for(IKChain chain : model.getIKChainList()){
895 ind().put("</ikChainList>").ln(2);
902 * @param chain チェーン情報
904 * @throws IOException 出力エラー
906 private PmdXmlExporter putIKChain(IKChain chain)
908 int depth = chain.getIKDepth();
909 float weight = chain.getIKWeight();
910 BoneInfo ikBone = chain.getIkBone();
912 ind().putLineComment("Ref:" + ikBone.getBoneName().getText()).ln();
913 ind().put("<ikChain ");
914 putNumberedIdAttr("ikBoneIdRef", PFX_BONE, ikBone).sp();
915 putIntAttr("recursiveDepth", depth).sp();
916 putFloatAttr("weight", weight);
920 for(BoneInfo bone : chain){
921 ind().put("<chainOrder ");
922 putNumberedIdAttr("boneIdRef", PFX_BONE, bone);
924 putLineComment("Ref:" + bone.getBoneName().getText());
929 ind().put("</ikChain>").ln(2);
936 * @param model モデルデータ
938 * @throws IOException 出力エラー
940 private PmdXmlExporter putMorphList(PmdModel model)
942 ind().put("<morphList>").ln(2);
945 putBlockComment(MORPHTYPE_COMMENT).ln();
947 Map<MorphType, List<MorphPart>> morphMap = model.getMorphMap();
948 for(MorphType type : MorphType.values()){
949 if(type == MorphType.BASE) continue;
950 List<MorphPart> partList = morphMap.get(type);
951 if(partList == null) continue;
952 for(MorphPart part : partList){
958 ind().put("</morphList>").ln(2);
967 * @throws IOException 出力エラー
969 private PmdXmlExporter putMorphPart(MorphPart part)
971 I18nText i18nName = part.getMorphName();
972 String primary = i18nName.getPrimaryText();
974 ind().put("<morph ");
975 putAttr("name", primary).sp();
976 putAttr("type", part.getMorphType().name());
978 putUnescapedComment(primary);
982 putI18nName(i18nName);
984 for(MorphVertex mvertex : part){
985 MkPos3D offset = mvertex.getOffset();
986 Vertex base = mvertex.getBaseVertex();
988 ind().put("<morphVertex ");
989 putNumberedIdAttr("vtxIdRef", PFX_VERTEX, base).sp();
990 putFloatAttr("xOff", (float) offset.getXpos()).sp();
991 putFloatAttr("yOff", (float) offset.getYpos()).sp();
992 putFloatAttr("zOff", (float) offset.getZpos()).sp();
998 ind().put("</morph>").ln(2);
1005 * @param model モデルデータ
1007 * @throws IOException 出力エラー
1009 private PmdXmlExporter putRigidList(PmdModel model)
1011 ind().put("<rigidList>").ln(2);
1014 putBlockComment(RIGIDBEHAVIOR_COMMENT).ln();
1016 for(RigidInfo rigid : model.getRigidList()){
1021 ind().put("</rigidList>").ln(2);
1030 * @throws IOException 出力エラー
1032 private PmdXmlExporter putRigid(RigidInfo rigid)
1034 BoneInfo linkedBone = rigid.getLinkedBone();
1035 I18nText i18nName = rigid.getRigidName();
1036 String primary = i18nName.getPrimaryText();
1038 putLocalNameComment(i18nName).ln();
1039 ind().put("<rigid ");
1040 putAttr("name", primary).sp();
1041 putNumberedIdAttr("rigidId", PFX_RIGID, rigid).sp();
1042 putAttr("behavior", rigid.getBehaviorType().name());
1046 putI18nName(i18nName);
1048 if(linkedBone != null){
1049 ind().put("<linkedBone ");
1050 putNumberedIdAttr("boneIdRef", PFX_BONE, linkedBone);
1052 putLineComment("Ref:" + linkedBone.getBoneName().getText());
1056 RigidShape shape = rigid.getRigidShape();
1057 putRigidShape(shape);
1059 MkPos3D position = rigid.getPosition();
1060 ind().putPosition(position).ln();
1062 Rad3d rotation = rigid.getRotation();
1063 ind().putRadRotation(rotation).ln();
1065 DynamicsInfo dynamics = rigid.getDynamicsInfo();
1066 putDynamics(dynamics).ln();
1068 for(RigidGroup group : rigid.getThroughGroupColl()){
1069 ind().put("<throughRigidGroup ");
1070 putNumberedIdAttr("rigidGroupIdRef",
1072 group.getSerialNumber() + 1).sp();
1077 ind().put("</rigid>").ln(2);
1086 * @throws IOException 出力エラー
1088 private PmdXmlExporter putRigidShape(RigidShape shape)
1090 RigidShapeType type = shape.getShapeType();
1094 ind().put("<rigidShapeBox ");
1095 putFloatAttr("width", shape.getWidth()).sp();
1096 putFloatAttr("height", shape.getHeight()).sp();
1097 putFloatAttr("depth", shape.getDepth()).sp();
1100 ind().put("<rigidShapeSphere ");
1101 putFloatAttr("radius", shape.getRadius()).sp();
1104 ind().put("<rigidShapeCapsule ");
1105 putFloatAttr("height", shape.getHeight()).sp();
1106 putFloatAttr("radius", shape.getRadius()).sp();
1110 throw new AssertionError();
1120 * @param dynamics 力学設定
1122 * @throws IOException 出力エラー
1124 private PmdXmlExporter putDynamics(DynamicsInfo dynamics)
1126 ind().put("<dynamics").ln();
1128 ind().putFloatAttr("mass", dynamics.getMass()).ln();
1129 ind().putFloatAttr("dampingPosition",
1130 dynamics.getDampingPosition()).ln();
1131 ind().putFloatAttr("dampingRotation",
1132 dynamics.getDampingRotation()).ln();
1133 ind().putFloatAttr("restitution", dynamics.getRestitution()).ln();
1134 ind().putFloatAttr("friction", dynamics.getFriction()).ln();
1136 ind().put("/>").ln();
1143 * @param model モデルデータ
1145 * @throws IOException 出力エラー
1147 private PmdXmlExporter putRigidGroupList(PmdModel model)
1149 ind().put("<rigidGroupList>").ln(2);
1152 for(RigidGroup group : model.getRigidGroupList()){
1153 ind().put("<rigidGroup ");
1154 putNumberedIdAttr("rigidGroupId",
1156 group.getSerialNumber() + 1);
1157 List<RigidInfo> rigidList = group.getRigidList();
1158 if(rigidList.size() <= 0){
1165 for(RigidInfo rigid : rigidList){
1166 ind().put("<rigidGroupMember ");
1167 putNumberedIdAttr("rigidIdRef", PFX_RIGID, rigid).sp();
1170 putLineComment("Ref:" + rigid.getRigidName().getText());
1175 ind().put("</rigidGroup>").ln(2);
1179 ind().put("</rigidGroupList>").ln(2);
1186 * @param model モデルデータ
1188 * @throws IOException 出力エラー
1190 private PmdXmlExporter putJointList(PmdModel model)
1192 ind().put("<jointList>").ln(2);
1195 for(JointInfo joint : model.getJointList()){
1200 ind().put("</jointList>").ln(2);
1207 * @param joint ジョイント情報
1209 * @throws IOException 出力エラー
1211 private PmdXmlExporter putJoint(JointInfo joint)
1213 I18nText i18nName = joint.getJointName();
1215 putLocalNameComment(i18nName).ln();
1216 ind().put("<joint ");
1217 putPrimaryNameAttr("name", i18nName);
1221 putI18nName(i18nName);
1223 RigidInfo rigidA = joint.getRigidA();
1224 RigidInfo rigidB = joint.getRigidB();
1225 ind().put("<jointedRigidPair ");
1226 putNumberedIdAttr("rigidIdRef1", PFX_RIGID, rigidA).sp();
1227 putNumberedIdAttr("rigidIdRef2", PFX_RIGID, rigidB).sp();
1230 putLineComment("[" + rigidA.getRigidName().getText() + "]"
1231 + " <=> [" + rigidB.getRigidName().getText() + "]");
1234 MkPos3D position = joint.getPosition();
1235 ind().putPosition(position).ln();
1237 TripletRange posRange = joint.getPositionRange();
1238 ind().put("<limitPosition").ln();
1241 putFloatAttr("xFrom", posRange.getXFrom()).sp();
1242 putFloatAttr("xTo", posRange.getXTo()).ln();
1244 putFloatAttr("yFrom", posRange.getYFrom()).sp();
1245 putFloatAttr("yTo", posRange.getYTo()).ln();
1247 putFloatAttr("zFrom", posRange.getZFrom()).sp();
1248 putFloatAttr("zTo", posRange.getZTo()).ln();
1250 ind().put("/>").ln(2);
1252 Rad3d rotation = joint.getRotation();
1253 ind().putRadRotation(rotation).ln();
1254 TripletRange rotRange = joint.getRotationRange();
1255 ind().put("<limitRotation").ln();
1258 putFloatAttr("xFrom", rotRange.getXFrom()).sp();
1259 putFloatAttr("xTo", rotRange.getXTo()).ln();
1261 putFloatAttr("yFrom", rotRange.getYFrom()).sp();
1262 putFloatAttr("yTo", rotRange.getYTo()).ln();
1264 putFloatAttr("zFrom", rotRange.getZFrom()).sp();
1265 putFloatAttr("zTo", rotRange.getZTo()).ln();
1267 ind().put("/>").ln(2);
1269 MkPos3D elaPosition = joint.getElasticPosition();
1270 ind().put("<elasticPosition ");
1271 putFloatAttr("x", (float) elaPosition.getXpos()).sp();
1272 putFloatAttr("y", (float) elaPosition.getYpos()).sp();
1273 putFloatAttr("z", (float) elaPosition.getZpos()).sp();
1276 Deg3d elaRotation = joint.getElasticRotation();
1277 ind().put("<elasticRotation ");
1278 putFloatAttr("xDeg", elaRotation.getXDeg()).sp();
1279 putFloatAttr("yDeg", elaRotation.getYDeg()).sp();
1280 putFloatAttr("zDeg", elaRotation.getZDeg()).sp();
1284 ind().put("</joint>").ln(2);