/// <summary>
        /// 指定されたクリッピングマスクがマスクするDrawableの占める矩形を計算する。
        /// 現時点でそのクリッピングマスクを使用するDrawableが無い場合はEmptyを返す。
        /// </summary>
        /// <param name="clipping_context">計算対象のクリッピングマスク</param>
        private RectangleF CalcClippedDrawTotalBounds(CubismClippingContext clipping_context)
        {
            RectangleF result = RectangleF.Empty;

            foreach (var index in clipping_context.ClippedDrawableIndexList)
            {
                // Drawableのバウンディングボックスとの和をとる
                RectangleF bounding_box = Model.GetDrawable(index).BoundingBox;
                if (bounding_box.IsEmpty == false)
                {
                    result = RectangleF.Union(result, bounding_box);
                }
            }
            return(result);
        }
        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="renderer">描画に使用するレンダラー</param>
        /// <param name="asset">描画するモデルのアセット</param>
        public CubismRenderingManager(ICubismRenderer renderer, CubismAsset asset)
        {
            Renderer = renderer;
            Asset    = asset;
            Model    = Asset.Model;

            // モデルのテクスチャをレンダラーにコピーする
            RendererTextures = new ICubismTexture[Asset.TextureByteArrays.Length];
            for (int index = 0; index < Asset.TextureByteArrays.Length; index++)
            {
                RendererTextures[index] = Renderer.CreateTexture(Asset.TextureByteArrays[index]);
            }

            // 各DrawableでどのDrawableをクリッピングマスクとして使用するか調べ、
            // もし同じDrawableの組み合わせをマスクとして用いるDrawableがあればマスクを共有するようにする
            int drawable_count = Model.DrawableCount;
            List <CubismClippingContext> all_clipping_contexts = new List <CubismClippingContext>();

            DrawableClippingContexts = new CubismClippingContext[drawable_count];
            for (int index = 0; index < drawable_count; index++)
            {
                var drawable = Model.GetDrawable(index);
                if (drawable.ClippingMaskIndexes.Length <= 0)
                {
                    DrawableClippingContexts[index] = null;
                    continue;
                }
                CubismClippingContext new_clippling_context = null;
                int[] mask_indexes = drawable.ClippingMaskIndexes.Distinct().OrderBy(x => x).ToArray();
                foreach (var target in all_clipping_contexts)
                {
                    if (mask_indexes.SequenceEqual(target.ClippingIdList) == true)
                    {
                        new_clippling_context = target;
                        break;
                    }
                }
                if (new_clippling_context == null)
                {
                    // クリッピングマスクをレンダラーに作成する
                    new_clippling_context = new CubismClippingContext(Renderer.CreateClippingMask(), mask_indexes);
                    all_clipping_contexts.Add(new_clippling_context);
                }
                new_clippling_context.ClippedDrawableIndexList.Add(index);
                DrawableClippingContexts[index] = new_clippling_context;
            }
            AllClippingContexts = all_clipping_contexts.ToArray();
        }
        /// <summary>
        /// レンダラーでモデルを描画する。
        /// </summary>
        public void Draw(Matrix4x4 mvp_matrix)
        {
            try
            {
                // 描画を開始する
                Renderer.StartDrawingModel(Asset.ModelColor, mvp_matrix);

                // クリッピングマスクを描画する
                SetupClippingMasks();

                // Drawableの描画順を取得し、描画する順番にインデックスを並べ替えたリストを作成する
                int   drawable_count             = Model.DrawableCount;
                var   drawable_render_order      = Model.GetDrawableRenderOrders();
                int[] reordered_drawable_indexes = new int[drawable_count];
                for (int index = 0; index < drawable_count; index++)
                {
                    reordered_drawable_indexes[drawable_render_order[index]] = index;
                }

                // 指定された順番通りにDrawableを描画していく
                foreach (int drawable_index in reordered_drawable_indexes)
                {
                    var drawable = Model.GetDrawable(drawable_index);
                    if (drawable.Visible == false)
                    {
                        // Drawableは非表示なので描画しない
                        continue;
                    }

                    // メッシュを描画する
                    var     texture       = RendererTextures[drawable.TextureIndex];
                    float[] vertex_buffer = drawable.VertexBuffer;
                    float[] uv_buffer     = drawable.UvBuffer;
                    short[] index_buffer  = drawable.IndexBuffer;
                    CubismClippingContext clipping_context = DrawableClippingContexts[drawable_index];
                    ICubismClippingMask   clipping_mask    = (clipping_context != null) ? clipping_context.Target : null;
                    Matrix4x4             clipping_matrix  = (clipping_context != null) ? clipping_context.MatrixForDraw : Matrix4x4.Identity;
                    Renderer.DrawMesh(texture, vertex_buffer, uv_buffer, index_buffer, clipping_mask, clipping_matrix, drawable.BlendMode, drawable.UseCulling, drawable.IsInvertedMask, drawable.Opacity);
                }
            }
            finally
            {
                Renderer.EndDrawingModel();
            }
        }