A3D7.7: COLLADAからユーザー定義プロパティを取り出す

2011年4月16日
OpenCOLLADAで書き出すCOLLADAファイルにはオブジェクトごとに設定したユーザー定義プロパティを含める事ができます。

ユーザー定義プロパティっていうのは、モデリングソフト等で↓こんな感じにオブジェクトごとに自由に設定できるデータで、自分はA3D+Jiglibでコリジョン設定をする際に剛体のパラメータに使おうかなって思ってました。
userdefwin.png

※書き出し時に赤枠の所にチェックを入れるとユーザー定義データが含められる
userprop.png

ただ、Alternativa3D7.7がユーザー定義データをパースしてくれているかがちょっとわからなくて。Object3Dにそれっぽいパラメータが見当たらなかったから多分パースしてないのかな?

よくわからないので、ユーザー定義プロパティだけをパースするクラスを作ってみました。

色々と自信のないソース

package {
	
	import alternativa.engine3d.core.Object3D;
	import flash.utils.Dictionary;
	
	/**
	 * OpenCOLLADAで書き出したデータからユーザー定義プロパティをパースする
	 */
	public class UserDataParser {
		
		private var _data:Dictionary = new Dictionary();
		
		public function UserDataParser() {
		}
		
		/**
		 * ユーザー定義プロパティをパース
		 * @param	xml	COLLADAデータ
		 * @param	objects	ParserColladaでパースしたObject3Dの配列
		 */
		public function parse(xml:XML, objects:Vector.<Object3D>):void {
			var ns:Namespace = xml.namespace();
			var users:Array = [];
			for each(var item:XML in xml..ns::library_visual_scenes.ns::visual_scene.ns::node) {
				var user:Object = { };
				users.push(user);
				var userProp:String = item..ns::technique.(@profile == "OpenCOLLADA").ns::user_properties;
				if (!userProp) continue;
				var params:Array = userProp.replace(/\r\n|\n/g, "\r").split("\r");
				for each(var p:String in params) {
					var match:Array = p.match(/^(.*)=(.*)$/);
					if (!match) continue;
					var atr:String = trim(match[1]);
					if (!atr) continue;
					user[atr] = scanValue(match[2]);
				}
			}
			for (var i:int = 0; i < objects.length; i++) {
				_data[objects[i]] = users[i];
			}
		}
		
		/**
		 * 文字列をNumber,String,Array,Booleanに変換する
		 * @param	str
		 * @return
		 */
		public function scanValue(str:String):* {
			str = trim(str);
			if (!str) return null;
			var s0:String = str.substr(0, 1);
			var s1:String = str.substr(-1, 1);
			
			var value:*;
			if ((s0 == '"' && s1 == '"') || (s0 == "'" && s1 == "'")) {
				value = str.substr(1, str.length-2);
			} else if (str == "true" || str == "false") {
				value = str == "true";
			} else if (s0 == '[' && s1 == ']') {
				value = scanArray(str.substr(1, str.length - 2));
			} else {
				value = Number(str);
			}
			
			return value;
		}
		
		private function scanArray(str:String):Array {
			var values:Array = [];
			str = trim(str);
			if (!str) return values;
			
			var buffer:String = "";
			var qt:String = "";
			var cnt:int = 0;
			var isString:Boolean = false;
			var strings:Array = str.split("");
			for each(var s:String in strings) {
				if (!isString && s == "," && !cnt) {
					values.push(scanValue(buffer));
					buffer = "";
				} else {
					if (!isString && (s == '"' || s == "'")) {
						isString = true;
						qt = s;
					} else if (isString && s == qt) {
						isString = false;
					}
					if (!isString) {
						if (s == "[") cnt++;
						if (s == "]") cnt--;
					}
					buffer += s;
				}
			}
			values.push(scanValue(buffer));
			
			return values;
		}
		
		private function trim(str:String):String {
			return str.replace(/^\s+|\s+$/g, "");
		}
		
		/**
		 * ユーザー定義プロパティを取得
		 * @param	obj
		 * @return
		 */
		public function getData(obj:Object3D):Object {
			return _data[obj];
		}
		
	}

}

このパーサはXMLからユーザー定義プロパティだけをパースするだけなので、COLLADAモデルは別にParserColladaでパースしておく必要があります。

(2011/4/30追記)親子関係のリンクがあった時の処理を組んでいなかったので、子以下のオブジェクトのプロパティが取れないかもしれません。

使い方

//COLLADAデータ
var xml:XML = <COLLADA>~</COLLADA>;

//COLLADAをパース
var parser:ParserCollada = new ParserCollada();
parser.parse(xml);

//XMLとParserCollada.objectsを渡してユーザー定義プロパティをパース
var user:UserDataParser = new UserDataParser();
user.parse(xml, parser.objects);

//名前がmojaのオブジェクトを取得
var moja:Object3D = parser.getObjectByName("moja");

//mojaのユーザー定義データを取得
var data:Object = user.getData(moja);

//mojaにtype="hoge"ってユーザー定義データがある場合、hogeがトレースされる
trace(data.type);

モデリングソフトで設定するユーザー定義プロパティの書式

(例)
hoge = "moja"
foo=123.4
test = [3, "@", -0.5, ["xxx","yyy"], false]
flag=true

  • 変数=値(セミコロンはつけない)
  • イコール前後や配列内のスペースはあってもなくてもいい
  • 値が数値、文字列、配列、ブーリアンならパースできる
  • 配列は入れ子になっていても大丈夫
  • 「"」か「'」で囲うと文字列になる

トラックバック(0)

トラックバックURL: http://www.morocoshi.net/mt/mt-tb.cgi/44

コメントする