4 * License : The MIT License
5 * Copyright(c) 2010 MikuToga Partners
8 package jp.sfjp.mikutoga.pmd.xml;
10 import java.awt.Color;
11 import java.io.IOException;
12 import java.text.MessageFormat;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.LinkedList;
17 import java.util.List;
19 import javax.xml.parsers.DocumentBuilder;
20 import jp.sfjp.mikutoga.corelib.I18nText;
21 import jp.sfjp.mikutoga.math.MkPos2D;
22 import jp.sfjp.mikutoga.math.MkPos3D;
23 import jp.sfjp.mikutoga.math.MkVec3D;
24 import jp.sfjp.mikutoga.pmd.BoneType;
25 import jp.sfjp.mikutoga.pmd.Deg3d;
26 import jp.sfjp.mikutoga.pmd.MorphType;
27 import jp.sfjp.mikutoga.pmd.Rad3d;
28 import jp.sfjp.mikutoga.pmd.RigidBehaviorType;
29 import jp.sfjp.mikutoga.pmd.RigidShapeType;
30 import jp.sfjp.mikutoga.pmd.TripletRange;
31 import jp.sfjp.mikutoga.pmd.model.BoneGroup;
32 import jp.sfjp.mikutoga.pmd.model.BoneInfo;
33 import jp.sfjp.mikutoga.pmd.model.DynamicsInfo;
34 import jp.sfjp.mikutoga.pmd.model.IKChain;
35 import jp.sfjp.mikutoga.pmd.model.JointInfo;
36 import jp.sfjp.mikutoga.pmd.model.ListUtil;
37 import jp.sfjp.mikutoga.pmd.model.Material;
38 import jp.sfjp.mikutoga.pmd.model.MorphPart;
39 import jp.sfjp.mikutoga.pmd.model.MorphVertex;
40 import jp.sfjp.mikutoga.pmd.model.PmdModel;
41 import jp.sfjp.mikutoga.pmd.model.RigidGroup;
42 import jp.sfjp.mikutoga.pmd.model.RigidInfo;
43 import jp.sfjp.mikutoga.pmd.model.RigidShape;
44 import jp.sfjp.mikutoga.pmd.model.ShadeInfo;
45 import jp.sfjp.mikutoga.pmd.model.Surface;
46 import jp.sfjp.mikutoga.pmd.model.ToonMap;
47 import jp.sfjp.mikutoga.pmd.model.Vertex;
48 import jp.sourceforge.mikutoga.xml.DomNsUtils;
49 import jp.sourceforge.mikutoga.xml.DomUtils;
50 import jp.sourceforge.mikutoga.xml.TogaXmlException;
51 import org.w3c.dom.Document;
52 import org.w3c.dom.Element;
53 import org.w3c.dom.Node;
54 import org.xml.sax.InputSource;
55 import org.xml.sax.SAXException;
58 * XML形式でのモデルファイルを読み込む。
60 public class XmlLoader {
62 private static final String ERR_INVROOT =
63 "invalid root element[{0}]";
64 private static final String ERR_UKVER =
65 "unknown schema version[{0}]";
68 private PmdModel model;
70 private final Map<String, Integer> toonIdxMap =
71 new HashMap<String, Integer>();
72 private final Map<String, BoneInfo> boneMap =
73 new HashMap<String, BoneInfo>();
74 private final Map<String, Vertex> vertexMap =
75 new HashMap<String, Vertex>();
76 private final Map<String, List<Surface>> surfaceGroupMap =
77 new HashMap<String, List<Surface>>();
78 private final Map<String, RigidInfo> rigidMap =
79 new HashMap<String, RigidInfo>();
80 private final Map<String, RigidGroup> rigidGroupMap =
81 new HashMap<String, RigidGroup>();
83 private String rootNamespace = Schema130128.NS_PMDXML;
84 private XmlModelFileType fileType = XmlModelFileType.XML_AUTO;
97 * 要素からxsd:string型属性値を読み取る。
101 * @throws TogaXmlException 属性値が見つからなかった。
103 private static String getStringAttr(Element elem, String attrName)
104 throws TogaXmlException{
105 return DomUtils.getStringAttr(elem, attrName);
109 * 要素からxsd:boolean型属性値を読み取る。
111 * @param attrName 属性名
113 * @throws TogaXmlException 属性値が見つからなかった。
115 private static boolean getBooleanAttr(Element elem, String attrName)
116 throws TogaXmlException{
117 return DomUtils.getBooleanAttr(elem, attrName);
121 * 要素からxsd:integer型属性値を読み取る。
123 * @param attrName 属性名
125 * @throws TogaXmlException 属性値が見つからなかった。
127 private static int getIntegerAttr(Element elem, String attrName)
128 throws TogaXmlException{
129 return DomUtils.getIntegerAttr(elem, attrName);
133 * 要素からxsd:float型属性値を読み取る。
135 * @param attrName 属性名
137 * @throws TogaXmlException 属性値が見つからなかった。
139 private static float getFloatAttr(Element elem, String attrName)
140 throws TogaXmlException{
141 return DomUtils.getFloatAttr(elem, attrName);
145 * 要素から日本語Windows用ファイル名を属性値として読み取る。
146 * 念のため文字U+00A5は文字U-005Cに変換される。
148 * @param attrName 属性名
150 * @throws TogaXmlException 属性値が見つからなかった。
152 private static String getSjisFileNameAttr(Element elem, String attrName)
153 throws TogaXmlException{
154 return DomUtils.getSjisFileNameAttr(elem, attrName);
158 * brタグで区切られた文字列内容(Mixed content)を
160 * brタグはその出現回数だけ\nに変換される。
161 * 生文字列コンテンツ中の\n,\rは削除される。
162 * 改行文字以外のホワイトスペースは保持される。
163 * @param parent br要素及び文字列コンテンツを含む要素
166 private static String getBRedContent(Element parent){
167 StringBuilder result = new StringBuilder();
169 for(Node node = parent.getFirstChild();
171 node = node.getNextSibling() ){
173 switch(node.getNodeType()){
174 case Node.ELEMENT_NODE:
175 Element elem = (Element) node;
176 if("br".equals(elem.getTagName())){
181 case Node.CDATA_SECTION_NODE:
182 String content = node.getTextContent();
183 content = content.replace("\r", "");
184 content = content.replace("\n", "");
185 result.append(content);
192 return result.toString();
200 private XmlModelFileType getFileType(){
201 return this.fileType;
205 * パース中のXMLファイル種別を設定する。
206 * @param type 具体的なファイル種別
208 private void setFileType(XmlModelFileType type){
209 if( type != XmlModelFileType.XML_101009
210 && type != XmlModelFileType.XML_130128 ){
211 throw new IllegalArgumentException();
213 this.fileType = type;
219 * @return 名前空間URI。nullなら名前空間が無いと見なされる
221 private String getRootNamespace(){
222 return this.rootNamespace;
226 * ルート要素の名前空間URIを設定する。
227 * @param name 名前空間URI。nullなら名前空間が無いと見なされる
229 private void setRootNamespace(String name){
230 this.rootNamespace = name;
235 * 指定された名前の子要素を1つだけ返す。
237 * @param tagName 子要素名
239 * @throws TogaXmlException 1つも見つからなかった
241 private Element getChild(Element parent, String tagName)
242 throws TogaXmlException{
243 String ns = getRootNamespace();
244 Element result = DomNsUtils.getFirstChild(parent, ns, tagName);
249 * 親要素が指定された名前の子要素を持つか判定する。
251 * @param tagName 子要素名
252 * @return 指定名の子要素が存在すればtrue
254 private boolean hasChild(Element parent, String tagName){
255 String ns = getRootNamespace();
256 return DomNsUtils.hasChild(parent, ns, tagName);
260 * 指定された名前の子要素のforeachを返す。
262 * @param childTag 子要素名
263 * @return 子要素のforeach
265 private Iterable<Element> eachChild(Element parent,
267 String ns = getRootNamespace();
268 return DomNsUtils.getEachChild(parent, ns, childTag);
273 * @param baseElement 元要素
274 * @param text 多言語名格納先
275 * @throws TogaXmlException あるべき属性が存在しない。
277 private void buildI18nName(Element baseElement, I18nText text)
278 throws TogaXmlException{
280 primaryText = getStringAttr(baseElement, "name");
281 text.setPrimaryText(primaryText);
283 for(Element i18nNameElem : eachChild(baseElement, "i18nName")){
284 String lang = getStringAttr(i18nNameElem, "lang");
285 String name = getStringAttr(i18nNameElem, "name");
286 if("en".equals(lang)){
287 text.setGlobalText(name);
289 text.setI18nText(lang, text);
298 * @param builder ドキュメントビルダ
299 * @param source XML入力
301 * @throws SAXException 構文エラー
302 * @throws IOException 入力エラー
303 * @throws TogaXmlException 構文エラー
305 public PmdModel parse(DocumentBuilder builder, InputSource source)
306 throws SAXException, IOException, TogaXmlException{
307 Document document = builder.parse(source);
308 PmdModel result = parse(document);
314 * @param document DOMドキュメント
316 * @throws TogaXmlException 構文エラー
318 public PmdModel parse(Document document)
319 throws TogaXmlException{
320 this.model = new PmdModel();
322 Element pmdModelElem = document.getDocumentElement();
323 String namespace = pmdModelElem.getNamespaceURI();
324 setRootNamespace(namespace);
326 buildBasicInfo(pmdModelElem);
328 buildBoneList(pmdModelElem);
329 buildVertexList(pmdModelElem);
330 buildSurfaceList(pmdModelElem);
332 buildToonMap(pmdModelElem);
333 buildMaterialList(pmdModelElem);
334 buildIkChainList(pmdModelElem);
335 buildMorphList(pmdModelElem);
336 buildBoneGroupList(pmdModelElem);
338 buildRigidList(pmdModelElem);
339 buildRigidGroupList(pmdModelElem);
340 resolveThroughRigidGroup(pmdModelElem);
342 buildJointList(pmdModelElem);
348 * DOMからモデル基本情報を組み立てる。
349 * @param pmdModelElem ルート要素
350 * @throws TogaXmlException 構文エラー
352 private void buildBasicInfo(Element pmdModelElem)
353 throws TogaXmlException{
354 if( ! DomNsUtils.hasNsLocalNameElem(pmdModelElem,
357 String tagName = pmdModelElem.getTagName();
358 String msg = MessageFormat.format(ERR_INVROOT, tagName);
359 throw new TogaXmlException(msg);
362 String version = getStringAttr(pmdModelElem, "schemaVersion");
363 if(Schema101009.VER_PMDXML.equals(version)){
364 setFileType(XmlModelFileType.XML_101009);
365 }else if(Schema130128.VER_PMDXML.equals(version)){
366 setFileType(XmlModelFileType.XML_130128);
368 String msg = MessageFormat.format(ERR_UKVER, version);
369 throw new TogaXmlException(msg);
372 I18nText modelName = this.model.getModelName();
373 buildI18nName(pmdModelElem, modelName);
375 String primaryDescription = null;
376 String globalDescription = null;
377 for(Element descriptionElem :
378 eachChild(pmdModelElem, "description")){
379 String descriptionText = getBRedContent(descriptionElem);
380 if( ! descriptionElem.hasAttribute("lang") ){
381 primaryDescription = descriptionText;
383 String lang = getStringAttr(descriptionElem, "lang");
384 if(lang.equals("ja")){
385 primaryDescription = descriptionText;
386 }else if(lang.equals("en")){
387 globalDescription = descriptionText;
392 I18nText description = this.model.getDescription();
393 description.setPrimaryText(primaryDescription);
394 description.setGlobalText(globalDescription);
400 * DOMからボーンリスト情報を組み立てる。
401 * @param pmdModelElem ルート要素
402 * @throws TogaXmlException 構文エラー
404 private void buildBoneList(Element pmdModelElem)
405 throws TogaXmlException{
406 Element boneListElem = getChild(pmdModelElem, "boneList");
408 List<BoneInfo> boneList = this.model.getBoneList();
410 for(Element boneElem : eachChild(boneListElem, "bone")){
411 BoneInfo boneInfo = new BoneInfo();
412 boneList.add(boneInfo);
414 I18nText boneName = boneInfo.getBoneName();
415 buildI18nName(boneElem, boneName);
417 String boneType = getStringAttr(boneElem, "type");
418 BoneType type = BoneType.valueOf(boneType);
419 boneInfo.setBoneType(type);
421 String boneId = getStringAttr(boneElem, "boneId");
422 this.boneMap.put(boneId, boneInfo);
424 Element positionElem = getChild(boneElem, "position");
425 float xPos = getFloatAttr(positionElem, "x");
426 float yPos = getFloatAttr(positionElem, "y");
427 float zPos = getFloatAttr(positionElem, "z");
428 MkPos3D position = boneInfo.getPosition();
429 position.setXpos(xPos);
430 position.setYpos(yPos);
431 position.setZpos(zPos);
434 ListUtil.assignIndexedSerial(boneList);
436 Iterator<BoneInfo> bit = boneList.iterator();
437 for(Element boneElem : eachChild(boneListElem, "bone")){
438 BoneInfo boneInfo = bit.next();
440 if(hasChild(boneElem, "ikBone")){ // 101009 only
441 Element ikBoneElem = getChild(boneElem, "ikBone");
442 String ikBoneId = getStringAttr(ikBoneElem, "boneIdRef");
443 BoneInfo ikBone = this.boneMap.get(ikBoneId);
444 boneInfo.setSrcBone(ikBone);
445 }else if(hasChild(boneElem, "sourceBone")){ // 130128 only
446 Element srcBoneElem = getChild(boneElem, "sourceBone");
447 String srcBoneId = getStringAttr(srcBoneElem, "boneIdRef");
448 BoneInfo srcBone = this.boneMap.get(srcBoneId);
449 boneInfo.setSrcBone(srcBone);
450 }else if(hasChild(boneElem, "rotationRatio")){
451 Element rotElem = getChild(boneElem, "rotationRatio");
452 int ratio = getIntegerAttr(rotElem, "ratio");
453 boneInfo.setRotationRatio(ratio);
456 Element boneChainElem = getChild(boneElem, "boneChain");
457 if(boneChainElem.hasAttribute("prevBoneIdRef")){
458 String prevId = getStringAttr(boneChainElem, "prevBoneIdRef");
459 BoneInfo prevBone = this.boneMap.get(prevId);
460 boneInfo.setPrevBone(prevBone);
462 if(boneChainElem.hasAttribute("nextBoneIdRef")){
463 String nextId = getStringAttr(boneChainElem, "nextBoneIdRef");
464 BoneInfo nextBone = this.boneMap.get(nextId);
465 boneInfo.setNextBone(nextBone);
473 * DOMから頂点リスト情報を組み立てる。
474 * @param pmdModelElem ルート要素
475 * @throws TogaXmlException 構文エラー
477 private void buildVertexList(Element pmdModelElem)
478 throws TogaXmlException{
479 Element vertexListElem = getChild(pmdModelElem, "vertexList");
481 List<Vertex> vertexList = this.model.getVertexList();
483 for(Element vertexElem : eachChild(vertexListElem, "vertex")){
484 Vertex vertex = new Vertex();
485 vertexList.add(vertex);
487 String vertexId = getStringAttr(vertexElem, "vtxId");
488 this.vertexMap.put(vertexId, vertex);
490 boolean showEdge = getBooleanAttr(vertexElem, "showEdge");
491 vertex.setEdgeAppearance(showEdge);
497 Element positionElem = getChild(vertexElem, "position");
498 xVal = getFloatAttr(positionElem, "x");
499 yVal = getFloatAttr(positionElem, "y");
500 zVal = getFloatAttr(positionElem, "z");
501 MkPos3D position = vertex.getPosition();
502 position.setXpos(xVal);
503 position.setYpos(yVal);
504 position.setZpos(zVal);
506 Element normalElem = getChild(vertexElem, "normal");
507 xVal = getFloatAttr(normalElem, "x");
508 yVal = getFloatAttr(normalElem, "y");
509 zVal = getFloatAttr(normalElem, "z");
510 MkVec3D normal = vertex.getNormal();
511 normal.setXVal(xVal);
512 normal.setYVal(yVal);
513 normal.setZVal(zVal);
515 Element uvElem = getChild(vertexElem, "uvMap");
516 float uVal = getFloatAttr(uvElem, "u");
517 float vVal = getFloatAttr(uvElem, "v");
518 MkPos2D uv = vertex.getUVPosition();
522 Element skinningElem = getChild(vertexElem, "skinning");
523 String boneId1 = getStringAttr(skinningElem, "boneIdRef1");
524 String boneId2 = getStringAttr(skinningElem, "boneIdRef2");
525 int weight = getIntegerAttr(skinningElem, "weightBalance");
526 BoneInfo boneA = this.boneMap.get(boneId1);
527 BoneInfo boneB = this.boneMap.get(boneId2);
528 vertex.setBonePair(boneA, boneB);
529 vertex.setWeightA(weight);
532 ListUtil.assignIndexedSerial(vertexList);
538 * DOMからポリゴンリスト情報を組み立てる。
539 * @param pmdModelElem ルート要素
540 * @throws TogaXmlException 構文エラー
542 private void buildSurfaceList(Element pmdModelElem)
543 throws TogaXmlException{
544 Element surfaceGroupListElem =
545 getChild(pmdModelElem, "surfaceGroupList");
547 for(Element surfaceGroupElem :
548 eachChild(surfaceGroupListElem, "surfaceGroup") ){
551 getStringAttr(surfaceGroupElem, "surfaceGroupId");
552 List<Surface> surfaceList = buildSurface(surfaceGroupElem);
554 this.surfaceGroupMap.put(groupId, surfaceList);
562 * @param surfaceGroupElem surfaceGroup要素
564 * @throws TogaXmlException 構文エラー
566 private List<Surface> buildSurface(Element surfaceGroupElem)
567 throws TogaXmlException{
568 List<Surface> result = new ArrayList<Surface>();
570 for(Element surfaceElem : eachChild(surfaceGroupElem, "surface")){
571 Surface surface = new Surface();
574 String id1 = getStringAttr(surfaceElem, "vtxIdRef1");
575 String id2 = getStringAttr(surfaceElem, "vtxIdRef2");
576 String id3 = getStringAttr(surfaceElem, "vtxIdRef3");
578 Vertex vertex1 = this.vertexMap.get(id1);
579 Vertex vertex2 = this.vertexMap.get(id2);
580 Vertex vertex3 = this.vertexMap.get(id3);
582 surface.setTriangle(vertex1, vertex2, vertex3);
589 * DOMからトゥーンマップ情報を組み立てる。
590 * @param pmdModelElem ルート要素
591 * @throws TogaXmlException 構文エラー
593 private void buildToonMap(Element pmdModelElem)
594 throws TogaXmlException{
595 ToonMap toonMap = this.model.getToonMap();
597 Element toonMapElem = getChild(pmdModelElem, "toonMap");
599 for(Element toonDefElem : eachChild(toonMapElem, "toonDef")){
600 String toonFileId = getStringAttr(toonDefElem, "toonFileId");
601 int toonIndex = getIntegerAttr(toonDefElem, "index");
602 String toonFile = getSjisFileNameAttr(toonDefElem, "winFileName");
604 toonMap.setIndexedToon(toonIndex, toonFile);
605 this.toonIdxMap.put(toonFileId, toonIndex);
612 * DOMからマテリアル情報を組み立てる。
613 * @param pmdModelElem ルート要素
614 * @throws TogaXmlException 構文エラー
616 private void buildMaterialList(Element pmdModelElem)
617 throws TogaXmlException{
618 Element materialListElem =
619 getChild(pmdModelElem, "materialList");
621 List<Surface> surfaceList = this.model.getSurfaceList();
622 List<Material> materialList = this.model.getMaterialList();
624 for(Element materialElem : eachChild(materialListElem, "material")){
625 Material material = new Material();
626 materialList.add(material);
628 material.getShadeInfo().setToonMap(this.model.getToonMap());
630 String surfaceGroupId =
631 getStringAttr(materialElem, "surfaceGroupIdRef");
632 List<Surface> surfaceGroup =
633 this.surfaceGroupMap.get(surfaceGroupId);
634 surfaceList.addAll(surfaceGroup);
635 material.getSurfaceList().addAll(surfaceGroup);
637 boolean hasEdge = getBooleanAttr(materialElem, "showEdge");
638 material.setEdgeAppearance(hasEdge);
640 ShadeInfo shadeInfo = material.getShadeInfo();
643 if(hasChild(materialElem, "toon")){
644 Element toonElem = getChild(materialElem, "toon");
645 String toonId = getStringAttr(toonElem, "toonFileIdRef");
646 toonIdx = this.toonIdxMap.get(toonId);
650 shadeInfo.setToonIndex(toonIdx);
652 if(hasChild(materialElem, "textureFile")){
653 Element textureFileElem =
654 getChild(materialElem, "textureFile");
656 getSjisFileNameAttr(textureFileElem, "winFileName");
657 shadeInfo.setTextureFileName(textureFile);
660 if(hasChild(materialElem, "spheremapFile")){
661 Element spheremapFileElem =
662 getChild(materialElem, "spheremapFile");
663 String spheremapFile =
664 getSjisFileNameAttr(spheremapFileElem, "winFileName");
665 shadeInfo.setSpheremapFileName(spheremapFile);
672 Element diffuseElem = getChild(materialElem, "diffuse");
673 red = getFloatAttr(diffuseElem, "r");
674 green = getFloatAttr(diffuseElem, "g");
675 blue = getFloatAttr(diffuseElem, "b");
676 float alpha = getFloatAttr(diffuseElem, "alpha");
677 Color diffuse = new Color(red, green, blue, alpha);
678 material.setDiffuseColor(diffuse);
680 Element specularElem = getChild(materialElem, "specular");
681 red = getFloatAttr(specularElem, "r");
682 green = getFloatAttr(specularElem, "g");
683 blue = getFloatAttr(specularElem, "b");
684 float shininess = getFloatAttr(specularElem, "shininess");
685 Color specular = new Color(red, green, blue);
686 material.setSpecularColor(specular);
687 material.setShininess(shininess);
689 Element ambientElem = getChild(materialElem, "ambient");
690 red = getFloatAttr(ambientElem, "r");
691 green = getFloatAttr(ambientElem, "g");
692 blue = getFloatAttr(ambientElem, "b");
693 Color ambient = new Color(red, green, blue);
694 material.setAmbientColor(ambient);
701 * DOMからIKチェーンリスト情報を組み立てる。
702 * @param pmdModelElem ルート要素
703 * @throws TogaXmlException 構文エラー
705 private void buildIkChainList(Element pmdModelElem)
706 throws TogaXmlException{
707 Element ikChainListElem =
708 getChild(pmdModelElem, "ikChainList");
710 List<IKChain> ikChainList = this.model.getIKChainList();
712 for(Element ikChainElem : eachChild(ikChainListElem, "ikChain")){
713 IKChain ikChain = new IKChain();
714 ikChainList.add(ikChain);
716 String ikBoneIdRef = getStringAttr(ikChainElem, "ikBoneIdRef");
718 getIntegerAttr(ikChainElem, "recursiveDepth");
719 float weight = getFloatAttr(ikChainElem, "weight");
721 BoneInfo ikBone = this.boneMap.get(ikBoneIdRef);
722 ikChain.setIkBone(ikBone);
723 ikChain.setIKDepth(rucursiveDepth);
724 ikChain.setIKWeight(weight);
726 List<BoneInfo> chainList = ikChain.getChainedBoneList();
728 for(Element orderElem : eachChild(ikChainElem, "chainOrder")){
729 String boneIdRef = getStringAttr(orderElem, "boneIdRef");
730 BoneInfo chaindBone = this.boneMap.get(boneIdRef);
731 chainList.add(chaindBone);
739 * DOMからモーフリスト情報を組み立てる。
740 * @param pmdModelElem ルート要素
741 * @throws TogaXmlException 構文エラー
743 private void buildMorphList(Element pmdModelElem)
744 throws TogaXmlException{
745 Element morphListElem =
746 getChild(pmdModelElem, "morphList");
748 Map<MorphType, List<MorphPart>> morphMap = this.model.getMorphMap();
750 for(Element morphElem : eachChild(morphListElem, "morph")){
751 MorphPart morphPart = new MorphPart();
753 I18nText name = morphPart.getMorphName();
754 buildI18nName(morphElem, name);
756 String type = getStringAttr(morphElem, "type");
757 MorphType morphType = MorphType.valueOf(type);
758 morphPart.setMorphType(morphType);
760 List<MorphVertex> morphVertexList =
761 morphPart.getMorphVertexList();
763 for(Element morphVertexElem
764 : eachChild(morphElem, "morphVertex")){
765 String vtxIdRef = getStringAttr(morphVertexElem, "vtxIdRef");
766 Vertex baseVertex = this.vertexMap.get(vtxIdRef);
767 float xOff = getFloatAttr(morphVertexElem, "xOff");
768 float yOff = getFloatAttr(morphVertexElem, "yOff");
769 float zOff = getFloatAttr(morphVertexElem, "zOff");
771 MorphVertex morphVertex = new MorphVertex();
772 morphVertex.setBaseVertex(baseVertex);
773 MkPos3D position = morphVertex.getOffset();
774 position.setXpos(xOff);
775 position.setYpos(yOff);
776 position.setZpos(zOff);
778 morphVertexList.add(morphVertex);
781 morphMap.get(morphType).add(morphPart);
784 List<MorphPart> serialList = new LinkedList<MorphPart>();
785 MorphPart baseDummy = new MorphPart();
786 serialList.add(baseDummy);
787 for(MorphPart part : morphMap.get(MorphType.EYEBROW)){
788 serialList.add(part);
790 for(MorphPart part : morphMap.get(MorphType.EYE)){
791 serialList.add(part);
793 for(MorphPart part : morphMap.get(MorphType.LIP)){
794 serialList.add(part);
796 for(MorphPart part : morphMap.get(MorphType.EXTRA)){
797 serialList.add(part);
799 ListUtil.assignIndexedSerial(serialList);
805 * DOMからボーングループ情報を組み立てる。
806 * @param pmdModelElem ルート要素
807 * @throws TogaXmlException 構文エラー
809 private void buildBoneGroupList(Element pmdModelElem)
810 throws TogaXmlException{
811 Element boneGroupListElem =
812 getChild(pmdModelElem, "boneGroupList");
814 List<BoneGroup> boneGroupList = this.model.getBoneGroupList();
815 BoneGroup defaultGroup = new BoneGroup();
816 boneGroupList.add(defaultGroup);
818 for(Element boneGroupElem
819 : eachChild(boneGroupListElem, "boneGroup")){
820 BoneGroup group = new BoneGroup();
821 boneGroupList.add(group);
823 I18nText name = group.getGroupName();
824 buildI18nName(boneGroupElem, name);
826 for(Element boneGroupMemberElem
827 : eachChild(boneGroupElem, "boneGroupMember")){
829 getStringAttr(boneGroupMemberElem, "boneIdRef");
830 BoneInfo bone = this.boneMap.get(boneIdRef);
831 group.getBoneList().add(bone);
835 ListUtil.assignIndexedSerial(boneGroupList);
841 * DOMから剛体リスト情報を組み立てる。
842 * @param pmdModelElem ルート要素
843 * @throws TogaXmlException 構文エラー
845 private void buildRigidList(Element pmdModelElem)
846 throws TogaXmlException{
847 Element rigidListElem =
848 getChild(pmdModelElem, "rigidList");
850 List<RigidInfo> rigidList = this.model.getRigidList();
852 for(Element rigidElem : eachChild(rigidListElem, "rigid")){
853 RigidInfo rigid = new RigidInfo();
854 rigidList.add(rigid);
856 I18nText name = rigid.getRigidName();
857 buildI18nName(rigidElem, name);
859 String behavior = getStringAttr(rigidElem, "behavior");
860 RigidBehaviorType type = RigidBehaviorType.valueOf(behavior);
861 rigid.setBehaviorType(type);
863 String rigidId = getStringAttr(rigidElem, "rigidId");
864 this.rigidMap.put(rigidId, rigid);
866 if(hasChild(rigidElem, "linkedBone")){
867 Element linkedBoneElem = getChild(rigidElem, "linkedBone");
868 String boneIdRef = getStringAttr(linkedBoneElem, "boneIdRef");
869 BoneInfo linkedBone = this.boneMap.get(boneIdRef);
870 rigid.setLinkedBone(linkedBone);
873 RigidShape rigidShape = rigid.getRigidShape();
874 if(hasChild(rigidElem, "rigidShapeSphere")){
876 getChild(rigidElem, "rigidShapeSphere");
877 float radius = getFloatAttr(shapeElem, "radius");
878 rigidShape.setShapeType(RigidShapeType.SPHERE);
879 rigidShape.setRadius(radius);
881 if(hasChild(rigidElem, "rigidShapeBox")){
883 getChild(rigidElem, "rigidShapeBox");
884 float width = getFloatAttr(shapeElem, "width");
885 float height = getFloatAttr(shapeElem, "height");
886 float depth = getFloatAttr(shapeElem, "depth");
887 rigidShape.setShapeType(RigidShapeType.BOX);
888 rigidShape.setWidth(width);
889 rigidShape.setHeight(height);
890 rigidShape.setDepth(depth);
892 if(hasChild(rigidElem, "rigidShapeCapsule")){
894 getChild(rigidElem, "rigidShapeCapsule");
895 float height = getFloatAttr(shapeElem, "height");
896 float radius = getFloatAttr(shapeElem, "radius");
897 rigidShape.setShapeType(RigidShapeType.CAPSULE);
898 rigidShape.setHeight(height);
899 rigidShape.setRadius(radius);
906 Element positionElem = getChild(rigidElem, "position");
907 xVal = getFloatAttr(positionElem, "x");
908 yVal = getFloatAttr(positionElem, "y");
909 zVal = getFloatAttr(positionElem, "z");
910 MkPos3D position = rigid.getPosition();
911 position.setXpos(xVal);
912 position.setYpos(yVal);
913 position.setZpos(zVal);
915 Element radRotationElem = getChild(rigidElem, "radRotation");
916 xVal = getFloatAttr(radRotationElem, "xRad");
917 yVal = getFloatAttr(radRotationElem, "yRad");
918 zVal = getFloatAttr(radRotationElem, "zRad");
919 Rad3d rotation = rigid.getRotation();
920 rotation.setXRad(xVal);
921 rotation.setYRad(yVal);
922 rotation.setZRad(zVal);
924 Element dynamicsElem = getChild(rigidElem, "dynamics");
925 float mass = getFloatAttr(dynamicsElem, "mass");
926 float dampingPosition =
927 getFloatAttr(dynamicsElem, "dampingPosition");
928 float dampingRotation =
929 getFloatAttr(dynamicsElem, "dampingRotation");
930 float restitution = getFloatAttr(dynamicsElem, "restitution");
931 float friction = getFloatAttr(dynamicsElem, "friction");
932 DynamicsInfo dynamics = rigid.getDynamicsInfo();
933 dynamics.setMass(mass);
934 dynamics.setDampingPosition(dampingPosition);
935 dynamics.setDampingRotation(dampingRotation);
936 dynamics.setRestitution(restitution);
937 dynamics.setFriction(friction);
940 ListUtil.assignIndexedSerial(rigidList);
946 * DOMから剛体グループリスト情報を組み立てる。
947 * @param pmdModelElem ルート要素
948 * @throws TogaXmlException 構文エラー
950 private void buildRigidGroupList(Element pmdModelElem)
951 throws TogaXmlException{
952 Element rigidGroupListElem =
953 getChild(pmdModelElem, "rigidGroupList");
955 List<RigidGroup> groupList = this.model.getRigidGroupList();
957 for(Element rigidGroupElem
958 : eachChild(rigidGroupListElem, "rigidGroup")){
959 RigidGroup rigidGroup = new RigidGroup();
960 groupList.add(rigidGroup);
962 String rigidGroupId =
963 getStringAttr(rigidGroupElem, "rigidGroupId");
964 this.rigidGroupMap.put(rigidGroupId, rigidGroup);
966 for(Element memberElem
967 : eachChild(rigidGroupElem, "rigidGroupMember")){
968 String rigidIdRef = getStringAttr(memberElem, "rigidIdRef");
969 RigidInfo rigid = this.rigidMap.get(rigidIdRef);
970 rigidGroup.getRigidList().add(rigid);
971 rigid.setRigidGroup(rigidGroup);
975 while(groupList.size() < 16){
976 RigidGroup rigidGroup = new RigidGroup();
977 groupList.add(rigidGroup);
980 ListUtil.assignIndexedSerial(groupList);
987 * @param pmdModelElem ルート要素
988 * @throws TogaXmlException 構文エラー
990 private void resolveThroughRigidGroup(Element pmdModelElem)
991 throws TogaXmlException{
992 Element rigidListElem =
993 getChild(pmdModelElem, "rigidList");
995 List<RigidInfo> rigidList = this.model.getRigidList();
997 Iterator<RigidInfo> rit = rigidList.iterator();
998 for(Element rigidElem : eachChild(rigidListElem, "rigid")){
999 RigidInfo rigid = rit.next();
1000 for(Element groupElem
1001 : eachChild(rigidElem, "throughRigidGroup")){
1002 String groupId = getStringAttr(groupElem, "rigidGroupIdRef");
1003 RigidGroup group = this.rigidGroupMap.get(groupId);
1004 rigid.getThroughGroupColl().add(group);
1012 * DOMからジョイントリストを組み立てる。
1013 * @param pmdModelElem ルート要素
1014 * @throws TogaXmlException 構文エラー
1016 private void buildJointList(Element pmdModelElem)
1017 throws TogaXmlException{
1018 Element jointListElem =
1019 getChild(pmdModelElem, "jointList");
1021 List<JointInfo> jointList = this.model.getJointList();
1023 for(Element jointElem : eachChild(jointListElem, "joint")){
1024 JointInfo joint = new JointInfo();
1025 jointList.add(joint);
1027 I18nText name = joint.getJointName();
1028 buildI18nName(jointElem, name);
1030 Element rigidPairElem = getChild(jointElem, "jointedRigidPair");
1031 String rigidIdRef1 = getStringAttr(rigidPairElem, "rigidIdRef1");
1032 String rigidIdRef2 = getStringAttr(rigidPairElem, "rigidIdRef2");
1033 RigidInfo rigid1 = this.rigidMap.get(rigidIdRef1);
1034 RigidInfo rigid2 = this.rigidMap.get(rigidIdRef2);
1035 joint.setRigidPair(rigid1, rigid2);
1047 MkPos3D position = joint.getPosition();
1048 Element positionElem = getChild(jointElem, "position");
1049 xVal = getFloatAttr(positionElem, "x");
1050 yVal = getFloatAttr(positionElem, "y");
1051 zVal = getFloatAttr(positionElem, "z");
1052 position.setXpos(xVal);
1053 position.setYpos(yVal);
1054 position.setZpos(zVal);
1056 TripletRange limitPosition = joint.getPositionRange();
1057 Element limitPositionElem = getChild(jointElem, "limitPosition");
1058 xFrom = getFloatAttr(limitPositionElem, "xFrom");
1059 xTo = getFloatAttr(limitPositionElem, "xTo");
1060 yFrom = getFloatAttr(limitPositionElem, "yFrom");
1061 yTo = getFloatAttr(limitPositionElem, "yTo");
1062 zFrom = getFloatAttr(limitPositionElem, "zFrom");
1063 zTo = getFloatAttr(limitPositionElem, "zTo");
1064 limitPosition.setXRange(xFrom, xTo);
1065 limitPosition.setYRange(yFrom, yTo);
1066 limitPosition.setZRange(zFrom, zTo);
1068 Rad3d rotation = joint.getRotation();
1069 Element rotationElem = getChild(jointElem, "radRotation");
1070 xVal = getFloatAttr(rotationElem, "xRad");
1071 yVal = getFloatAttr(rotationElem, "yRad");
1072 zVal = getFloatAttr(rotationElem, "zRad");
1073 rotation.setXRad(xVal);
1074 rotation.setYRad(yVal);
1075 rotation.setZRad(zVal);
1077 TripletRange limitRotation = joint.getRotationRange();
1078 Element limitRotationElem = getChild(jointElem, "limitRotation");
1079 xFrom = getFloatAttr(limitRotationElem, "xFrom");
1080 xTo = getFloatAttr(limitRotationElem, "xTo");
1081 yFrom = getFloatAttr(limitRotationElem, "yFrom");
1082 yTo = getFloatAttr(limitRotationElem, "yTo");
1083 zFrom = getFloatAttr(limitRotationElem, "zFrom");
1084 zTo = getFloatAttr(limitRotationElem, "zTo");
1085 limitRotation.setXRange(xFrom, xTo);
1086 limitRotation.setYRange(yFrom, yTo);
1087 limitRotation.setZRange(zFrom, zTo);
1089 MkPos3D elasticPosition = joint.getElasticPosition();
1090 Element elasticPositionElem =
1091 getChild(jointElem, "elasticPosition");
1092 xVal = getFloatAttr(elasticPositionElem, "x");
1093 yVal = getFloatAttr(elasticPositionElem, "y");
1094 zVal = getFloatAttr(elasticPositionElem, "z");
1095 elasticPosition.setXpos(xVal);
1096 elasticPosition.setYpos(yVal);
1097 elasticPosition.setZpos(zVal);
1099 Deg3d elasticRotation = joint.getElasticRotation();
1100 Element elasticRotationElem =
1101 getChild(jointElem, "elasticRotation");
1102 xVal = getFloatAttr(elasticRotationElem, "xDeg");
1103 yVal = getFloatAttr(elasticRotationElem, "yDeg");
1104 zVal = getFloatAttr(elasticRotationElem, "zDeg");
1105 elasticRotation.setXDeg(xVal);
1106 elasticRotation.setYDeg(yVal);
1107 elasticRotation.setZDeg(zVal);