using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Index = System.Int32;

namespace XELF.PhysX.ClothSample {

	/// <summary>
	/// 物理計算の入出力に使うポリゴンメッシュ
	/// </summary>
	partial class Mesh {
		public VertexPositionNormalTexture[] Vertices;
		public Index[] Indices;

		/// <summary>
		/// ModelMeshから作成する。
		/// </summary>
		/// <param name="modelMesh"></param>
		/// <returns></returns>
		public static Mesh FromModelMesh(ModelMesh modelMesh) {
			var mesh = new Mesh();

			// 頂点

			var sourceVertices = new VertexPositionNormalTexture[
				modelMesh.VertexBuffer.SizeInBytes / VertexPositionNormalTexture.SizeInBytes];
			modelMesh.VertexBuffer.GetData(sourceVertices);

			mesh.Vertices = new VertexPositionNormalTexture[sourceVertices.Length];
			sourceVertices.CopyTo(mesh.Vertices, 0);

			// インデックス

			if (modelMesh.IndexBuffer.IndexElementSize == IndexElementSize.SixteenBits) {
				var indices = new short[modelMesh.IndexBuffer.SizeInBytes / 2];
				mesh.Indices = new Index[indices.Length];
				modelMesh.IndexBuffer.GetData(indices);

				// インデックスをパートわけしない形式に展開
				foreach (var part in modelMesh.MeshParts) {
					for (int i = part.StartIndex, n = i + part.PrimitiveCount * 3; i < n; i++) {
						mesh.Indices[i] = (Index)(indices[i] + part.BaseVertex);
					}
				}
			} else {
				var indices = new int[modelMesh.IndexBuffer.SizeInBytes / 4];
				mesh.Indices = new Index[indices.Length];
				modelMesh.IndexBuffer.GetData(indices);

				// インデックスをパートわけしない形式に展開
				foreach (var part in modelMesh.MeshParts) {
					for (int i = part.StartIndex, n = i + part.PrimitiveCount * 3; i < n; i++) {
						mesh.Indices[i] = (Index)(indices[i] + part.BaseVertex);
					}
				}
			}

			return mesh;
		}
	}

}

namespace XELF.PhysX.ClothSample {

	partial class Mesh {
		/// <summary>
		/// 格子状のメッシュを作る。
		/// </summary>
		/// <param name="width"></param>
		/// <param name="height"></param>
		/// <returns></returns>
		public static Mesh CreateGrid(int width, int height) {
			var mesh = new Mesh();

			mesh.Vertices = new VertexPositionNormalTexture[(width + 1) * (height + 1)];
			mesh.Indices = new Index[width * height * 6];
			{
				int stride = width + 1;
				{
					int v = 0;
					for (int y = 0; y < height + 1; y++) {
						for (int x = 0; x < stride; x++) {
							mesh.Vertices[v++] = new VertexPositionNormalTexture(
								new Vector3(x, y, 0),
								Vector3.UnitZ,
								Vector2.Zero);
						}
					}
				}
				{
					int i = 0;
					for (int y = 0; y < height; y++) {
						for (int x = 0; x < width; x++) {
							Index j = (Index)(x + y * stride);
							mesh.Indices[i] = (Index)j;
							mesh.Indices[i + 1] = (Index)(j + 1);
							mesh.Indices[i + 2] = (Index)(j + stride);
							mesh.Indices[i + 3] = (Index)(j + 1);
							mesh.Indices[i + 4] = (Index)(j + stride + 1);
							mesh.Indices[i + 5] = (Index)(j + stride);
							i += 6;
						}
					}
				}
			}
			return mesh;
		}
	}
}
