OSDN Git Service

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