OSDN Git Service

XML出力改善
[mikutoga/Pmd2XML.git] / src / main / java / jp / sourceforge / mikutoga / pmd / model / xml / Xml2PmdLoader.java
1 /*
2  * xml loader
3  *
4  * License : The MIT License
5  * Copyright(c) 2010 MikuToga Partners
6  */
7
8 package jp.sourceforge.mikutoga.pmd.model.xml;
9
10 import java.awt.Color;
11 import java.io.IOException;
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.LinkedList;
15 import java.util.List;
16 import java.util.Map;
17 import javax.xml.parsers.DocumentBuilder;
18 import jp.sourceforge.mikutoga.corelib.I18nText;
19 import jp.sourceforge.mikutoga.pmd.model.ListUtil;
20 import jp.sourceforge.mikutoga.math.MkPos2D;
21 import jp.sourceforge.mikutoga.math.MkPos3D;
22 import jp.sourceforge.mikutoga.math.MkVec3D;
23 import jp.sourceforge.mikutoga.pmd.BoneType;
24 import jp.sourceforge.mikutoga.pmd.Deg3d;
25 import jp.sourceforge.mikutoga.pmd.MorphType;
26 import jp.sourceforge.mikutoga.pmd.Rad3d;
27 import jp.sourceforge.mikutoga.pmd.RigidBehaviorType;
28 import jp.sourceforge.mikutoga.pmd.RigidShapeType;
29 import jp.sourceforge.mikutoga.pmd.TripletRange;
30 import jp.sourceforge.mikutoga.pmd.model.BoneGroup;
31 import jp.sourceforge.mikutoga.pmd.model.BoneInfo;
32 import jp.sourceforge.mikutoga.pmd.model.DynamicsInfo;
33 import jp.sourceforge.mikutoga.pmd.model.IKChain;
34 import jp.sourceforge.mikutoga.pmd.model.JointInfo;
35 import jp.sourceforge.mikutoga.pmd.model.Material;
36 import jp.sourceforge.mikutoga.pmd.model.MorphPart;
37 import jp.sourceforge.mikutoga.pmd.model.MorphVertex;
38 import jp.sourceforge.mikutoga.pmd.model.PmdModel;
39 import jp.sourceforge.mikutoga.pmd.model.RigidGroup;
40 import jp.sourceforge.mikutoga.pmd.model.RigidInfo;
41 import jp.sourceforge.mikutoga.pmd.model.RigidShape;
42 import jp.sourceforge.mikutoga.pmd.model.ShadeInfo;
43 import jp.sourceforge.mikutoga.pmd.model.Surface;
44 import jp.sourceforge.mikutoga.pmd.model.ToonMap;
45 import jp.sourceforge.mikutoga.pmd.model.Vertex;
46 import jp.sourceforge.mikutoga.xml.DomUtils;
47 import jp.sourceforge.mikutoga.xml.TogaXmlException;
48 import org.w3c.dom.Document;
49 import org.w3c.dom.Element;
50 import org.w3c.dom.Node;
51 import org.w3c.dom.NodeList;
52 import org.xml.sax.InputSource;
53 import org.xml.sax.SAXException;
54
55 /**
56  * XML形式でのモデルファイルを読み込む。
57  */
58 public class Xml2PmdLoader {
59
60     private final DocumentBuilder builder;
61
62     private PmdModel model;
63
64     private final Map<String, Integer> toonIdxMap =
65             new HashMap<String, Integer>();
66     private final Map<String, BoneInfo> boneMap =
67             new HashMap<String, BoneInfo>();
68     private final Map<String, Vertex> vertexMap =
69             new HashMap<String, Vertex>();
70     private final Map<String, List<Surface>> surfaceGroupMap =
71             new HashMap<String, List<Surface>>();
72     private final Map<String, RigidInfo> rigidMap =
73             new HashMap<String, RigidInfo>();
74     private final Map<String, RigidGroup> rigidGroupMap =
75             new HashMap<String, RigidGroup>();
76
77
78     /**
79      * コンストラクタ。
80      * @param builder ビルダ
81      */
82     public Xml2PmdLoader(DocumentBuilder builder){
83         super();
84         this.builder = builder;
85         return;
86     }
87
88     /**
89      * 要素からxsd:string型属性値を読み取る。
90      * @param elem 要素
91      * @param attrName 属性名
92      * @return 文字列
93      * @throws TogaXmlException 属性値が見つからなかった。
94      */
95     private static String getStringAttr(Element elem, String attrName)
96             throws TogaXmlException{
97         return DomUtils.getStringAttr(elem, attrName);
98     }
99
100     /**
101      * 要素からxsd:boolean型属性値を読み取る。
102      * @param elem 要素
103      * @param attrName 属性名
104      * @return 真ならtrue
105      * @throws TogaXmlException 属性値が見つからなかった。
106      */
107     private static boolean getBooleanAttr(Element elem, String attrName)
108             throws TogaXmlException{
109         return DomUtils.getBooleanAttr(elem, attrName);
110     }
111
112     /**
113      * 要素からxsd:integer型属性値を読み取る。
114      * @param elem 要素
115      * @param attrName 属性名
116      * @return int値
117      * @throws TogaXmlException 属性値が見つからなかった。
118      */
119     private static int getIntegerAttr(Element elem, String attrName)
120             throws TogaXmlException{
121         return DomUtils.getIntegerAttr(elem, attrName);
122     }
123
124     /**
125      * 要素からxsd:float型属性値を読み取る。
126      * @param elem 要素
127      * @param attrName 属性名
128      * @return float値
129      * @throws TogaXmlException 属性値が見つからなかった。
130      */
131     private static float getFloatAttr(Element elem, String attrName)
132             throws TogaXmlException{
133         return DomUtils.getFloatAttr(elem, attrName);
134     }
135
136     /**
137      * 要素から日本語Windows用ファイル名を属性値として読み取る。
138      * 念のため文字U+00A5は文字U-005Cに変換される。
139      * @param elem 要素
140      * @param attrName 属性名
141      * @return ファイル名
142      * @throws TogaXmlException 属性値が見つからなかった。
143      */
144     private static String getSjisFileNameAttr(Element elem, String attrName)
145             throws TogaXmlException{
146         return DomUtils.getSjisFileNameAttr(elem, attrName);
147     }
148
149     /**
150      * 指定された名前の子要素を1つだけ返す。
151      * @param parent 親要素
152      * @param tagName 子要素名
153      * @return 子要素
154      * @throws TogaXmlException 1つも見つからなかった
155      */
156     private static Element getChild(Element parent, String tagName)
157             throws TogaXmlException{
158         return DomUtils.getChild(parent, tagName);
159     }
160
161     /**
162      * 親要素が指定された名前の子要素を持つか判定する。
163      * @param parent 親要素
164      * @param tagName 子要素名
165      * @return 指定名の子要素が存在すればtrue
166      */
167     private static boolean hasChild(Element parent, String tagName){
168         return DomUtils.hasChild(parent, tagName);
169     }
170
171     /**
172      * 指定された名前の子要素のforeachを返す。
173      * @param parent 親要素
174      * @param childTag 子要素名
175      * @return 子要素のforeach
176      */
177     private static Iterable<Element> eachChild(Element parent,
178                                                     String childTag){
179         return DomUtils.getEachChild(parent, childTag);
180     }
181
182     /**
183      * グローバル名を取得する。
184      * 元要素のname属性及びi18nNameタグを持つ子要素が検索対象
185      * @param parent 元要素
186      * @return グローバル名。なければnull
187      */
188     private static String getGlobalName(Element parent){
189         NodeList nodeList = parent.getElementsByTagName("i18nName");
190         int length = nodeList.getLength();
191         for(int idx = 0; idx < length; idx++){
192             Node i18nNameNode = nodeList.item(idx);
193             Element i18nNameElem = (Element)i18nNameNode;
194             String lang = i18nNameElem.getAttribute("lang");
195             if(lang == null || lang.length() <= 0) continue;
196             if(lang.equals("en")){
197                 String name = i18nNameElem.getAttribute("name");
198                 return name;
199             }
200         }
201         return null;
202     }
203
204     /**
205      * brタグで区切られた文字列内容(Mixed content)を改行付き文字列に変換する。
206      * brタグはその出現回数だけ\nに変換される。
207      * 生文字列コンテンツ中の\n,\rは削除される。
208      * 改行文字以外のホワイトスペースは保持される。
209      * @param parent br要素及び文字列コンテンツを含む要素
210      * @return 変換された文字列
211      */
212     private static String getBRedContent(Element parent){
213         StringBuilder result = new StringBuilder();
214
215         for(Node node = parent.getFirstChild();
216             node != null;
217             node = node.getNextSibling() ){
218
219             switch(node.getNodeType()){
220             case Node.ELEMENT_NODE:
221                 Element elem = (Element) node;
222                 if("br".equals(elem.getTagName())){
223                     result.append('\n');
224                 }
225                 break;
226             case Node.TEXT_NODE:
227             case Node.CDATA_SECTION_NODE:
228                 String content = node.getTextContent();
229                 content = content.replace("\r", "");
230                 content = content.replace("\n", "");
231                 result.append(content);
232                 break;
233             default:
234                 break;
235             }
236         }
237
238         return result.toString();
239     }
240
241     /**
242      * 多言語名を取得する。
243      * @param baseElement 元要素
244      * @param text 多言語名
245      * @throws TogaXmlException あるべき属性が存在しない。
246      */
247     private static void buildI18nName(Element baseElement, I18nText text)
248             throws TogaXmlException{
249         String primaryText;
250         primaryText = getStringAttr(baseElement, "name");
251         text.setPrimaryText(primaryText);
252
253         for(Element i18nNameElem : eachChild(baseElement, "i18nName")){
254             String lang = getStringAttr(i18nNameElem, "lang");
255             String name = getStringAttr(i18nNameElem, "name");
256             if("en".equals(lang)){
257                 text.setGlobalText(name);
258             }else{
259                 text.setI18nText(lang, text);
260             }
261         }
262
263         return;
264     }
265
266     /**
267      * XMLのパースを開始する。
268      * @param source XML入力
269      * @return モデルデータ
270      * @throws SAXException 構文エラー
271      * @throws IOException 入力エラー
272      * @throws TogaXmlException 構文エラー
273      */
274     public PmdModel parse(InputSource source)
275             throws SAXException, IOException, TogaXmlException{
276         Document document = this.builder.parse(source);
277
278         this.model = new PmdModel();
279
280         Element pmdModelElem = document.getDocumentElement();
281
282         buildBasicInfo(pmdModelElem);
283
284         buildBoneList(pmdModelElem);
285         buildVertexList(pmdModelElem);
286         buildSurfaceList(pmdModelElem);
287
288         buildToonMap(pmdModelElem);
289         buildMaterialList(pmdModelElem);
290         buildIkChainList(pmdModelElem);
291         buildMorphList(pmdModelElem);
292         buildBoneGroupList(pmdModelElem);
293
294         buildRigidList(pmdModelElem);
295         buildRigidGroupList(pmdModelElem);
296         resolveThroughRigidGroup(pmdModelElem);
297
298         buildJointList(pmdModelElem);
299
300         return this.model;
301     }
302
303     private void buildBasicInfo(Element pmdModelElem)
304             throws TogaXmlException{
305         String primaryName = getStringAttr(pmdModelElem, "name");
306         String globalName = getGlobalName(pmdModelElem);
307
308         I18nText modelName = this.model.getModelName();
309         modelName.setPrimaryText(primaryName);
310         modelName.setGlobalText(globalName);
311
312         String primaryDescription = null;
313         String globalDescription = null;
314         for(Element descriptionElem :
315             eachChild(pmdModelElem, "description")){
316             String descriptionText = getBRedContent(descriptionElem);
317             if( ! descriptionElem.hasAttribute("lang") ){
318                 primaryDescription = descriptionText;
319             }else{
320                 String lang = getStringAttr(descriptionElem, "lang");
321                 if(lang.equals("ja")){
322                     primaryDescription = descriptionText;
323                 }else if(lang.equals("en")){
324                     globalDescription = descriptionText;
325                 }
326             }
327         }
328
329         I18nText description = this.model.getDescription();
330         description.setPrimaryText(primaryDescription);
331         description.setGlobalText(globalDescription);
332
333         return;
334     }
335
336     private void buildToonMap(Element pmdModelElem)
337             throws TogaXmlException{
338         ToonMap toonMap = this.model.getToonMap();
339
340         Element toonMapElem = getChild(pmdModelElem, "toonMap");
341
342         for(Element toonDefElem : eachChild(toonMapElem, "toonDef")){
343             String toonFileId = getStringAttr(toonDefElem, "toonFileId");
344             int toonIndex = getIntegerAttr(toonDefElem, "index");
345             String toonFile = getSjisFileNameAttr(toonDefElem, "winFileName");
346
347             toonMap.setIndexedToon(toonIndex, toonFile);
348             this.toonIdxMap.put(toonFileId, toonIndex);
349         }
350
351         return;
352     }
353
354     private void buildBoneList(Element pmdModelElem)
355             throws TogaXmlException{
356         Element boneListElem = getChild(pmdModelElem, "boneList");
357
358         List<BoneInfo> boneList = this.model.getBoneList();
359
360         for(Element boneElem : eachChild(boneListElem, "bone")){
361             BoneInfo boneInfo = new BoneInfo();
362             boneList.add(boneInfo);
363
364             I18nText boneName = boneInfo.getBoneName();
365             buildI18nName(boneElem, boneName);
366
367             String boneType = getStringAttr(boneElem, "type");
368             BoneType type = BoneType.valueOf(boneType);
369             boneInfo.setBoneType(type);
370
371             String boneId = getStringAttr(boneElem, "boneId");
372             this.boneMap.put(boneId, boneInfo);
373
374             Element positionElem = getChild(boneElem, "position");
375             float xPos = getFloatAttr(positionElem, "x");
376             float yPos = getFloatAttr(positionElem, "y");
377             float zPos = getFloatAttr(positionElem, "z");
378             MkPos3D position = boneInfo.getPosition();
379             position.setXpos(xPos);
380             position.setYpos(yPos);
381             position.setZpos(zPos);
382         }
383
384         ListUtil.assignIndexedSerial(boneList);
385
386         int serial = 0;
387         for(Element boneElem : eachChild(boneListElem, "bone")){
388             BoneInfo boneInfo = boneList.get(serial++);
389
390             if(hasChild(boneElem, "ikBone")){
391                 Element ikBoneElem = getChild(boneElem, "ikBone");
392                 String ikBoneId = getStringAttr(ikBoneElem, "boneIdRef");
393                 BoneInfo ikBone = this.boneMap.get(ikBoneId);
394                 boneInfo.setIKBone(ikBone);
395             }else if(hasChild(boneElem, "rotationRatio")){
396                 Element ikBoneElem = getChild(boneElem, "rotationRatio");
397                 int ratio = getIntegerAttr(ikBoneElem, "ratio");
398                 boneInfo.setRotationRatio(ratio);
399             }
400
401             Element boneChainElem = getChild(boneElem, "boneChain");
402             if(boneChainElem.hasAttribute("prevBoneIdRef")){
403                 String prevId = getStringAttr(boneChainElem, "prevBoneIdRef");
404                 BoneInfo prevBone = this.boneMap.get(prevId);
405                 boneInfo.setPrevBone(prevBone);
406             }
407             if(boneChainElem.hasAttribute("nextBoneIdRef")){
408                 String nextId = getStringAttr(boneChainElem, "nextBoneIdRef");
409                 BoneInfo nextBone = this.boneMap.get(nextId);
410                 boneInfo.setNextBone(nextBone);
411             }
412         }
413
414         return;
415     }
416
417     private void buildVertexList(Element pmdModelElem)
418             throws TogaXmlException{
419         Element vertexListElem = getChild(pmdModelElem, "vertexList");
420
421         List<Vertex> vertexList = this.model.getVertexList();
422
423         for(Element vertexElem : eachChild(vertexListElem, "vertex")){
424             Vertex vertex = new Vertex();
425             vertexList.add(vertex);
426
427             String vertexId = getStringAttr(vertexElem, "vtxId");
428             this.vertexMap.put(vertexId, vertex);
429
430             boolean showEdge = getBooleanAttr(vertexElem, "showEdge");
431             vertex.setEdgeAppearance(showEdge);
432
433             float xVal;
434             float yVal;
435             float zVal;
436
437             Element positionElem = getChild(vertexElem, "position");
438             xVal = getFloatAttr(positionElem, "x");
439             yVal = getFloatAttr(positionElem, "y");
440             zVal = getFloatAttr(positionElem, "z");
441             MkPos3D position = vertex.getPosition();
442             position.setXpos(xVal);
443             position.setYpos(yVal);
444             position.setZpos(zVal);
445
446             Element normalElem = getChild(vertexElem, "normal");
447             xVal = getFloatAttr(normalElem, "x");
448             yVal = getFloatAttr(normalElem, "y");
449             zVal = getFloatAttr(normalElem, "z");
450             MkVec3D normal = vertex.getNormal();
451             normal.setXVal(xVal);
452             normal.setYVal(yVal);
453             normal.setZVal(zVal);
454
455             Element uvElem = getChild(vertexElem, "uvMap");
456             float uVal = getFloatAttr(uvElem, "u");
457             float vVal = getFloatAttr(uvElem, "v");
458             MkPos2D uv = vertex.getUVPosition();
459             uv.setXpos(uVal);
460             uv.setYpos(vVal);
461
462             Element skinningElem = getChild(vertexElem, "skinning");
463             String boneId1 = getStringAttr(skinningElem, "boneIdRef1");
464             String boneId2 = getStringAttr(skinningElem, "boneIdRef2");
465             int weight = getIntegerAttr(skinningElem, "weightBalance");
466             BoneInfo boneA = this.boneMap.get(boneId1);
467             BoneInfo boneB = this.boneMap.get(boneId2);
468             vertex.setBonePair(boneA, boneB);
469             vertex.setWeightA(weight);
470         }
471
472         ListUtil.assignIndexedSerial(vertexList);
473
474         return;
475     }
476
477     private void buildSurfaceList(Element pmdModelElem)
478             throws TogaXmlException{
479         Element surfaceGroupListElem =
480                 getChild(pmdModelElem, "surfaceGroupList");
481
482         for(Element surfaceGroupElem :
483             eachChild(surfaceGroupListElem, "surfaceGroup") ){
484
485             String groupId =
486                     getStringAttr(surfaceGroupElem, "surfaceGroupId");
487             List<Surface> surfaceList = buildSurface(surfaceGroupElem);
488
489             this.surfaceGroupMap.put(groupId, surfaceList);
490         }
491     }
492
493     private List<Surface> buildSurface(Element surfaceGroupElem)
494             throws TogaXmlException{
495         List<Surface> result = new ArrayList<Surface>();
496
497         for(Element surfaceElem : eachChild(surfaceGroupElem, "surface")){
498             Surface surface = new Surface();
499             result.add(surface);
500
501             String id1 = getStringAttr(surfaceElem, "vtxIdRef1");
502             String id2 = getStringAttr(surfaceElem, "vtxIdRef2");
503             String id3 = getStringAttr(surfaceElem, "vtxIdRef3");
504
505             Vertex vertex1 = this.vertexMap.get(id1);
506             Vertex vertex2 = this.vertexMap.get(id2);
507             Vertex vertex3 = this.vertexMap.get(id3);
508
509             surface.setTriangle(vertex1, vertex2, vertex3);
510         }
511
512         return result;
513     }
514
515     private void buildMaterialList(Element pmdModelElem)
516             throws TogaXmlException{
517         Element materialListElem =
518                 getChild(pmdModelElem, "materialList");
519
520         List<Surface> surfaceList = this.model.getSurfaceList();
521         List<Material> materialList = this.model.getMaterialList();
522
523         for(Element materialElem : eachChild(materialListElem, "material")){
524             Material material = new Material();
525             materialList.add(material);
526
527             material.getShadeInfo().setToonMap(this.model.getToonMap());
528
529             String surfaceGroupId =
530                     getStringAttr(materialElem, "surfaceGroupIdRef");
531             List<Surface> surfaceGroup =
532                     this.surfaceGroupMap.get(surfaceGroupId);
533             surfaceList.addAll(surfaceGroup);
534             material.getSurfaceList().addAll(surfaceGroup);
535
536             boolean hasEdge = getBooleanAttr(materialElem, "showEdge");
537             material.setEdgeAppearance(hasEdge);
538
539             ShadeInfo shadeInfo = material.getShadeInfo();
540
541             int toonIdx;
542             if(hasChild(materialElem, "toon")){
543                 Element toonElem = getChild(materialElem, "toon");
544                 String toonId = getStringAttr(toonElem, "toonFileIdRef");
545                 toonIdx = this.toonIdxMap.get(toonId);
546             }else{
547                 toonIdx = 255;
548             }
549             shadeInfo.setToonIndex(toonIdx);
550
551             if(hasChild(materialElem, "textureFile")){
552                 Element textureFileElem =
553                         getChild(materialElem, "textureFile");
554                 String textureFile =
555                         getSjisFileNameAttr(textureFileElem, "winFileName");
556                 shadeInfo.setTextureFileName(textureFile);
557             }
558
559             if(hasChild(materialElem, "spheremapFile")){
560                 Element spheremapFileElem =
561                         getChild(materialElem, "spheremapFile");
562                 String spheremapFile =
563                         getSjisFileNameAttr(spheremapFileElem, "winFileName");
564                 shadeInfo.setSpheremapFileName(spheremapFile);
565             }
566
567             float red;
568             float green;
569             float blue;
570
571             Element diffuseElem = getChild(materialElem, "diffuse");
572             red   = getFloatAttr(diffuseElem, "r");
573             green = getFloatAttr(diffuseElem, "g");
574             blue  = getFloatAttr(diffuseElem, "b");
575             float alpha = getFloatAttr(diffuseElem, "alpha");
576             Color diffuse = new Color(red, green, blue, alpha);
577             material.setDiffuseColor(diffuse);
578
579             Element specularElem = getChild(materialElem, "specular");
580             red   = getFloatAttr(specularElem, "r");
581             green = getFloatAttr(specularElem, "g");
582             blue  = getFloatAttr(specularElem, "b");
583             float shininess = getFloatAttr(specularElem, "shininess");
584             Color specular = new Color(red, green, blue);
585             material.setSpecularColor(specular);
586             material.setShininess(shininess);
587
588             Element ambientElem = getChild(materialElem, "ambient");
589             red   = getFloatAttr(ambientElem, "r");
590             green = getFloatAttr(ambientElem, "g");
591             blue  = getFloatAttr(ambientElem, "b");
592             Color ambient = new Color(red, green, blue);
593             material.setAmbientColor(ambient);
594         }
595
596         return;
597     }
598
599     private void buildIkChainList(Element pmdModelElem)
600             throws TogaXmlException{
601         Element ikChainListElem =
602                 getChild(pmdModelElem, "ikChainList");
603
604         List<IKChain> ikChainList = this.model.getIKChainList();
605
606         for(Element ikChainElem : eachChild(ikChainListElem, "ikChain")){
607             IKChain ikChain = new IKChain();
608             ikChainList.add(ikChain);
609
610             String ikBoneIdRef = getStringAttr(ikChainElem, "ikBoneIdRef");
611             int rucursiveDepth =
612                     getIntegerAttr(ikChainElem, "recursiveDepth");
613             float weight = getFloatAttr(ikChainElem, "weight");
614
615             BoneInfo ikBone = this.boneMap.get(ikBoneIdRef);
616             ikChain.setIkBone(ikBone);
617             ikChain.setIKDepth(rucursiveDepth);
618             ikChain.setIKWeight(weight);
619
620             List<BoneInfo> chainList = ikChain.getChainedBoneList();
621
622             for(Element orderElem : eachChild(ikChainElem, "chainOrder")){
623                 String boneIdRef = getStringAttr(orderElem, "boneIdRef");
624                 BoneInfo chaindBone = this.boneMap.get(boneIdRef);
625                 chainList.add(chaindBone);
626             }
627         }
628
629         return;
630     }
631
632     private void buildMorphList(Element pmdModelElem)
633             throws TogaXmlException{
634         Element morphListElem =
635                 getChild(pmdModelElem, "morphList");
636
637         Map<MorphType, List<MorphPart>> morphMap = this.model.getMorphMap();
638
639         for(Element morphElem : eachChild(morphListElem, "morph")){
640             MorphPart morphPart = new MorphPart();
641
642             I18nText name = morphPart.getMorphName();
643             buildI18nName(morphElem, name);
644
645             String type = getStringAttr(morphElem, "type");
646             MorphType morphType = MorphType.valueOf(type);
647             morphPart.setMorphType(morphType);
648
649             List<MorphVertex> morphVertexList =
650                     morphPart.getMorphVertexList();
651
652             for(Element morphVertexElem
653                     : eachChild(morphElem, "morphVertex")){
654                 String vtxIdRef = getStringAttr(morphVertexElem, "vtxIdRef");
655                 Vertex baseVertex = this.vertexMap.get(vtxIdRef);
656                 float xOff = getFloatAttr(morphVertexElem, "xOff");
657                 float yOff = getFloatAttr(morphVertexElem, "yOff");
658                 float zOff = getFloatAttr(morphVertexElem, "zOff");
659
660                 MorphVertex morphVertex = new MorphVertex();
661                 morphVertex.setBaseVertex(baseVertex);
662                 MkPos3D position = morphVertex.getOffset();
663                 position.setXpos(xOff);
664                 position.setYpos(yOff);
665                 position.setZpos(zOff);
666
667                 morphVertexList.add(morphVertex);
668             }
669
670             morphMap.get(morphType).add(morphPart);
671         }
672
673         List<MorphPart> serialList = new LinkedList<MorphPart>();
674         MorphPart baseDummy = new MorphPart();
675         serialList.add(baseDummy);
676         for(MorphPart part : morphMap.get(MorphType.EYEBROW)){
677             serialList.add(part);
678         }
679         for(MorphPart part : morphMap.get(MorphType.EYE)){
680             serialList.add(part);
681         }
682         for(MorphPart part : morphMap.get(MorphType.LIP)){
683             serialList.add(part);
684         }
685         for(MorphPart part : morphMap.get(MorphType.EXTRA)){
686             serialList.add(part);
687         }
688         ListUtil.assignIndexedSerial(serialList);
689
690         return;
691     }
692
693     private void buildBoneGroupList(Element pmdModelElem)
694             throws TogaXmlException{
695         Element boneGroupListElem =
696                 getChild(pmdModelElem, "boneGroupList");
697
698         List<BoneGroup> boneGroupList = this.model.getBoneGroupList();
699         BoneGroup defaultGroup = new BoneGroup();
700         boneGroupList.add(defaultGroup);
701
702         for(Element boneGroupElem
703                 : eachChild(boneGroupListElem, "boneGroup")){
704             BoneGroup group = new BoneGroup();
705             boneGroupList.add(group);
706
707             I18nText name = group.getGroupName();
708             buildI18nName(boneGroupElem, name);
709
710             for(Element boneGroupMemberElem
711                     : eachChild(boneGroupElem, "boneGroupMember")){
712                 String boneIdRef =
713                         getStringAttr(boneGroupMemberElem, "boneIdRef");
714                 BoneInfo bone = this.boneMap.get(boneIdRef);
715                 group.getBoneList().add(bone);
716             }
717         }
718
719         ListUtil.assignIndexedSerial(boneGroupList);
720
721         return;
722     }
723
724     private void buildRigidList(Element pmdModelElem)
725             throws TogaXmlException{
726         Element rigidListElem =
727                 getChild(pmdModelElem, "rigidList");
728
729         List<RigidInfo> rigidList = this.model.getRigidList();
730
731         for(Element rigidElem : eachChild(rigidListElem, "rigid")){
732             RigidInfo rigid = new RigidInfo();
733             rigidList.add(rigid);
734
735             I18nText name = rigid.getRigidName();
736             buildI18nName(rigidElem, name);
737
738             String behavior = getStringAttr(rigidElem, "behavior");
739             RigidBehaviorType type = RigidBehaviorType.valueOf(behavior);
740             rigid.setBehaviorType(type);
741
742             String rigidId = getStringAttr(rigidElem, "rigidId");
743             this.rigidMap.put(rigidId, rigid);
744
745             if(hasChild(rigidElem, "linkedBone")){
746                 Element linkedBoneElem = getChild(rigidElem, "linkedBone");
747                 String boneIdRef = getStringAttr(linkedBoneElem, "boneIdRef");
748                 BoneInfo linkedBone = this.boneMap.get(boneIdRef);
749                 rigid.setLinkedBone(linkedBone);
750             }
751
752             RigidShape rigidShape = rigid.getRigidShape();
753             if(hasChild(rigidElem, "rigidShapeSphere")){
754                 Element shapeElem =
755                         getChild(rigidElem, "rigidShapeSphere");
756                 float radius = getFloatAttr(shapeElem, "radius");
757                 rigidShape.setShapeType(RigidShapeType.SPHERE);
758                 rigidShape.setRadius(radius);
759             }
760             if(hasChild(rigidElem, "rigidShapeBox")){
761                 Element shapeElem =
762                         getChild(rigidElem, "rigidShapeBox");
763                 float width  = getFloatAttr(shapeElem, "width");
764                 float height = getFloatAttr(shapeElem, "height");
765                 float depth  = getFloatAttr(shapeElem, "depth");
766                 rigidShape.setShapeType(RigidShapeType.BOX);
767                 rigidShape.setWidth(width);
768                 rigidShape.setHeight(height);
769                 rigidShape.setDepth(depth);
770             }
771             if(hasChild(rigidElem, "rigidShapeCapsule")){
772                 Element shapeElem =
773                         getChild(rigidElem, "rigidShapeCapsule");
774                 float height = getFloatAttr(shapeElem, "height");
775                 float radius = getFloatAttr(shapeElem, "radius");
776                 rigidShape.setShapeType(RigidShapeType.CAPSULE);
777                 rigidShape.setHeight(height);
778                 rigidShape.setRadius(radius);
779             }
780
781             float xVal;
782             float yVal;
783             float zVal;
784
785             Element positionElem = getChild(rigidElem, "position");
786             xVal = getFloatAttr(positionElem, "x");
787             yVal = getFloatAttr(positionElem, "y");
788             zVal = getFloatAttr(positionElem, "z");
789             MkPos3D position = rigid.getPosition();
790             position.setXpos(xVal);
791             position.setYpos(yVal);
792             position.setZpos(zVal);
793
794             Element radRotationElem = getChild(rigidElem, "radRotation");
795             xVal = getFloatAttr(radRotationElem, "xRad");
796             yVal = getFloatAttr(radRotationElem, "yRad");
797             zVal = getFloatAttr(radRotationElem, "zRad");
798             Rad3d rotation = rigid.getRotation();
799             rotation.setXRad(xVal);
800             rotation.setYRad(yVal);
801             rotation.setZRad(zVal);
802
803             Element dynamicsElem = getChild(rigidElem, "dynamics");
804             float mass = getFloatAttr(dynamicsElem, "mass");
805             float dampingPosition =
806                     getFloatAttr(dynamicsElem, "dampingPosition");
807             float dampingRotation =
808                     getFloatAttr(dynamicsElem, "dampingRotation");
809             float restitution = getFloatAttr(dynamicsElem, "restitution");
810             float friction = getFloatAttr(dynamicsElem, "friction");
811             DynamicsInfo dynamics = rigid.getDynamicsInfo();
812             dynamics.setMass(mass);
813             dynamics.setDampingPosition(dampingPosition);
814             dynamics.setDampingRotation(dampingRotation);
815             dynamics.setRestitution(restitution);
816             dynamics.setFriction(friction);
817         }
818
819         ListUtil.assignIndexedSerial(rigidList);
820
821         return;
822     }
823
824     private void buildRigidGroupList(Element pmdModelElem)
825             throws TogaXmlException{
826         Element rigidGroupListElem =
827                 getChild(pmdModelElem, "rigidGroupList");
828
829         List<RigidGroup> groupList = this.model.getRigidGroupList();
830
831         for(Element rigidGroupElem
832                 : eachChild(rigidGroupListElem, "rigidGroup")){
833             RigidGroup rigidGroup = new RigidGroup();
834             groupList.add(rigidGroup);
835
836             String rigidGroupId =
837                     getStringAttr(rigidGroupElem, "rigidGroupId");
838             this.rigidGroupMap.put(rigidGroupId, rigidGroup);
839
840             for(Element memberElem
841                     : eachChild(rigidGroupElem, "rigidGroupMember")){
842                 String rigidIdRef = getStringAttr(memberElem, "rigidIdRef");
843                 RigidInfo rigid = this.rigidMap.get(rigidIdRef);
844                 rigidGroup.getRigidList().add(rigid);
845                 rigid.setRigidGroup(rigidGroup);
846             }
847         }
848
849         while(groupList.size() < 16){
850             RigidGroup rigidGroup = new RigidGroup();
851             groupList.add(rigidGroup);
852         }
853
854         ListUtil.assignIndexedSerial(groupList);
855
856         return;
857     }
858
859     private void resolveThroughRigidGroup(Element pmdModelElem)
860             throws TogaXmlException{
861         Element rigidListElem =
862                 getChild(pmdModelElem, "rigidList");
863
864         List<RigidInfo> rigidList = this.model.getRigidList();
865
866         int serialNum = 0;
867         for(Element rigidElem : eachChild(rigidListElem, "rigid")){
868             RigidInfo rigid = rigidList.get(serialNum++);
869             for(Element groupElem
870                     : eachChild(rigidElem, "throughRigidGroup")){
871                 String groupId = getStringAttr(groupElem, "rigidGroupIdRef");
872                 RigidGroup group = this.rigidGroupMap.get(groupId);
873                 rigid.getThroughGroupColl().add(group);
874             }
875         }
876
877         return;
878     }
879
880     private void buildJointList(Element pmdModelElem)
881             throws TogaXmlException{
882         Element jointListElem =
883                 getChild(pmdModelElem, "jointList");
884
885         List<JointInfo> jointList = this.model.getJointList();
886
887         for(Element jointElem : eachChild(jointListElem, "joint")){
888             JointInfo joint = new JointInfo();
889             jointList.add(joint);
890
891             I18nText name = joint.getJointName();
892             buildI18nName(jointElem, name);
893
894             Element rigidPairElem = getChild(jointElem, "jointedRigidPair");
895             String rigidIdRef1 = getStringAttr(rigidPairElem, "rigidIdRef1");
896             String rigidIdRef2 = getStringAttr(rigidPairElem, "rigidIdRef2");
897             RigidInfo rigid1 = this.rigidMap.get(rigidIdRef1);
898             RigidInfo rigid2 = this.rigidMap.get(rigidIdRef2);
899             joint.setRigidPair(rigid1, rigid2);
900
901             float xVal;
902             float yVal;
903             float zVal;
904             float xFrom;
905             float xTo;
906             float yFrom;
907             float yTo;
908             float zFrom;
909             float zTo;
910
911             MkPos3D position = joint.getPosition();
912             Element positionElem = getChild(jointElem, "position");
913             xVal = getFloatAttr(positionElem, "x");
914             yVal = getFloatAttr(positionElem, "y");
915             zVal = getFloatAttr(positionElem, "z");
916             position.setXpos(xVal);
917             position.setYpos(yVal);
918             position.setZpos(zVal);
919
920             TripletRange limitPosition = joint.getPositionRange();
921             Element limitPositionElem = getChild(jointElem, "limitPosition");
922             xFrom = getFloatAttr(limitPositionElem, "xFrom");
923             xTo   = getFloatAttr(limitPositionElem, "xTo");
924             yFrom = getFloatAttr(limitPositionElem, "yFrom");
925             yTo   = getFloatAttr(limitPositionElem, "yTo");
926             zFrom = getFloatAttr(limitPositionElem, "zFrom");
927             zTo   = getFloatAttr(limitPositionElem, "zTo");
928             limitPosition.setXRange(xFrom, xTo);
929             limitPosition.setYRange(yFrom, yTo);
930             limitPosition.setZRange(zFrom, zTo);
931
932             Rad3d rotation = joint.getRotation();
933             Element rotationElem = getChild(jointElem, "radRotation");
934             xVal = getFloatAttr(rotationElem, "xRad");
935             yVal = getFloatAttr(rotationElem, "yRad");
936             zVal = getFloatAttr(rotationElem, "zRad");
937             rotation.setXRad(xVal);
938             rotation.setYRad(yVal);
939             rotation.setZRad(zVal);
940
941             TripletRange limitRotation = joint.getRotationRange();
942             Element limitRotationElem = getChild(jointElem, "limitRotation");
943             xFrom = getFloatAttr(limitRotationElem, "xFrom");
944             xTo   = getFloatAttr(limitRotationElem, "xTo");
945             yFrom = getFloatAttr(limitRotationElem, "yFrom");
946             yTo   = getFloatAttr(limitRotationElem, "yTo");
947             zFrom = getFloatAttr(limitRotationElem, "zFrom");
948             zTo   = getFloatAttr(limitRotationElem, "zTo");
949             limitRotation.setXRange(xFrom, xTo);
950             limitRotation.setYRange(yFrom, yTo);
951             limitRotation.setZRange(zFrom, zTo);
952
953             MkPos3D elasticPosition = joint.getElasticPosition();
954             Element elasticPositionElem =
955                     getChild(jointElem, "elasticPosition");
956             xVal = getFloatAttr(elasticPositionElem, "x");
957             yVal = getFloatAttr(elasticPositionElem, "y");
958             zVal = getFloatAttr(elasticPositionElem, "z");
959             elasticPosition.setXpos(xVal);
960             elasticPosition.setYpos(yVal);
961             elasticPosition.setZpos(zVal);
962
963             Deg3d elasticRotation = joint.getElasticRotation();
964             Element elasticRotationElem =
965                     getChild(jointElem, "elasticRotation");
966             xVal = getFloatAttr(elasticRotationElem, "xDeg");
967             yVal = getFloatAttr(elasticRotationElem, "yDeg");
968             zVal = getFloatAttr(elasticRotationElem, "zDeg");
969             elasticRotation.setXDeg(xVal);
970             elasticRotation.setYDeg(yVal);
971             elasticRotation.setZDeg(zVal);
972         }
973
974         return;
975     }
976
977 }