bate's blog

調べたこと実装したことなどを取りとめもなく書きます。

Colladaからデータ取得

C#のLinqToXMLでColladaからデータを取ってみる

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Xml.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace WindowsFormsApplication1
{
    /// <summary>
    /// マテリアル情報
    /// </summary>
    struct Material
    {
        public string MaterialName;
        public List<string> TextureFileName;
        public Vector4 DiffuseColor;
        public Vector4 AmbientColor;
        public Vector4 EmissionColor;
        public Vector4 SpecularColor;
        public float Shininess;
        public float RefractionIndex;
    }

    public partial class Form1 : Form
    {
        private Dictionary<string, string> m_ImageDictionary;
        private List<Material> m_MaterialList;
        public Form1()
        {
            m_ImageDictionary = new Dictionary<string, string>();
            m_MaterialList = new List<Material>();

            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            openFileDialog1.InitialDirectory = @"D:\text\dae";
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                string dae_filename = openFileDialog1.FileName;
                textBox1.Text = dae_filename;
                parseDAE(dae_filename);
            }
        }

        /// <summary>
        /// DAEを解釈
        /// </summary>
        /// <param name="dae_filename"></param>
        private void parseDAE(string dae_filename)
        {
            var load_dae = XDocument.Load(@dae_filename);
            XNamespace ex = @"http://www.collada.org/2005/11/COLLADASchema";

            // テクスチャ
            m_ImageDictionary = parseTexture(load_dae, ex);

            // マテリアル
            m_MaterialList = parseMaterialList(load_dae, ex);
        }

        /// <summary>
        /// テクスチャの連想配列作成
        /// </summary>
        /// <param name="dae"></param>
        /// <param name="ex"></param>
        /// <returns></returns>
        private Dictionary<string, string> parseTexture(XDocument dae, XNamespace ex)
        {
            Dictionary<string, string> imageDictionary = new Dictionary<string, string>();
            var query = from n in dae.Descendants(ex + "image") select n;
            foreach (var elem in query)
            {
                imageDictionary.Add(elem.Attribute("id").Value, elem.Value);
            }

            return imageDictionary;
        }

        /// <summary>
        /// マテリアルリスト
        /// </summary>
        /// <param name="dae"></param>
        /// <param name="ex"></param>
        /// <returns></returns>
        private List<Material> parseMaterialList(XDocument dae, XNamespace ex)
        {
            List<Material> materialList = new List<Material>();
            var query = from n in dae.Descendants(ex + "effect") select n;
            foreach (var elem in query)
            {
                Material mat = new Material();
                mat.TextureFileName = new List<string>();

                // マテリアル名
                mat.MaterialName = elem.Attribute("id").Value;

                // テクスチャ名(複数の場合あり)
                XElement el = elem;
                var q = from m in el.Descendants(ex + "surface") select m;
                foreach (var e in q)
                {
                    string texname = m_ImageDictionary[e.Value];
                    mat.TextureFileName.Add(texname);
                }

                // diffuse
                mat.DiffuseColor = parseColor("diffuse", el, ex);
                // ambient
                mat.AmbientColor = parseColor("ambient", el, ex);
                // emission
                mat.EmissionColor = parseColor("emission", el, ex);
                // specular
                mat.SpecularColor = parseColor("specular", el, ex);
                // shininess
                mat.Shininess = parseParam("shiniess", el, ex);
                // refraction index
                mat.RefractionIndex = parseParam("index_of_refraction", el, ex);
                

                materialList.Add(mat);
            }

            return materialList;
        }

        /// <summary>
        /// library_effects内の色を解析
        /// </summary>
        /// <param name="colorname"></param>
        /// <param name="element"></param>
        /// <param name="ex"></param>
        /// <returns></returns>
        private Vector4 parseColor(string colorname, XElement element, XNamespace ex)
        {
            var query = from m in element.Descendants(ex + colorname) select m;
            Vector4 color = new Vector4();
            foreach (var e in query)
            {
                string col = e.Value;
                string[] array = col.Split(' ');
                if (array.Count() > 1)
                {
                    color.X = float.Parse(array[0]);
                    color.Y = float.Parse(array[1]);
                    color.Z = float.Parse(array[2]);
                    color.W = float.Parse(array[3]);
                }
                else
                {
                    color.X =
                    color.Y =
                    color.Z =
                    color.W = 1.0f;
                }
            }

            return color;
        }

        /// <summary>
        /// float解析
        /// </summary>
        /// <param name="colorname"></param>
        /// <param name="element"></param>
        /// <param name="ex"></param>
        /// <returns></returns>
        private float parseParam(string paramname, XElement element, XNamespace ex)
        {
            var query = from m in element.Descendants(ex + paramname) select m;
            float param = 0.0f;
            foreach (var e in query)
            {
                string p = e.Value;
                if (p.Length > 0)
                {
                    param = float.Parse(p);
                }
            }

            return param;
        }
    }
}