4 * License : The MIT License
5 * Copyright(c) 2010 MikuToga Partners
8 package jp.sourceforge.mikutoga.pmd.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.corelib.SerialNumbered;
17 import jp.sourceforge.mikutoga.pmd.BoneGroup;
18 import jp.sourceforge.mikutoga.pmd.BoneInfo;
19 import jp.sourceforge.mikutoga.pmd.BoneType;
20 import jp.sourceforge.mikutoga.pmd.Deg3d;
21 import jp.sourceforge.mikutoga.pmd.DynamicsInfo;
22 import jp.sourceforge.mikutoga.pmd.IKChain;
23 import jp.sourceforge.mikutoga.pmd.JointInfo;
24 import jp.sourceforge.mikutoga.pmd.Material;
25 import jp.sourceforge.mikutoga.pmd.MorphPart;
26 import jp.sourceforge.mikutoga.pmd.MorphType;
27 import jp.sourceforge.mikutoga.pmd.MorphVertex;
28 import jp.sourceforge.mikutoga.pmd.PmdModel;
29 import jp.sourceforge.mikutoga.pmd.Pos2d;
30 import jp.sourceforge.mikutoga.pmd.Pos3d;
31 import jp.sourceforge.mikutoga.pmd.Rad3d;
32 import jp.sourceforge.mikutoga.pmd.RigidGroup;
33 import jp.sourceforge.mikutoga.pmd.RigidInfo;
34 import jp.sourceforge.mikutoga.pmd.RigidShape;
35 import jp.sourceforge.mikutoga.pmd.RigidShapeType;
36 import jp.sourceforge.mikutoga.pmd.ShadeInfo;
37 import jp.sourceforge.mikutoga.pmd.Surface;
38 import jp.sourceforge.mikutoga.pmd.ToonMap;
39 import jp.sourceforge.mikutoga.pmd.TripletRange;
40 import jp.sourceforge.mikutoga.pmd.Vec3d;
41 import jp.sourceforge.mikutoga.pmd.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 = "";
99 * 文字エンコーディングはUTF-8が用いられる。
100 * @param stream 出力ストリーム
102 public PmdXmlExporter(OutputStream stream){
108 * Generatorメタ情報を設定する。
109 * @param generatorArg Generatorメタ情報
110 * @throws NullPointerException 引数がnull
112 public void setGenerator(String generatorArg)
113 throws NullPointerException{
114 if(generatorArg == null) throw new NullPointerException();
115 this.generator = generatorArg;
120 * 任意の文字列がBasicLatin文字のみから構成されるか判定する。
122 * @return null、長さ0もしくはBasicLatin文字のみから構成されるならtrue
124 public static boolean hasOnlyBasicLatin(CharSequence seq){
125 if(seq == null) return true;
126 int length = seq.length();
127 for(int pos = 0; pos < length; pos++){
128 char ch = seq.charAt(pos);
129 if(ch > 0x007f) return false;
136 * @return {@inheritDoc}
137 * @throws IOException {@inheritDoc}
140 public PmdXmlExporter ind() throws IOException{
146 * 文字参照によるエスケープを補佐するためのコメントを出力する。
149 * @throws IOException 出力エラー
151 protected PmdXmlExporter putUnescapedComment(CharSequence seq)
153 if( ! isBasicLatinOnlyOut() ) return this;
154 if(hasOnlyBasicLatin(seq)) return this;
155 put(' ').putLineComment(seq);
164 * @throws IOException 出力エラー
166 protected PmdXmlExporter putI18nName(I18nText text) throws IOException{
167 for(String lang639 : text.lang639CodeList()){
168 if(lang639.equals(I18nText.CODE639_PRIMARY)) continue;
169 String name = text.getText(lang639);
170 ind().put("<i18nName ");
171 putAttr("lang", lang639).put(' ');
172 putAttr("name", name);
174 putUnescapedComment(name);
181 * 番号付けされたID(IDREF)属性を出力する。
182 * @param attrName 属性名
183 * @param prefix IDプレフィクス
186 * @throws IOException 出力エラー
188 protected PmdXmlExporter putNumberedIdAttr(CharSequence attrName,
192 put(attrName).put("=\"");
193 put(prefix).put(num);
199 * 番号付けされたID(IDREF)属性を出力する。
200 * @param attrName 属性名
201 * @param prefix IDプレフィクス
202 * @param numbered 番号付けされたオブジェクト
204 * @throws IOException 出力エラー
206 protected PmdXmlExporter putNumberedIdAttr(CharSequence attrName,
208 SerialNumbered numbered )
210 putNumberedIdAttr(attrName, prefix, numbered.getSerialNumber());
216 * @param position 位置情報
218 * @throws IOException 出力エラー
220 protected PmdXmlExporter putPosition(Pos3d position) throws IOException{
222 putFloatAttr("x", position.getXPos()).put(' ');
223 putFloatAttr("y", position.getYPos()).put(' ');
224 putFloatAttr("z", position.getZPos()).put(' ');
231 * @param rotation 姿勢情報
233 * @throws IOException 出力エラー
235 protected PmdXmlExporter putRadRotation(Rad3d rotation)
237 put("<radRotation ");
238 putFloatAttr("xRad", rotation.getXRad()).put(' ');
239 putFloatAttr("yRad", rotation.getYRad()).put(' ');
240 putFloatAttr("zRad", rotation.getZRad()).put(' ');
246 * 多言語識別名属性のローカルな名前をコメント出力する。
249 * @throws IOException 出力エラー
251 protected PmdXmlExporter putLocalNameComment(I18nText name)
253 String localName = name.getText();
254 ind().putLineComment(localName);
259 * 多言語識別名属性のプライマリな名前を出力する。
260 * @param attrName 属性名
263 * @throws IOException 出力エラー
265 protected PmdXmlExporter putPrimaryNameAttr(CharSequence attrName,
268 String primaryName = name.getPrimaryText();
269 putAttr(attrName, primaryName);
274 * PMDモデルデータをXML形式で出力する。
275 * @param model PMDモデルデータ
276 * @throws IOException 出力エラー
278 public void putPmdModel(PmdModel model) throws IOException{
279 ind().put("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>").ln(2);
281 ind().putBlockComment(TOP_COMMENT).ln(2);
284 ind().put("<!DOCTYPE pmdModel").ln();
285 ind().put(" SYSTEM \"")
286 .put(PmdXmlResources.DTD_PMDXML)
291 I18nText modelName = model.getModelName();
292 ind().putLocalNameComment(modelName).ln();
293 ind().put("<pmdModel").ln();
295 ind().putAttr("xmlns", PmdXmlResources.NS_PMDXML).ln();
296 ind().putAttr("xmlns:xsi", XmlResourceResolver.NS_XSD).ln();
297 ind().putAttr("xsi:schemaLocation", SCHEMA_LOCATION).ln();
298 ind().putAttr("schemaVersion", PmdXmlResources.VER_PMDXML).ln(2);
299 ind().putPrimaryNameAttr("name", modelName).ln();
303 putModelInfo(model).flush();
304 putMetaInfo(model).flush();
305 putMaterialList(model).flush();
306 putToonMap(model).flush();
307 putBoneList(model).flush();
308 putBoneGroupList(model).flush();
309 putIKChainList(model).flush();
310 putMorphList(model).flush();
311 putRigidList(model).flush();
312 putRigidGroupList(model).flush();
313 putJointList(model).flush();
314 putSurfaceGroupList(model).flush();
315 putVertexList(model).flush();
317 ind().put("</pmdModel>").ln(2);
318 ind().put("<!-- EOF -->").ln();
327 * @throws IOException 出力エラー
329 private PmdXmlExporter putModelInfo(PmdModel model)
331 I18nText modelName = model.getModelName();
332 putI18nName(modelName);
335 I18nText description = model.getDescription();
336 for(String lang639 : description.lang639CodeList()){
337 String descText = description.getText(lang639);
338 putDescription(lang639, descText);
347 * @param lang639 言語コード
348 * @param content 詳細内容
350 * @throws IOException 出力エラー
352 private PmdXmlExporter putDescription(CharSequence lang639,
353 CharSequence content)
355 String text = content.toString();
356 text = text.replace(CRLF, LF);
357 text = text.replace(CR, LF);
359 ind().put("<description");
360 if( ! I18nText.CODE639_PRIMARY.equals(lang639) ){
362 putAttr("lang", lang639);
366 putBRedContent(text);
369 ind().put("</description>").ln();
371 if( ! hasOnlyBasicLatin(text) && isBasicLatinOnlyOut() ){
372 putBlockComment(text);
379 * break要素を含む要素内容を出力する。
380 * 必要に応じてXML定義済み実体文字が割り振られた文字、
381 * コントロールコード、および非BasicLatin文字がエスケープされる。
385 * @throws IOException 出力エラー
387 protected BasicXmlExporter putBRedContent(CharSequence content)
389 int length = content.length();
391 for(int pos = 0; pos < length; pos++){
392 char ch = content.charAt(pos);
395 }else if(Character.isISOControl(ch)){
397 }else if( ! isBasicLatin(ch) && isBasicLatinOnlyOut()){
401 case '&': put("&"); break;
402 case '<': put("<"); break;
403 case '>': put(">"); break;
404 case '"': put("""); break;
405 case '\'': put("'"); break;
406 default: put(ch); break;
416 * @param model モデルデータ
418 * @throws IOException 出力エラー
420 private PmdXmlExporter putMetaInfo(PmdModel model) throws IOException{
421 ind().put("<license>").ln();
422 ind().put("</license>").ln(2);
424 ind().put("<credits>").ln();
425 ind().put("</credits>").ln(2);
428 putAttr("name", "generator").put(' ')
429 .putAttr("content", this.generator);
432 putAttr("name", "siteURL").put(' ').putAttr("content", "");
435 putAttr("name", "imageURL").put(' ').putAttr("content", "");
443 * @param model モデルデータ
445 * @throws IOException 出力エラー
447 private PmdXmlExporter putMaterialList(PmdModel model)
449 ind().put("<materialList>").ln(2);
453 for(Material material : model.getMaterialList()){
454 putMaterial(material, ct++);
458 ind().put("</materialList>").ln(2);
465 * @param material マテリアル素材
466 * @param no マテリアル通し番号
468 * @throws IOException 出力エラー
470 private PmdXmlExporter putMaterial(Material material, int no)
473 if(material.getEdgeAppearance()) bool = "true";
475 I18nText name = material.getMaterialName();
476 String primary = name.getPrimaryText();
477 String local = name.getText();
479 if(local != null && local.length() > 0){
480 ind().putLineComment(local).ln();
482 ind().put("<material ");
483 if(primary != null && primary.length() > 0){
484 putAttr("name", primary).put(' ');
487 putAttr("showEdge", bool);
489 putNumberedIdAttr("surfaceGroupIdRef", PFX_SURFACEGROUP, no);
495 float[] rgba = new float[4];
497 Color diffuse = material.getDiffuseColor();
498 diffuse.getRGBComponents(rgba);
499 ind().put("<diffuse ");
500 putFloatAttr("r", rgba[0]).put(' ');
501 putFloatAttr("g", rgba[1]).put(' ');
502 putFloatAttr("b", rgba[2]).put(' ');
503 putFloatAttr("alpha", rgba[3]).put(' ');
506 Color specular = material.getSpecularColor();
507 specular.getRGBComponents(rgba);
508 float shininess = material.getShininess();
509 ind().put("<specular ");
510 putFloatAttr("r", rgba[0]).put(' ');
511 putFloatAttr("g", rgba[1]).put(' ');
512 putFloatAttr("b", rgba[2]).put(' ');
513 putFloatAttr("shininess", shininess).put(' ');
516 Color ambient = material.getAmbientColor();
517 ambient.getRGBComponents(rgba);
518 ind().put("<ambient ");
519 putFloatAttr("r", rgba[0]).put(' ');
520 putFloatAttr("g", rgba[1]).put(' ');
521 putFloatAttr("b", rgba[2]).put(' ');
524 ShadeInfo shade = material.getShadeInfo();
525 String textureFileName = shade.getTextureFileName();
526 String spheremapFileName = shade.getSpheremapFileName();
528 if(shade.isValidToonIndex()){
530 int toonIdx = shade.getToonIndex();
531 putNumberedIdAttr("toonFileIdRef", PFX_TOONFILE, toonIdx);
533 String toonFileName = shade.getToonFileName();
534 if(toonFileName != null && toonFileName.length() > 0){
535 put(' ').putLineComment(toonFileName);
540 if(textureFileName != null && textureFileName.length() > 0){
541 ind().put("<textureFile ");
542 putAttr("winFileName", textureFileName);
546 if(spheremapFileName != null && spheremapFileName.length() > 0){
547 ind().put("<spheremapFile ");
548 putAttr("winFileName", spheremapFileName);
553 ind().put("</material>").ln(2);
559 * トゥーンファイルマッピング情報を出力する。
560 * @param model モデルデータ
562 * @throws IOException 出力エラー
564 private PmdXmlExporter putToonMap(PmdModel model)
566 ind().put("<toonMap>").ln();
569 ToonMap map = model.getToonMap();
570 for(int index = 0; index <= 9; index++){
571 ind().putToon(map, index).ln();
575 ind().put("</toonMap>").ln(2);
580 * 個別のトゥーンファイル情報を出力する。
582 * @param index インデックス値
584 * @throws IOException 出力エラー
586 private PmdXmlExporter putToon(ToonMap map, int index)
589 putNumberedIdAttr("toonFileId", PFX_TOONFILE, index).put(' ');
590 putIntAttr("index", index).put(' ');
591 String toonFile = map.getIndexedToon(index);
592 putAttr("winFileName", toonFile);
594 putUnescapedComment(toonFile);
599 * サーフェイスグループリストを出力する。
600 * @param model モデルデータ
602 * @throws IOException 出力エラー
604 private PmdXmlExporter putSurfaceGroupList(PmdModel model)
606 ind().put("<surfaceGroupList>").ln(2);
610 for(Material material : model.getMaterialList()){
611 List<Surface> surfaceList = material.getSurfaceList();
612 putSurfaceList(surfaceList, ct++);
616 ind().put("</surfaceGroupList>").ln(2);
622 * 個別のサーフェイスグループを出力する。
623 * @param surfaceList サーフェイスのリスト
624 * @param index グループインデックス
626 * @throws IOException 出力エラー
628 private PmdXmlExporter putSurfaceList(List<Surface> surfaceList,
631 ind().put("<surfaceGroup ");
632 putNumberedIdAttr("surfaceGroupId", PFX_SURFACEGROUP, index);
636 for(Surface surface : surfaceList){
641 ind().put("</surfaceGroup>").ln(2);
648 * @param surface サーフェイス
650 * @throws IOException 出力エラー
652 private PmdXmlExporter putSurface(Surface surface)
654 ind().put("<surface ");
656 Vertex vertex1 = surface.getVertex1();
657 Vertex vertex2 = surface.getVertex2();
658 Vertex vertex3 = surface.getVertex3();
660 putNumberedIdAttr("vtxIdRef1", PFX_VERTEX, vertex1).put(' ');
661 putNumberedIdAttr("vtxIdRef2", PFX_VERTEX, vertex2).put(' ');
662 putNumberedIdAttr("vtxIdRef3", PFX_VERTEX, vertex3).put(' ');
670 * @param model モデルデータ
672 * @throws IOException 出力エラー
674 private PmdXmlExporter putVertexList(PmdModel model)
676 ind().put("<vertexList>").ln(2);
679 for(Vertex vertex : model.getVertexList()){
684 ind().put("</vertexList>").ln(2);
693 * @throws IOException 出力エラー
695 private PmdXmlExporter putVertex(Vertex vertex)
698 if(vertex.getEdgeAppearance()) bool = "true";
701 ind().put("<vertex ");
702 putNumberedIdAttr("vtxId", PFX_VERTEX, vertex).put(' ');
703 putAttr("showEdge", bool);
707 Pos3d position = vertex.getPosition();
708 ind().putPosition(position).ln();
710 Vec3d normal = vertex.getNormal();
711 ind().put("<normal ");
712 putFloatAttr("x", normal.getXVal()).put(' ');
713 putFloatAttr("y", normal.getYVal()).put(' ');
714 putFloatAttr("z", normal.getZVal()).put(' ');
717 Pos2d uvPos = vertex.getUVPosition();
718 ind().put("<uvMap ");
719 putFloatAttr("u", uvPos.getXPos()).put(' ');
720 putFloatAttr("v", uvPos.getYPos()).put(' ');
723 BoneInfo boneA = vertex.getBoneA();
724 BoneInfo boneB = vertex.getBoneB();
725 int weight = vertex.getWeightA();
726 ind().put("<skinning ");
727 putNumberedIdAttr("boneIdRef1", PFX_BONE, boneA).put(' ');
728 putNumberedIdAttr("boneIdRef2", PFX_BONE, boneB).put(' ');
729 putIntAttr("weightBalance", weight).put(' ');
733 ind().put("</vertex>").ln(2);
740 * @param model モデルデータ
742 * @throws IOException 出力エラー
744 private PmdXmlExporter putBoneList(PmdModel model)
746 ind().put("<boneList>").ln(2);
749 putBlockComment(BONETYPE_COMMENT).ln();
751 for(BoneInfo bone : model.getBoneList()){
756 ind().put("</boneList>").ln(2);
765 * @throws IOException 出力エラー
767 private PmdXmlExporter putBone(BoneInfo bone)
769 I18nText i18nName = bone.getBoneName();
770 BoneType type = bone.getBoneType();
772 putLocalNameComment(i18nName).putLineComment(type.getGuiName()).ln();
774 putPrimaryNameAttr("name", i18nName).put(' ');
775 putNumberedIdAttr("boneId", PFX_BONE, bone).put(' ');
776 putAttr("type", type.name());
780 putI18nName(i18nName);
782 Pos3d position = bone.getPosition();
783 ind().putPosition(position).ln();
785 BoneInfo ikBone = bone.getIKBone();
786 if(bone.getBoneType() == BoneType.LINKEDROT){
787 ind().put("<rotationRatio ");
788 putIntAttr("ratio", bone.getRotationRatio());
790 }else if(ikBone != null){
791 ind().put("<ikBone ");
792 putNumberedIdAttr("boneIdRef", PFX_BONE, ikBone);
794 String ikBoneName = "Ref:" + ikBone.getBoneName().getText();
795 putLineComment(ikBoneName);
799 StringBuilder chainComment = new StringBuilder();
800 ind().put("<boneChain");
801 BoneInfo prev = bone.getPrevBone();
802 BoneInfo next = bone.getNextBone();
805 putNumberedIdAttr("prevBoneIdRef", PFX_BONE, prev);
806 chainComment.append('[')
807 .append(prev.getBoneName().getPrimaryText())
813 putNumberedIdAttr("nextBoneIdRef", PFX_BONE, next);
814 if(chainComment.length() <= 0) chainComment.append("#");
815 chainComment.append(" =>")
817 .append(next.getBoneName().getPrimaryText())
821 ind().putLineComment(chainComment).ln();
824 ind().put("</bone>").ln(2);
831 * @param model モデルデータ
833 * @throws IOException 出力エラー
835 private PmdXmlExporter putBoneGroupList(PmdModel model)
837 ind().put("<boneGroupList>").ln(2);
840 for(BoneGroup group : model.getBoneGroupList()){
841 if(group.isDefaultBoneGroup()) continue;
846 ind().put("</boneGroupList>").ln(2);
853 * @param group ボーングループ情報
855 * @throws IOException 出力エラー
857 private PmdXmlExporter putBoneGroup(BoneGroup group)
859 I18nText i18nName = group.getGroupName();
861 putLocalNameComment(i18nName).ln();
862 ind().put("<boneGroup ");
863 putPrimaryNameAttr("name", i18nName);
867 putI18nName(i18nName);
869 for(BoneInfo bone : group){
870 ind().put("<boneGroupMember ");
871 putNumberedIdAttr("boneIdRef", PFX_BONE, bone);
873 String boneName = "Ref:" + bone.getBoneName().getText();
874 putLineComment(boneName).ln();
878 ind().put("</boneGroup>").ln(2);
885 * @param model モデルデータ
887 * @throws IOException 出力エラー
889 private PmdXmlExporter putIKChainList(PmdModel model)
891 ind().put("<ikChainList>").ln(2);
894 for(IKChain chain : model.getIKChainList()){
899 ind().put("</ikChainList>").ln(2);
906 * @param chain チェーン情報
908 * @throws IOException 出力エラー
910 private PmdXmlExporter putIKChain(IKChain chain)
912 int depth = chain.getIKDepth();
913 float weight = chain.getIKWeight();
914 BoneInfo ikBone = chain.getIkBone();
916 ind().putLineComment("Ref:" + ikBone.getBoneName().getText()).ln();
917 ind().put("<ikChain ");
918 putNumberedIdAttr("ikBoneIdRef", PFX_BONE, ikBone).put(' ');
919 putIntAttr("recursiveDepth", depth).put(' ');
920 putFloatAttr("weight", weight);
924 for(BoneInfo bone : chain){
925 ind().put("<chainOrder ");
926 putNumberedIdAttr("boneIdRef", PFX_BONE, bone);
928 putLineComment("Ref:" + bone.getBoneName().getText());
933 ind().put("</ikChain>").ln(2);
940 * @param model モデルデータ
942 * @throws IOException 出力エラー
944 private PmdXmlExporter putMorphList(PmdModel model)
946 ind().put("<morphList>").ln(2);
949 putBlockComment(MORPHTYPE_COMMENT).ln();
951 Map<MorphType, List<MorphPart>> morphMap = model.getMorphMap();
952 for(MorphType type : MorphType.values()){
953 if(type == MorphType.BASE) continue;
954 List<MorphPart> partList = morphMap.get(type);
955 if(partList == null) continue;
956 for(MorphPart part : partList){
962 ind().put("</morphList>").ln(2);
971 * @throws IOException 出力エラー
973 private PmdXmlExporter putMorphPart(MorphPart part)
975 I18nText i18nName = part.getMorphName();
976 String primary = i18nName.getPrimaryText();
978 ind().put("<morph ");
979 putAttr("name", primary).put(' ');
980 putAttr("type", part.getMorphType().name());
982 putUnescapedComment(primary);
986 putI18nName(i18nName);
988 for(MorphVertex mvertex : part){
989 Pos3d offset = mvertex.getOffset();
990 Vertex base = mvertex.getBaseVertex();
992 ind().put("<morphVertex ");
993 putNumberedIdAttr("vtxIdRef", PFX_VERTEX, base).put(' ');
994 putFloatAttr("xOff", offset.getXPos()).put(' ');
995 putFloatAttr("yOff", offset.getYPos()).put(' ');
996 putFloatAttr("zOff", offset.getZPos()).put(' ');
1002 ind().put("</morph>").ln(2);
1009 * @param model モデルデータ
1011 * @throws IOException 出力エラー
1013 private PmdXmlExporter putRigidList(PmdModel model)
1015 ind().put("<rigidList>").ln(2);
1018 putBlockComment(RIGIDBEHAVIOR_COMMENT).ln();
1020 for(RigidInfo rigid : model.getRigidList()){
1025 ind().put("</rigidList>").ln(2);
1034 * @throws IOException 出力エラー
1036 private PmdXmlExporter putRigid(RigidInfo rigid)
1038 BoneInfo linkedBone = rigid.getLinkedBone();
1039 I18nText i18nName = rigid.getRigidName();
1040 String primary = i18nName.getPrimaryText();
1042 putLocalNameComment(i18nName).ln();
1043 ind().put("<rigid ");
1044 putAttr("name", primary).put(' ');
1045 putNumberedIdAttr("rigidId", PFX_RIGID, rigid).put(' ');
1046 putAttr("behavior", rigid.getBehaviorType().name());
1050 putI18nName(i18nName);
1052 if(linkedBone != null){
1053 ind().put("<linkedBone ");
1054 putNumberedIdAttr("boneIdRef", PFX_BONE, linkedBone);
1056 putLineComment("Ref:" + linkedBone.getBoneName().getText());
1060 RigidShape shape = rigid.getRigidShape();
1061 putRigidShape(shape);
1063 Pos3d position = rigid.getPosition();
1064 ind().putPosition(position).ln();
1066 Rad3d rotation = rigid.getRotation();
1067 ind().putRadRotation(rotation).ln();
1069 DynamicsInfo dynamics = rigid.getDynamicsInfo();
1070 putDynamics(dynamics).ln();
1072 for(RigidGroup group : rigid.getThroughGroupColl()){
1073 ind().put("<throughRigidGroup ");
1074 putNumberedIdAttr("rigidGroupIdRef",
1076 group.getSerialNumber() + 1).put(' ');
1081 ind().put("</rigid>").ln(2);
1090 * @throws IOException 出力エラー
1092 private PmdXmlExporter putRigidShape(RigidShape shape)
1094 RigidShapeType type = shape.getShapeType();
1098 ind().put("<rigidShapeBox ");
1099 putFloatAttr("width", shape.getWidth()).put(' ');
1100 putFloatAttr("height", shape.getHeight()).put(' ');
1101 putFloatAttr("depth", shape.getDepth()).put(' ');
1104 ind().put("<rigidShapeSphere ");
1105 putFloatAttr("radius", shape.getRadius()).put(' ');
1108 ind().put("<rigidShapeCapsule ");
1109 putFloatAttr("height", shape.getHeight()).put(' ');
1110 putFloatAttr("radius", shape.getRadius()).put(' ');
1114 throw new AssertionError();
1124 * @param dynamics 力学設定
1126 * @throws IOException 出力エラー
1128 private PmdXmlExporter putDynamics(DynamicsInfo dynamics)
1130 ind().put("<dynamics").ln();
1132 ind().putFloatAttr("mass", dynamics.getMass()).ln();
1133 ind().putFloatAttr("dampingPosition",
1134 dynamics.getDampingPosition()).ln();
1135 ind().putFloatAttr("dampingRotation",
1136 dynamics.getDampingRotation()).ln();
1137 ind().putFloatAttr("restitution", dynamics.getRestitution()).ln();
1138 ind().putFloatAttr("friction", dynamics.getFriction()).ln();
1140 ind().put("/>").ln();
1147 * @param model モデルデータ
1149 * @throws IOException 出力エラー
1151 private PmdXmlExporter putRigidGroupList(PmdModel model)
1153 ind().put("<rigidGroupList>").ln(2);
1156 for(RigidGroup group : model.getRigidGroupList()){
1157 ind().put("<rigidGroup ");
1158 putNumberedIdAttr("rigidGroupId",
1160 group.getSerialNumber() + 1);
1161 List<RigidInfo> rigidList = group.getRigidList();
1162 if(rigidList.size() <= 0){
1169 for(RigidInfo rigid : rigidList){
1170 ind().put("<rigidGroupMember ");
1171 putNumberedIdAttr("rigidIdRef", PFX_RIGID, rigid).put(' ');
1174 putLineComment("Ref:" + rigid.getRigidName().getText());
1179 ind().put("</rigidGroup>").ln(2);
1183 ind().put("</rigidGroupList>").ln(2);
1190 * @param model モデルデータ
1192 * @throws IOException 出力エラー
1194 private PmdXmlExporter putJointList(PmdModel model)
1196 ind().put("<jointList>").ln(2);
1199 for(JointInfo joint : model.getJointList()){
1204 ind().put("</jointList>").ln(2);
1211 * @param joint ジョイント情報
1213 * @throws IOException 出力エラー
1215 private PmdXmlExporter putJoint(JointInfo joint)
1217 I18nText i18nName = joint.getJointName();
1219 putLocalNameComment(i18nName).ln();
1220 ind().put("<joint ");
1221 putPrimaryNameAttr("name", i18nName);
1225 putI18nName(i18nName);
1227 RigidInfo rigidA = joint.getRigidA();
1228 RigidInfo rigidB = joint.getRigidB();
1229 ind().put("<jointedRigidPair ");
1230 putNumberedIdAttr("rigidIdRef1", PFX_RIGID, rigidA).put(' ');
1231 putNumberedIdAttr("rigidIdRef2", PFX_RIGID, rigidB).put(' ');
1234 putLineComment("[" + rigidA.getRigidName().getText() + "]"
1235 + " <=> [" + rigidB.getRigidName().getText() + "]");
1238 Pos3d position = joint.getPosition();
1239 ind().putPosition(position).ln();
1241 TripletRange posRange = joint.getPositionRange();
1242 ind().put("<limitPosition").ln();
1245 putFloatAttr("xFrom", posRange.getXFrom()).put(' ');
1246 putFloatAttr("xTo", posRange.getXTo()).ln();
1248 putFloatAttr("yFrom", posRange.getYFrom()).put(' ');
1249 putFloatAttr("yTo", posRange.getYTo()).ln();
1251 putFloatAttr("zFrom", posRange.getZFrom()).put(' ');
1252 putFloatAttr("zTo", posRange.getZTo()).ln();
1254 ind().put("/>").ln(2);
1256 Rad3d rotation = joint.getRotation();
1257 ind().putRadRotation(rotation).ln();
1258 TripletRange rotRange = joint.getRotationRange();
1259 ind().put("<limitRotation").ln();
1262 putFloatAttr("xFrom", rotRange.getXFrom()).put(' ');
1263 putFloatAttr("xTo", rotRange.getXTo()).ln();
1265 putFloatAttr("yFrom", rotRange.getYFrom()).put(' ');
1266 putFloatAttr("yTo", rotRange.getYTo()).ln();
1268 putFloatAttr("zFrom", rotRange.getZFrom()).put(' ');
1269 putFloatAttr("zTo", rotRange.getZTo()).ln();
1271 ind().put("/>").ln(2);
1273 Pos3d elaPosition = joint.getElasticPosition();
1274 ind().put("<elasticPosition ");
1275 putFloatAttr("x", elaPosition.getXPos()).put(' ');
1276 putFloatAttr("y", elaPosition.getYPos()).put(' ');
1277 putFloatAttr("z", elaPosition.getZPos()).put(' ');
1280 Deg3d elaRotation = joint.getElasticRotation();
1281 ind().put("<elasticRotation ");
1282 putFloatAttr("xDeg", elaRotation.getXDeg()).put(' ');
1283 putFloatAttr("yDeg", elaRotation.getYDeg()).put(' ');
1284 putFloatAttr("zDeg", elaRotation.getZDeg()).put(' ');
1288 ind().put("</joint>").ln(2);