OSDN Git Service

PMD出力機能及びXML入出力機能のソースをマージ
[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      * @throw 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      * @throw 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      * @throw 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      * @throw 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      * @throw 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      * @throw 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     private static String getGlobalName(Element parent){\r
183         NodeList nodeList = parent.getElementsByTagName("i18nName");\r
184         int length = nodeList.getLength();\r
185         for(int idx = 0; idx < length; idx++){\r
186             Node i18nNameNode = nodeList.item(idx);\r
187             Element i18nNameElem = (Element)i18nNameNode;\r
188             String lang = i18nNameElem.getAttribute("lang");\r
189             if(lang == null || lang.length() <= 0) continue;\r
190             if(lang.equals("en")){\r
191                 String name = i18nNameElem.getAttribute("name");\r
192                 return name;\r
193             }\r
194         }\r
195         return null;\r
196     }\r
197 \r
198     /**\r
199      * brタグで区切られた文字列内容(Mixed content)を改行付き文字列に変換する。\r
200      * brタグはその出現回数だけ\nに変換される。\r
201      * 生文字列コンテンツ中の\n,\rは削除される。\r
202      * 改行文字以外のホワイトスペースは保持される。\r
203      * @param parent br要素及び文字列コンテンツを含む要素\r
204      * @return 変換された文字列\r
205      */\r
206     private static String getBRedContent(Element parent){\r
207         StringBuilder result = new StringBuilder();\r
208 \r
209         for(Node node = parent.getFirstChild();\r
210             node != null;\r
211             node = node.getNextSibling() ){\r
212 \r
213             switch(node.getNodeType()){\r
214             case Node.ELEMENT_NODE:\r
215                 Element elem = (Element) node;\r
216                 if("br".equals(elem.getTagName())){\r
217                     result.append('\n');\r
218                 }\r
219                 break;\r
220             case Node.TEXT_NODE:\r
221             case Node.CDATA_SECTION_NODE:\r
222                 String content = node.getTextContent();\r
223                 content = content.replace("\r", "");\r
224                 content = content.replace("\n", "");\r
225                 result.append(content);\r
226                 break;\r
227             default:\r
228                 break;\r
229             }\r
230         }\r
231 \r
232         return result.toString();\r
233     }\r
234 \r
235     private static void buildI18nName(Element baseElement, I18nText text)\r
236             throws TogaXmlException{\r
237         String primaryText;\r
238         primaryText = getStringAttr(baseElement, "name");\r
239         text.setPrimaryText(primaryText);\r
240 \r
241         for(Element i18nNameElem : eachChild(baseElement, "i18nName")){\r
242             String lang = getStringAttr(i18nNameElem, "lang");\r
243             String name = getStringAttr(i18nNameElem, "name");\r
244             if("en".equals(lang)){\r
245                 text.setGlobalText(name);\r
246             }else{\r
247                 text.setText(lang, text);\r
248             }\r
249         }\r
250 \r
251         return;\r
252     }\r
253 \r
254     public PmdModel parse(InputSource source)\r
255             throws SAXException, IOException, TogaXmlException{\r
256         Document document = this.builder.parse(source);\r
257 \r
258         this.model = new PmdModel();\r
259 \r
260         Element pmdModelElem = document.getDocumentElement();\r
261 \r
262         buildBasicInfo(pmdModelElem);\r
263 \r
264         buildBoneList(pmdModelElem);\r
265         buildVertexList(pmdModelElem);\r
266         buildSurfaceList(pmdModelElem);\r
267 \r
268         buildToonMap(pmdModelElem);\r
269         buildMaterialList(pmdModelElem);\r
270         buildIkChainList(pmdModelElem);\r
271         buildMorphList(pmdModelElem);\r
272         buildBoneGroupList(pmdModelElem);\r
273 \r
274         buildRigidList(pmdModelElem);\r
275         buildRigidGroupList(pmdModelElem);\r
276         resolveThroughRigidGroup(pmdModelElem);\r
277 \r
278         buildJointList(pmdModelElem);\r
279 \r
280         return this.model;\r
281     }\r
282 \r
283     private void buildBasicInfo(Element pmdModelElem)\r
284             throws TogaXmlException{\r
285         String primaryName = getStringAttr(pmdModelElem, "name");\r
286         String globalName = getGlobalName(pmdModelElem);\r
287 \r
288         I18nText modelName = this.model.getModelName();\r
289         modelName.setPrimaryText(primaryName);\r
290         modelName.setGlobalText(globalName);\r
291 \r
292         String primaryDescription = null;\r
293         String globalDescription = null;\r
294         for(Element descriptionElem :\r
295             eachChild(pmdModelElem, "description")){\r
296             String descriptionText = getBRedContent(descriptionElem);\r
297             if( ! descriptionElem.hasAttribute("lang") ){\r
298                 primaryDescription = descriptionText;\r
299             }else{\r
300                 String lang = getStringAttr(descriptionElem, "lang");\r
301                 if(lang.equals("ja")){\r
302                     primaryDescription = descriptionText;\r
303                 }else if(lang.equals("en")){\r
304                     globalDescription = descriptionText;\r
305                 }\r
306             }\r
307         }\r
308 \r
309         I18nText description = this.model.getDescription();\r
310         description.setPrimaryText(primaryDescription);\r
311         description.setGlobalText(globalDescription);\r
312 \r
313         return;\r
314     }\r
315 \r
316     private void buildToonMap(Element pmdModelElem)\r
317             throws TogaXmlException{\r
318         ToonMap toonMap = this.model.getToonMap();\r
319 \r
320         Element toonMapElem = getChild(pmdModelElem, "toonMap");\r
321 \r
322         for(Element toonDefElem : eachChild(toonMapElem, "toonDef")){\r
323             String toonFileId = getStringAttr(toonDefElem, "toonFileId");\r
324             int toonIndex = getIntegerAttr(toonDefElem, "index");\r
325             String toonFile = getSjisFileNameAttr(toonDefElem, "winFileName");\r
326 \r
327             toonMap.setIndexedToon(toonIndex, toonFile);\r
328             this.toonIdxMap.put(toonFileId, toonIndex);\r
329         }\r
330 \r
331         return;\r
332     }\r
333 \r
334     private void buildBoneList(Element pmdModelElem)\r
335             throws TogaXmlException{\r
336         Element boneListElem = getChild(pmdModelElem, "boneList");\r
337 \r
338         List<BoneInfo> boneList = this.model.getBoneList();\r
339 \r
340         for(Element boneElem : eachChild(boneListElem, "bone")){\r
341             BoneInfo boneInfo = new BoneInfo();\r
342             boneList.add(boneInfo);\r
343 \r
344             I18nText boneName = boneInfo.getBoneName();\r
345             buildI18nName(boneElem, boneName);\r
346 \r
347             String boneType = getStringAttr(boneElem, "type");\r
348             BoneType type = BoneType.valueOf(boneType);\r
349             boneInfo.setBoneType(type);\r
350 \r
351             String boneId = getStringAttr(boneElem, "boneId");\r
352             this.boneMap.put(boneId, boneInfo);\r
353 \r
354             Element positionElem = getChild(boneElem, "position");\r
355             float xPos = getFloatAttr(positionElem, "x");\r
356             float yPos = getFloatAttr(positionElem, "y");\r
357             float zPos = getFloatAttr(positionElem, "z");\r
358             Pos3d position = boneInfo.getPosition();\r
359             position.setXPos(xPos);\r
360             position.setYPos(yPos);\r
361             position.setZPos(zPos);\r
362         }\r
363 \r
364         ListUtil.assignIndexedSerial(boneList);\r
365 \r
366         int serial = 0;\r
367         for(Element boneElem : eachChild(boneListElem, "bone")){\r
368             BoneInfo boneInfo = boneList.get(serial++);\r
369 \r
370             if(hasChild(boneElem, "ikBone")){\r
371                 Element ikBoneElem = getChild(boneElem, "ikBone");\r
372                 String ikBoneId = getStringAttr(ikBoneElem, "boneIdRef");\r
373                 BoneInfo ikBone = this.boneMap.get(ikBoneId);\r
374                 boneInfo.setIKBone(ikBone);\r
375             }else if(hasChild(boneElem, "rotationRatio")){\r
376                 Element ikBoneElem = getChild(boneElem, "rotationRatio");\r
377                 int ratio = getIntegerAttr(ikBoneElem, "ratio");\r
378                 boneInfo.setRotationRatio(ratio);\r
379             }\r
380 \r
381             Element boneChainElem = getChild(boneElem, "boneChain");\r
382             if(boneChainElem.hasAttribute("prevBoneIdRef")){\r
383                 String prevId = getStringAttr(boneChainElem, "prevBoneIdRef");\r
384                 BoneInfo prevBone = this.boneMap.get(prevId);\r
385                 boneInfo.setPrevBone(prevBone);\r
386             }\r
387             if(boneChainElem.hasAttribute("nextBoneIdRef")){\r
388                 String nextId = getStringAttr(boneChainElem, "nextBoneIdRef");\r
389                 BoneInfo nextBone = this.boneMap.get(nextId);\r
390                 boneInfo.setNextBone(nextBone);\r
391             }\r
392         }\r
393 \r
394         return;\r
395     }\r
396 \r
397     private void buildVertexList(Element pmdModelElem)\r
398             throws TogaXmlException{\r
399         Element vertexListElem = getChild(pmdModelElem, "vertexList");\r
400 \r
401         List<Vertex> vertexList = this.model.getVertexList();\r
402 \r
403         for(Element vertexElem : eachChild(vertexListElem, "vertex")){\r
404             Vertex vertex = new Vertex();\r
405             vertexList.add(vertex);\r
406 \r
407             String vertexId = getStringAttr(vertexElem, "vtxId");\r
408             this.vertexMap.put(vertexId, vertex);\r
409 \r
410             boolean showEdge = getBooleanAttr(vertexElem, "showEdge");\r
411             vertex.setEdgeAppearance(showEdge);\r
412 \r
413             float xVal;\r
414             float yVal;\r
415             float zVal;\r
416 \r
417             Element positionElem = getChild(vertexElem, "position");\r
418             xVal = getFloatAttr(positionElem, "x");\r
419             yVal = getFloatAttr(positionElem, "y");\r
420             zVal = getFloatAttr(positionElem, "z");\r
421             Pos3d position = vertex.getPosition();\r
422             position.setXPos(xVal);\r
423             position.setYPos(yVal);\r
424             position.setZPos(zVal);\r
425 \r
426             Element normalElem = getChild(vertexElem, "normal");\r
427             xVal = getFloatAttr(normalElem, "x");\r
428             yVal = getFloatAttr(normalElem, "y");\r
429             zVal = getFloatAttr(normalElem, "z");\r
430             Vec3d normal = vertex.getNormal();\r
431             normal.setXVal(xVal);\r
432             normal.setYVal(yVal);\r
433             normal.setZVal(zVal);\r
434 \r
435             Element uvElem = getChild(vertexElem, "uvMap");\r
436             float uVal = getFloatAttr(uvElem, "u");\r
437             float vVal = getFloatAttr(uvElem, "v");\r
438             Pos2d uv = vertex.getUVPosition();\r
439             uv.setXPos(uVal);\r
440             uv.setYPos(vVal);\r
441 \r
442             Element skinningElem = getChild(vertexElem, "skinning");\r
443             String boneId1 = getStringAttr(skinningElem, "boneIdRef1");\r
444             String boneId2 = getStringAttr(skinningElem, "boneIdRef2");\r
445             int weight = getIntegerAttr(skinningElem, "weightBalance");\r
446             BoneInfo boneA = this.boneMap.get(boneId1);\r
447             BoneInfo boneB = this.boneMap.get(boneId2);\r
448             vertex.setBonePair(boneA, boneB);\r
449             vertex.setWeightA(weight);\r
450         }\r
451 \r
452         ListUtil.assignIndexedSerial(vertexList);\r
453 \r
454         return;\r
455     }\r
456 \r
457     private void buildSurfaceList(Element pmdModelElem)\r
458             throws TogaXmlException{\r
459         Element surfaceGroupListElem =\r
460                 getChild(pmdModelElem, "surfaceGroupList");\r
461 \r
462         for(Element surfaceGroupElem :\r
463             eachChild(surfaceGroupListElem, "surfaceGroup") ){\r
464 \r
465             String groupId = getStringAttr(surfaceGroupElem, "surfaceGroupId");\r
466             List<Surface> surfaceList = buildSurface(surfaceGroupElem);\r
467 \r
468             this.surfaceGroupMap.put(groupId, surfaceList);\r
469         }\r
470     }\r
471 \r
472     private List<Surface> buildSurface(Element surfaceGroupElem)\r
473             throws TogaXmlException{\r
474         List<Surface> result = new ArrayList<Surface>();\r
475 \r
476         for(Element surfaceElem : eachChild(surfaceGroupElem, "surface")){\r
477             Surface surface = new Surface();\r
478             result.add(surface);\r
479 \r
480             String id1 = getStringAttr(surfaceElem, "vtxIdRef1");\r
481             String id2 = getStringAttr(surfaceElem, "vtxIdRef2");\r
482             String id3 = getStringAttr(surfaceElem, "vtxIdRef3");\r
483 \r
484             Vertex vertex1 = this.vertexMap.get(id1);\r
485             Vertex vertex2 = this.vertexMap.get(id2);\r
486             Vertex vertex3 = this.vertexMap.get(id3);\r
487 \r
488             surface.setTriangle(vertex1, vertex2, vertex3);\r
489         }\r
490 \r
491         return result;\r
492     }\r
493 \r
494     private void buildMaterialList(Element pmdModelElem)\r
495             throws TogaXmlException{\r
496         Element materialListElem =\r
497                 getChild(pmdModelElem, "materialList");\r
498 \r
499         List<Surface> surfaceList = this.model.getSurfaceList();\r
500         List<Material> materialList = this.model.getMaterialList();\r
501 \r
502         for(Element materialElem : eachChild(materialListElem, "material")){\r
503             Material material = new Material();\r
504             materialList.add(material);\r
505 \r
506             material.getShadeInfo().setToonMap(this.model.getToonMap());\r
507 \r
508             String surfaceGroupId =\r
509                     getStringAttr(materialElem, "surfaceGroupIdRef");\r
510             List<Surface> surfaceGroup =\r
511                     this.surfaceGroupMap.get(surfaceGroupId);\r
512             surfaceList.addAll(surfaceGroup);\r
513             material.getSurfaceList().addAll(surfaceGroup);\r
514 \r
515             boolean hasEdge = getBooleanAttr(materialElem, "showEdge");\r
516             material.setEdgeAppearance(hasEdge);\r
517 \r
518             ShadeInfo shadeInfo = material.getShadeInfo();\r
519 \r
520             int toonIdx;\r
521             if(hasChild(materialElem, "toon")){\r
522                 Element toonElem = getChild(materialElem, "toon");\r
523                 String toonId = getStringAttr(toonElem, "toonFileIdRef");\r
524                 toonIdx = this.toonIdxMap.get(toonId);\r
525             }else{\r
526                 toonIdx = 255;\r
527             }\r
528             shadeInfo.setToonIndex(toonIdx);\r
529 \r
530             if(hasChild(materialElem, "textureFile")){\r
531                 Element textureFileElem =\r
532                         getChild(materialElem, "textureFile");\r
533                 String textureFile =\r
534                         getSjisFileNameAttr(textureFileElem, "winFileName");\r
535                 shadeInfo.setTextureFileName(textureFile);\r
536             }\r
537 \r
538             if(hasChild(materialElem, "spheremapFile")){\r
539                 Element spheremapFileElem =\r
540                         getChild(materialElem, "spheremapFile");\r
541                 String spheremapFile =\r
542                         getSjisFileNameAttr(spheremapFileElem, "winFileName");\r
543                 shadeInfo.setSpheremapFileName(spheremapFile);\r
544             }\r
545 \r
546             float red;\r
547             float green;\r
548             float blue;\r
549 \r
550             Element diffuseElem = getChild(materialElem, "diffuse");\r
551             red   = getFloatAttr(diffuseElem, "r");\r
552             green = getFloatAttr(diffuseElem, "g");\r
553             blue  = getFloatAttr(diffuseElem, "b");\r
554             float alpha = getFloatAttr(diffuseElem, "alpha");\r
555             Color diffuse = new Color(red, green, blue, alpha);\r
556             material.setDiffuseColor(diffuse);\r
557 \r
558             Element specularElem = getChild(materialElem, "specular");\r
559             red   = getFloatAttr(specularElem, "r");\r
560             green = getFloatAttr(specularElem, "g");\r
561             blue  = getFloatAttr(specularElem, "b");\r
562             float shininess = getFloatAttr(specularElem, "shininess");\r
563             Color specular = new Color(red, green, blue);\r
564             material.setSpecularColor(specular);\r
565             material.setShininess(shininess);\r
566 \r
567             Element ambientElem = getChild(materialElem, "ambient");\r
568             red   = getFloatAttr(ambientElem, "r");\r
569             green = getFloatAttr(ambientElem, "g");\r
570             blue  = getFloatAttr(ambientElem, "b");\r
571             Color ambient = new Color(red, green, blue);\r
572             material.setAmbientColor(ambient);\r
573         }\r
574 \r
575         return;\r
576     }\r
577 \r
578     private void buildIkChainList(Element pmdModelElem)\r
579             throws TogaXmlException{\r
580         Element ikChainListElem =\r
581                 getChild(pmdModelElem, "ikChainList");\r
582 \r
583         List<IKChain> ikChainList = this.model.getIKChainList();\r
584 \r
585         for(Element ikChainElem : eachChild(ikChainListElem, "ikChain")){\r
586             IKChain ikChain = new IKChain();\r
587             ikChainList.add(ikChain);\r
588 \r
589             String ikBoneIdRef = getStringAttr(ikChainElem, "ikBoneIdRef");\r
590             int rucursiveDepth = getIntegerAttr(ikChainElem, "recursiveDepth");\r
591             float weight = getFloatAttr(ikChainElem, "weight");\r
592 \r
593             BoneInfo ikBone = this.boneMap.get(ikBoneIdRef);\r
594             ikChain.setIkBone(ikBone);\r
595             ikChain.setIKDepth(rucursiveDepth);\r
596             ikChain.setIKWeight(weight);\r
597 \r
598             List<BoneInfo> chainList = ikChain.getChainedBoneList();\r
599 \r
600             for(Element orderElem : eachChild(ikChainElem, "chainOrder")){\r
601                 String boneIdRef = getStringAttr(orderElem, "boneIdRef");\r
602                 BoneInfo chaindBone = this.boneMap.get(boneIdRef);\r
603                 chainList.add(chaindBone);\r
604             }\r
605         }\r
606 \r
607         return;\r
608     }\r
609 \r
610     private void buildMorphList(Element pmdModelElem)\r
611             throws TogaXmlException{\r
612         Element morphListElem =\r
613                 getChild(pmdModelElem, "morphList");\r
614 \r
615         Map<MorphType, List<MorphPart>> morphMap = this.model.getMorphMap();\r
616 \r
617         for(Element morphElem : eachChild(morphListElem, "morph")){\r
618             MorphPart morphPart = new MorphPart();\r
619 \r
620             I18nText name = morphPart.getMorphName();\r
621             buildI18nName(morphElem, name);\r
622 \r
623             String type = getStringAttr(morphElem, "type");\r
624             MorphType morphType = MorphType.valueOf(type);\r
625             morphPart.setMorphType(morphType);\r
626 \r
627             List<MorphVertex> morphVertexList = morphPart.getMorphVertexList();\r
628 \r
629             for(Element morphVertexElem : eachChild(morphElem, "morphVertex")){\r
630                 String vtxIdRef = getStringAttr(morphVertexElem, "vtxIdRef");\r
631                 Vertex baseVertex = this.vertexMap.get(vtxIdRef);\r
632                 float xOff = getFloatAttr(morphVertexElem, "xOff");\r
633                 float yOff = getFloatAttr(morphVertexElem, "yOff");\r
634                 float zOff = getFloatAttr(morphVertexElem, "zOff");\r
635 \r
636                 MorphVertex morphVertex = new MorphVertex();\r
637                 morphVertex.setBaseVertex(baseVertex);\r
638                 Pos3d position = morphVertex.getOffset();\r
639                 position.setXPos(xOff);\r
640                 position.setYPos(yOff);\r
641                 position.setZPos(zOff);\r
642 \r
643                 morphVertexList.add(morphVertex);\r
644             }\r
645 \r
646             morphMap.get(morphType).add(morphPart);\r
647         }\r
648 \r
649         List<MorphPart> serialList = new LinkedList<MorphPart>();\r
650         MorphPart baseDummy = new MorphPart();\r
651         serialList.add(baseDummy);\r
652         for(MorphPart part : morphMap.get(MorphType.EYEBROW)){\r
653             serialList.add(part);\r
654         }\r
655         for(MorphPart part : morphMap.get(MorphType.EYE)){\r
656             serialList.add(part);\r
657         }\r
658         for(MorphPart part : morphMap.get(MorphType.LIP)){\r
659             serialList.add(part);\r
660         }\r
661         for(MorphPart part : morphMap.get(MorphType.EXTRA)){\r
662             serialList.add(part);\r
663         }\r
664         ListUtil.assignIndexedSerial(serialList);\r
665 \r
666         return;\r
667     }\r
668 \r
669     private void buildBoneGroupList(Element pmdModelElem)\r
670             throws TogaXmlException{\r
671         Element boneGroupListElem =\r
672                 getChild(pmdModelElem, "boneGroupList");\r
673 \r
674         List<BoneGroup> boneGroupList = this.model.getBoneGroupList();\r
675         BoneGroup defaultGroup = new BoneGroup();\r
676         boneGroupList.add(defaultGroup);\r
677 \r
678         for(Element boneGroupElem : eachChild(boneGroupListElem, "boneGroup")){\r
679             BoneGroup group = new BoneGroup();\r
680             boneGroupList.add(group);\r
681 \r
682             I18nText name = group.getGroupName();\r
683             buildI18nName(boneGroupElem, name);\r
684 \r
685             for(Element boneGroupMemberElem : eachChild(boneGroupElem, "boneGroupMember")){\r
686                 String boneIdRef = getStringAttr(boneGroupMemberElem, "boneIdRef");\r
687                 BoneInfo bone = this.boneMap.get(boneIdRef);\r
688                 group.getBoneList().add(bone);\r
689             }\r
690         }\r
691 \r
692         ListUtil.assignIndexedSerial(boneGroupList);\r
693 \r
694         return;\r
695     }\r
696 \r
697     private void buildRigidList(Element pmdModelElem)\r
698             throws TogaXmlException{\r
699         Element rigidListElem =\r
700                 getChild(pmdModelElem, "rigidList");\r
701 \r
702         List<RigidInfo> rigidList = this.model.getRigidList();\r
703 \r
704         for(Element rigidElem : eachChild(rigidListElem, "rigid")){\r
705             RigidInfo rigid = new RigidInfo();\r
706             rigidList.add(rigid);\r
707 \r
708             I18nText name = rigid.getRigidName();\r
709             buildI18nName(rigidElem, name);\r
710 \r
711             String behavior = getStringAttr(rigidElem, "behavior");\r
712             RigidBehaviorType type = RigidBehaviorType.valueOf(behavior);\r
713             rigid.setBehaviorType(type);\r
714 \r
715             String rigidId = getStringAttr(rigidElem, "rigidId");\r
716             this.rigidMap.put(rigidId, rigid);\r
717 \r
718             Element linkedBoneElem = getChild(rigidElem, "linkedBone");\r
719             String boneIdRef = getStringAttr(linkedBoneElem, "boneIdRef");\r
720             BoneInfo linkedBone = this.boneMap.get(boneIdRef);\r
721             rigid.setLinkedBone(linkedBone);\r
722 \r
723             RigidShape rigidShape = rigid.getRigidShape();\r
724             if(hasChild(rigidElem, "rigidShapeSphere")){\r
725                 Element shapeElem =\r
726                         getChild(rigidElem, "rigidShapeSphere");\r
727                 float radius = getFloatAttr(shapeElem, "radius");\r
728                 rigidShape.setShapeType(RigidShapeType.SPHERE);\r
729                 rigidShape.setRadius(radius);\r
730             }\r
731             if(hasChild(rigidElem, "rigidShapeBox")){\r
732                 Element shapeElem =\r
733                         getChild(rigidElem, "rigidShapeBox");\r
734                 float width  = getFloatAttr(shapeElem, "width");\r
735                 float height = getFloatAttr(shapeElem, "height");\r
736                 float depth  = getFloatAttr(shapeElem, "depth");\r
737                 rigidShape.setShapeType(RigidShapeType.BOX);\r
738                 rigidShape.setWidth(width);\r
739                 rigidShape.setHeight(height);\r
740                 rigidShape.setDepth(depth);\r
741             }\r
742             if(hasChild(rigidElem, "rigidShapeCapsule")){\r
743                 Element shapeElem =\r
744                         getChild(rigidElem, "rigidShapeCapsule");\r
745                 float height = getFloatAttr(shapeElem, "height");\r
746                 float radius = getFloatAttr(shapeElem, "radius");\r
747                 rigidShape.setShapeType(RigidShapeType.CAPSULE);\r
748                 rigidShape.setHeight(height);\r
749                 rigidShape.setRadius(radius);\r
750             }\r
751 \r
752             float xVal;\r
753             float yVal;\r
754             float zVal;\r
755 \r
756             Element positionElem = getChild(rigidElem, "position");\r
757             xVal = getFloatAttr(positionElem, "x");\r
758             yVal = getFloatAttr(positionElem, "y");\r
759             zVal = getFloatAttr(positionElem, "z");\r
760             Pos3d position = rigid.getPosition();\r
761             position.setXPos(xVal);\r
762             position.setYPos(yVal);\r
763             position.setZPos(zVal);\r
764 \r
765             Element radRotationElem = getChild(rigidElem, "radRotation");\r
766             xVal = getFloatAttr(radRotationElem, "xRad");\r
767             yVal = getFloatAttr(radRotationElem, "yRad");\r
768             zVal = getFloatAttr(radRotationElem, "zRad");\r
769             Rad3d rotation = rigid.getRotation();\r
770             rotation.setXRad(xVal);\r
771             rotation.setYRad(yVal);\r
772             rotation.setZRad(zVal);\r
773 \r
774             Element dynamicsElem = getChild(rigidElem, "dynamics");\r
775             float mass = getFloatAttr(dynamicsElem, "mass");\r
776             float dampingPosition = getFloatAttr(dynamicsElem, "dampingPosition");\r
777             float dampingRotation = getFloatAttr(dynamicsElem, "dampingRotation");\r
778             float restitution = getFloatAttr(dynamicsElem, "restitution");\r
779             float friction = getFloatAttr(dynamicsElem, "friction");\r
780             DynamicsInfo dynamics = rigid.getDynamicsInfo();\r
781             dynamics.setMass(mass);\r
782             dynamics.setDampingPosition(dampingPosition);\r
783             dynamics.setDampingRotation(dampingRotation);\r
784             dynamics.setRestitution(restitution);\r
785             dynamics.setFriction(friction);\r
786         }\r
787 \r
788         ListUtil.assignIndexedSerial(rigidList);\r
789 \r
790         return;\r
791     }\r
792 \r
793     private void buildRigidGroupList(Element pmdModelElem)\r
794             throws TogaXmlException{\r
795         Element rigidGroupListElem =\r
796                 getChild(pmdModelElem, "rigidGroupList");\r
797 \r
798         List<RigidGroup> groupList = this.model.getRigidGroupList();\r
799 \r
800         for(Element rigidGroupElem : eachChild(rigidGroupListElem, "rigidGroup")){\r
801             RigidGroup rigidGroup = new RigidGroup();\r
802             groupList.add(rigidGroup);\r
803 \r
804             String rigidGroupId = getStringAttr(rigidGroupElem, "rigidGroupId");\r
805             this.rigidGroupMap.put(rigidGroupId, rigidGroup);\r
806 \r
807             for(Element memberElem : eachChild(rigidGroupElem, "rigidGroupMember")){\r
808                 String rigidIdRef = getStringAttr(memberElem, "rigidIdRef");\r
809                 RigidInfo rigid = this.rigidMap.get(rigidIdRef);\r
810                 rigidGroup.getRigidList().add(rigid);\r
811                 rigid.setRigidGroup(rigidGroup);\r
812             }\r
813         }\r
814 \r
815         while(groupList.size() < 16){\r
816             RigidGroup rigidGroup = new RigidGroup();\r
817             groupList.add(rigidGroup);\r
818         }\r
819 \r
820         ListUtil.assignIndexedSerial(groupList);\r
821 \r
822         return;\r
823     }\r
824 \r
825     private void resolveThroughRigidGroup(Element pmdModelElem)\r
826             throws TogaXmlException{\r
827         Element rigidListElem =\r
828                 getChild(pmdModelElem, "rigidList");\r
829 \r
830         List<RigidInfo> rigidList = this.model.getRigidList();\r
831 \r
832         int serialNum = 0;\r
833         for(Element rigidElem : eachChild(rigidListElem, "rigid")){\r
834             RigidInfo rigid = rigidList.get(serialNum++);\r
835             for(Element groupElem : eachChild(rigidElem, "throughRigidGroup")){\r
836                 String groupId = getStringAttr(groupElem, "rigidGroupIdRef");\r
837                 RigidGroup group = this.rigidGroupMap.get(groupId);\r
838                 rigid.getThroughGroupColl().add(group);\r
839             }\r
840         }\r
841 \r
842         return;\r
843     }\r
844 \r
845     private void buildJointList(Element pmdModelElem)\r
846             throws TogaXmlException{\r
847         Element jointListElem =\r
848                 getChild(pmdModelElem, "jointList");\r
849 \r
850         List<JointInfo> jointList = this.model.getJointList();\r
851 \r
852         for(Element jointElem : eachChild(jointListElem, "joint")){\r
853             JointInfo joint = new JointInfo();\r
854             jointList.add(joint);\r
855 \r
856             I18nText name = joint.getJointName();\r
857             buildI18nName(jointElem, name);\r
858 \r
859             Element rigidPairElem = getChild(jointElem, "jointedRigidPair");\r
860             String rigidIdRef1 = getStringAttr(rigidPairElem, "rigidIdRef1");\r
861             String rigidIdRef2 = getStringAttr(rigidPairElem, "rigidIdRef2");\r
862             RigidInfo rigid1 = this.rigidMap.get(rigidIdRef1);\r
863             RigidInfo rigid2 = this.rigidMap.get(rigidIdRef2);\r
864             joint.setRigidPair(rigid1, rigid2);\r
865 \r
866             float xVal;\r
867             float yVal;\r
868             float zVal;\r
869             float xFrom;\r
870             float xTo;\r
871             float yFrom;\r
872             float yTo;\r
873             float zFrom;\r
874             float zTo;\r
875 \r
876             Pos3d position = joint.getPosition();\r
877             Element positionElem = getChild(jointElem, "position");\r
878             xVal = getFloatAttr(positionElem, "x");\r
879             yVal = getFloatAttr(positionElem, "y");\r
880             zVal = getFloatAttr(positionElem, "z");\r
881             position.setXPos(xVal);\r
882             position.setYPos(yVal);\r
883             position.setZPos(zVal);\r
884 \r
885             TripletRange limitPosition = joint.getPositionRange();\r
886             Element limitPositionElem = getChild(jointElem, "limitPosition");\r
887             xFrom = getFloatAttr(limitPositionElem, "xFrom");\r
888             xTo   = getFloatAttr(limitPositionElem, "xTo");\r
889             yFrom = getFloatAttr(limitPositionElem, "yFrom");\r
890             yTo   = getFloatAttr(limitPositionElem, "yTo");\r
891             zFrom = getFloatAttr(limitPositionElem, "zFrom");\r
892             zTo   = getFloatAttr(limitPositionElem, "zTo");\r
893             limitPosition.setXRange(xFrom, xTo);\r
894             limitPosition.setYRange(yFrom, yTo);\r
895             limitPosition.setZRange(zFrom, zTo);\r
896 \r
897             Rad3d rotation = joint.getRotation();\r
898             Element rotationElem = getChild(jointElem, "radRotation");\r
899             xVal = getFloatAttr(rotationElem, "xRad");\r
900             yVal = getFloatAttr(rotationElem, "yRad");\r
901             zVal = getFloatAttr(rotationElem, "zRad");\r
902             rotation.setXRad(xVal);\r
903             rotation.setYRad(yVal);\r
904             rotation.setZRad(zVal);\r
905 \r
906             TripletRange limitRotation = joint.getRotationRange();\r
907             Element limitRotationElem = getChild(jointElem, "limitRotation");\r
908             xFrom = getFloatAttr(limitRotationElem, "xFrom");\r
909             xTo   = getFloatAttr(limitRotationElem, "xTo");\r
910             yFrom = getFloatAttr(limitRotationElem, "yFrom");\r
911             yTo   = getFloatAttr(limitRotationElem, "yTo");\r
912             zFrom = getFloatAttr(limitRotationElem, "zFrom");\r
913             zTo   = getFloatAttr(limitRotationElem, "zTo");\r
914             limitRotation.setXRange(xFrom, xTo);\r
915             limitRotation.setYRange(yFrom, yTo);\r
916             limitRotation.setZRange(zFrom, zTo);\r
917 \r
918             Pos3d elasticPosition = joint.getElasticPosition();\r
919             Element elasticPositionElem = getChild(jointElem, "elasticPosition");\r
920             xVal = getFloatAttr(elasticPositionElem, "x");\r
921             yVal = getFloatAttr(elasticPositionElem, "y");\r
922             zVal = getFloatAttr(elasticPositionElem, "z");\r
923             elasticPosition.setXPos(xVal);\r
924             elasticPosition.setYPos(yVal);\r
925             elasticPosition.setZPos(zVal);\r
926 \r
927             Deg3d elasticRotation = joint.getElasticRotation();\r
928             Element elasticRotationElem = getChild(jointElem, "elasticRotation");\r
929             xVal = getFloatAttr(elasticRotationElem, "xDeg");\r
930             yVal = getFloatAttr(elasticRotationElem, "yDeg");\r
931             zVal = getFloatAttr(elasticRotationElem, "zDeg");\r
932             elasticRotation.setXDeg(xVal);\r
933             elasticRotation.setYDeg(yVal);\r
934             elasticRotation.setZDeg(zVal);\r
935         }\r
936 \r
937         return;\r
938     }\r
939 \r
940 }\r