using SharpDX;
using SharpDX.D3DCompiler;
using SharpDX.Direct3D;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApp4
{
public class StaticObject
{
readonly Collection m_Vector_Vertex = new Collection();
readonly Collection m_Vector_UV = new Collection();
readonly Collection m_Vector_Normals = new Collection();
readonly Collection m_Vector_Materials = new Collection();
readonly Collection m_Vector_Textures = new Collection();
readonly Collection m_Vector_Weight = new Collection();

Collection> m_Ready_To_Buffer_Anim = new Collection>();
public Collection>> m_Vector_Animations = new Collection>>();

public Collection> Tree_Node = new Collection>();

public Collection Pure_Translation = new Collection();
public Collection Liste_BB_Name = new Collection();
public Collection> m_Vectors_List = new Collection>();

//public Collection> m_Ready_To_Buffer = new Collection>();
public int frame_Current = 0;
int frame_skiper = 0;

VertexShader vertexShader;
PixelShader pixelShader;

SharpDX.Direct3D11.Buffer[] verticesBuffer;
InputLayout layout;
SharpDX.Direct3D11.Buffer contantBuffer;
RasterizerState _rasterState;
ShaderResourceView[] textureView;

float Arm_Height = 0.0f;
int Nbr_Bones = 0;
public struct VertexType
{
public Vector3 pos;
public Vector2 uv;
public Vector3 norm;
}

public struct Anim_Data
{
public Matrix rotation;
public Vector3 translation;
public string name;
public string parent;
public Vector3 TransF0;
}

public struct Vertex_Buffer_Anim
{
public Vector3 position;
public Vector2 texture;
public Vector3 normal;
public Vector4 bone0;
public Vector4 weight0;
public Vector4 bone1;
public Vector4 weight1;
}

public StaticObject(string filename, SharpDX.Direct3D11.Device device, DeviceContext context)
{
string line;

List LinesVector = filename.Split('\n').ToList();

MessageBox.Show(LinesVector.Count().ToString());

line = LinesVector[0];


string ObjectName = line.Split(' ')[0];
int Nbr_Meshes = int.Parse(line.Split(' ')[4]);
//int Nbr_Bones = 0;

int linesConter = 0;
for (int mm = 0; mm < 1; mm++)
{
linesConter++;// formating

linesConter++;
line = LinesVector[linesConter];

int Nbr_Triangles = int.Parse(line.Split(' ')[0]);

string Mesh_Name = line.Split(' ')[9];
Nbr_Bones = int.Parse(line.Split(' ')[3]);

float[] Translation = new float[3];
float[] Quaternion = new float[4];
float[] Scaling = new float[3];

linesConter++; // formating

linesConter++;
line = LinesVector[linesConter];


Translation[0] = float.Parse(line.Split(' ')[0]);
Translation[1] = float.Parse(line.Split(' ')[1]);
Translation[2] = float.Parse(line.Split(' ')[2]);

linesConter++; // formating

linesConter++;
line = LinesVector[linesConter];


Quaternion[0] = float.Parse(line.Split(' ')[0]);
Quaternion[1] = float.Parse(line.Split(' ')[1]);
Quaternion[2] = float.Parse(line.Split(' ')[2]);
Quaternion[3] = float.Parse(line.Split(' ')[3]);

linesConter++; // formating

linesConter++;
line = LinesVector[linesConter];


Scaling[0] = float.Parse(line.Split(' ')[0]);
Scaling[1] = float.Parse(line.Split(' ')[1]);
Scaling[2] = float.Parse(line.Split(' ')[2]);


Read_Vertex_Coordinates(LinesVector, linesConter, out linesConter, Nbr_Triangles, out m_Vector_Vertex, false);
Read_UV_Coordinates(LinesVector, linesConter, out linesConter, Nbr_Triangles, out m_Vector_UV);
Read_Normals_Coordinates(LinesVector, linesConter, out linesConter, Nbr_Triangles, out m_Vector_Normals);
Read_Materials_Index(LinesVector, linesConter, out linesConter, Nbr_Triangles, out m_Vector_Materials);
Read_Textures(LinesVector, linesConter, out linesConter, Nbr_Triangles, out m_Vector_Textures);
Read_Weight_Array(LinesVector, linesConter, out linesConter, Nbr_Triangles, Nbr_Bones, out m_Vector_Weight);
Read_Animations(LinesVector, linesConter, out linesConter, Nbr_Triangles, Nbr_Bones, out Arm_Height, out m_Vector_Animations);
Rearrange_Animations();

Apply_Object_Transform(Nbr_Triangles, Scaling, Quaternion, Translation);

Create_Buffer();

Read_BB(LinesVector, linesConter, out linesConter);

Initialize(device, context);
}
}

private void Rearrange_Animations()
{
/*TN tn = new TN();
tn.name = m_Vector_Animations[0][0][0].name;
tn.parent = null;*/
for (int z = 0; z < m_Vector_Animations[0].Count(); z++)
{
TreeNode Tree_Nodet = new TreeNode(m_Vector_Animations[0][z][0], m_Vector_Animations[0][z][0].name);

//TreeNode current = Tree_Nodet;

for (int i = 0; i < m_Vector_Animations[0][z].Count(); i++)
{
string name = m_Vector_Animations[0][z][i].name;

//current = Tree_Nodet.find_Node(name);
for (int j = 0; j < m_Vector_Animations[0][z].Count() - 1; j++)
{
if (name == m_Vector_Animations[0][z][j + 1].parent)
{
Tree_Nodet.find_Node(name).AddChild(m_Vector_Animations[0][z][j + 1], m_Vector_Animations[0][z][j + 1].name);
}
}
}

Tree_Node.Add(Tree_Nodet);
}
//MessageBox.Show(Tree_Node.Count().ToString());
}

private void Read_BB(List data, int linecntr, out int linecntrout)
{
linecntr += 2;// formating


//Vector3 Max = new Vector3(float.MinValue, float.MinValue, float.MinValue);
//Vector3 Min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);

for (int s = 0; s < 13; s++)
{
linecntr += 3;// formating

string line = data[linecntr];

//MessageBox.Show(data[linecntr]);

int Nbr_Triangles = int.Parse(line.Split(' ')[0]);

string Mesh_Name = line.Split(' ')[9];

float[] Translation = new float[3];
float[] Quaternion = new float[4];
float[] Scaling = new float[3];

linecntr++; // formating

linecntr++;
line = data[linecntr];


Translation[0] = float.Parse(line.Split(' ')[0]);
Translation[1] = -float.Parse(line.Split(' ')[1]);
Translation[2] = float.Parse(line.Split(' ')[2]);

linecntr++; // formating

linecntr++;
line = data[linecntr];


Quaternion[0] = float.Parse(line.Split(' ')[0]);
Quaternion[1] = float.Parse(line.Split(' ')[1]);
Quaternion[2] = float.Parse(line.Split(' ')[2]);
Quaternion[3] = float.Parse(line.Split(' ')[3]);

linecntr++; // formating

linecntr++;
line = data[linecntr];


Scaling[0] = float.Parse(line.Split(' ')[0]);
Scaling[1] = float.Parse(line.Split(' ')[1]);
Scaling[2] = float.Parse(line.Split(' ')[2]);


Collection tmpVertex = new Collection();

Read_Vertex_Coordinates(data, linecntr, out linecntr, Nbr_Triangles, out tmpVertex, false);

//if (Quaternion[0] != 1 || Quaternion[1] != 0 || Quaternion[2] != 0 || Quaternion[3] != 0 || Scaling[0] != 1.0f || Scaling[1] != -1.0f || Scaling[2] != 1.0f) MessageBox.Show("Transformation de BB non support�: Read_BB()");

Pure_Translation.Add(new Vector3(Translation[0], Translation[1], Translation[2]));
Liste_BB_Name.Add(Mesh_Name);

Collection tmpBB = new Collection();

for (int j = 0; j < tmpVertex.Count; j++)
{

tmpVertex[j][0] *= Scaling[0];
tmpVertex[j][1] *= Scaling[1];
tmpVertex[j][2] *= Scaling[2];

//----------------------

float a, b, c, w, x, y, z, r1, r2, r3, r4, r5, r6, r7, r8;

a = tmpVertex[j][0];
b = tmpVertex[j][1];
c = tmpVertex[j][2];


x = y = z = w = 0;

Quaternion_Normalize(Quaternion[1], Quaternion[2], Quaternion[3], Quaternion[0], out x, out y, out z, out w);

//test << Object_Quaternion[0] << " " << Object_Quaternion[1] << " " << Object_Quaternion[2] << " " << Object_Quaternion[3] << "\n";

Hamilton(out r1, out r2, out r3, out r4, w, x, y, z, 0, a, b, c);
Hamilton(out r5, out r6, out r7, out r8, r1, r2, r3, r4, w, -x, -y, -z);

tmpVertex[j][0] = r6;
tmpVertex[j][1] = r7;
tmpVertex[j][2] = r8;

//-----------------------

//tmpVertex[j][0] += Translation[0];
//tmpVertex[j][1] += Translation[1];
//tmpVertex[j][2] += Translation[2];

//---------------------
tmpBB.Add(new Vector3(tmpVertex[j][0], tmpVertex[j][1], tmpVertex[j][2]));
}

m_Vectors_List.Add(tmpBB);
}


linecntrout = linecntr;
//MessageBox.Show(SphereBox.ToString());
}

private void Read_Weight_Array(List data, int linecntr, out int lineconter, int nbr_Triangles, int nbr_bones, out Collection Weight)
{
Collection WeightTmp = new Collection();


linecntr++;// formating
linecntr++;// formating

for (int m = 0; m < nbr_Triangles * 3; m++)
{
linecntr++;
string line = data[linecntr];

float[][] Weight_Array = new float[8][];

for (int j = 0; j < line.Split(' ').Count() / 2; j++)
{
Weight_Array[j] = new float[2];
for (int k = 0; k < nbr_bones; k++)
{
if (int.Parse(line.Split(' ')[2 * j]) == k)
{
Weight_Array[j][0] = k; // float.Parse(line.Split(' ')[2 * j]);
Weight_Array[j][1] = float.Parse(line.Split(' ')[2 * j + 1]);
}
}
}
for (int j = line.Split(' ').Count() / 2; j < 8; j++)
{
Weight_Array[j] = new float[2];
Weight_Array[j][0] = -1;
Weight_Array[j][1] = 0;
}
WeightTmp.Add(Weight_Array);
}
Weight = WeightTmp;
lineconter = linecntr;
}

private void Read_Animations(List data, int linecntr, out int lineconter, int nbr_Triangles, int Nbr_Bones, out float Arm_Height, out Collection>> Animations)
{
float tmp_Arm_Height = 0;

linecntr++;// formating
linecntr++;// formating

string line = data[linecntr];
byte Nbr_Animation = byte.Parse(line.Split(' ')[3]);

Collection>> tmpAni = new Collection>>();
for (int h = 0; h < Nbr_Animation; h++)
{
int Nbr_Frames;

linecntr++;

line = data[linecntr];

Nbr_Frames = int.Parse(line.Split(' ')[0]);

linecntr++;

Vector3[] trans0 = new Vector3[Nbr_Bones];
Collection> frameslist = new Collection>();
for (int i = 0; i < Nbr_Frames; i++)
{
Collection boneslist = new Collection();
for (int j = 0; j < Nbr_Bones; j++)
{
Matrix animation_Data = new Matrix();

linecntr++;

line = data[linecntr];

animation_Data.Row1 = new Vector4(float.Parse(line.Split(' ')[20]), float.Parse(line.Split(' ')[24]), float.Parse(line.Split(' ')[28]), float.Parse(line.Split(' ')[32]));
animation_Data.Row2 = new Vector4(float.Parse(line.Split(' ')[21]), float.Parse(line.Split(' ')[25]), float.Parse(line.Split(' ')[29]), float.Parse(line.Split(' ')[33]));
animation_Data.Row3 = new Vector4(float.Parse(line.Split(' ')[22]), float.Parse(line.Split(' ')[26]), float.Parse(line.Split(' ')[30]), float.Parse(line.Split(' ')[34]));
animation_Data.Row4 = new Vector4(float.Parse(line.Split(' ')[23]), float.Parse(line.Split(' ')[27]), float.Parse(line.Split(' ')[31]), float.Parse(line.Split(' ')[35]));

if (i == 0) trans0[j] = new Vector3(float.Parse(line.Split(' ')[7]), float.Parse(line.Split(' ')[8]), float.Parse(line.Split(' ')[9]));
//Matrix Translation = Matrix.Translation(float.Parse(line.Split(' ')[36]), float.Parse(line.Split(' ')[37]), float.Parse(line.Split(' ')[38]));

if (h == 0 && i == 0 && j == 6)
{
tmp_Arm_Height = float.Parse(line.Split(' ')[9]);
//MessageBox.Show(tmp_Arm_Height.ToString());
}

Anim_Data D = new Anim_Data();
D.rotation = animation_Data; // * Matrix.Scaling(1,-1,1);
D.translation = new Vector3(float.Parse(line.Split(' ')[7]), float.Parse(line.Split(' ')[8]), float.Parse(line.Split(' ')[9]));
D.name = line.Split(' ')[3];
D.parent = line.Split(' ')[5];
D.TransF0 = trans0[j];

boneslist.Add(D);
}
frameslist.Add(boneslist);
}

tmpAni.Add(frameslist);
}

Animations = tmpAni;
lineconter = linecntr;
Arm_Height = tmp_Arm_Height;
}

void Create_Buffer()
{
Collection> tmp = new Collection>();

for(int u = 0; u < m_Vector_Textures.Count; u++)
{
Collection tmp1 = new Collection();
tmp.Add(tmp1);
//MessageBox.Show("sss");
}

for (int i = 0; i < m_Vector_Normals.Count() / 3; i++)
{


Vertex_Buffer_Anim VT = new Vertex_Buffer_Anim();

VT.position = new Vector3(m_Vector_Vertex[i * 3 + 0][0], m_Vector_Vertex[i * 3 + 0][1], m_Vector_Vertex[i * 3 + 0][2]);
VT.texture = new Vector2(m_Vector_UV[i * 3 + 0][0], m_Vector_UV[i * 3 + 0][1]);
VT.normal = new Vector3(m_Vector_Normals[i * 3 + 0][0], m_Vector_Normals[i * 3 + 0][1], m_Vector_Normals[i * 3 + 0][2]);
VT.bone0 = new Vector4(m_Vector_Weight[i * 3 + 0][0][0], m_Vector_Weight[i * 3 + 0][1][0], m_Vector_Weight[i * 3 + 0][2][0], m_Vector_Weight[i * 3 + 0][3][0]);
VT.bone1 = new Vector4(m_Vector_Weight[i * 3 + 0][4][0], m_Vector_Weight[i * 3 + 0][5][0], m_Vector_Weight[i * 3 + 0][6][0], m_Vector_Weight[i * 3 + 0][7][0]);
VT.weight0 = new Vector4(m_Vector_Weight[i * 3 + 0][0][1], m_Vector_Weight[i * 3 + 0][1][1], m_Vector_Weight[i * 3 + 0][2][1], m_Vector_Weight[i * 3 + 0][3][1]);
VT.weight1 = new Vector4(m_Vector_Weight[i * 3 + 0][4][1], m_Vector_Weight[i * 3 + 0][5][1], m_Vector_Weight[i * 3 + 0][6][1], m_Vector_Weight[i * 3 + 0][7][1]);

tmp[m_Vector_Materials[i]].Add(VT);

VT.position = new Vector3(m_Vector_Vertex[i * 3 + 1][0], m_Vector_Vertex[i * 3 + 1][1], m_Vector_Vertex[i * 3 + 1][2]);
VT.texture = new Vector2(m_Vector_UV[i * 3 + 1][0], m_Vector_UV[i * 3 + 1][1]);
VT.normal = new Vector3(m_Vector_Normals[i * 3 + 1][0], m_Vector_Normals[i * 3 + 1][1], m_Vector_Normals[i * 3 + 1][2]);
VT.bone0 = new Vector4(m_Vector_Weight[i * 3 + 1][0][0], m_Vector_Weight[i * 3 + 1][1][0], m_Vector_Weight[i * 3 + 1][2][0], m_Vector_Weight[i * 3 + 1][3][0]);
VT.bone1 = new Vector4(m_Vector_Weight[i * 3 + 1][4][0], m_Vector_Weight[i * 3 + 1][5][0], m_Vector_Weight[i * 3 + 1][6][0], m_Vector_Weight[i * 3 + 1][7][0]);
VT.weight0 = new Vector4(m_Vector_Weight[i * 3 + 1][0][1], m_Vector_Weight[i * 3 + 1][1][1], m_Vector_Weight[i * 3 + 1][2][1], m_Vector_Weight[i * 3 + 1][3][1]);
VT.weight1 = new Vector4(m_Vector_Weight[i * 3 + 1][4][1], m_Vector_Weight[i * 3 + 1][5][1], m_Vector_Weight[i * 3 + 1][6][1], m_Vector_Weight[i * 3 + 1][7][1]);

tmp[m_Vector_Materials[i]].Add(VT);

VT.position = new Vector3(m_Vector_Vertex[i * 3 + 2][0], m_Vector_Vertex[i * 3 + 2][1], m_Vector_Vertex[i * 3 + 2][2]);
VT.texture = new Vector2(m_Vector_UV[i * 3 + 2][0], m_Vector_UV[i * 3 + 2][1]);
VT.normal = new Vector3(m_Vector_Normals[i * 3 + 2][0], m_Vector_Normals[i * 3 + 2][1], m_Vector_Normals[i * 3 + 2][2]);
VT.bone0 = new Vector4(m_Vector_Weight[i * 3 + 2][0][0], m_Vector_Weight[i * 3 + 2][1][0], m_Vector_Weight[i * 3 + 2][2][0], m_Vector_Weight[i * 3 + 2][3][0]);
VT.bone1 = new Vector4(m_Vector_Weight[i * 3 + 2][4][0], m_Vector_Weight[i * 3 + 2][5][0], m_Vector_Weight[i * 3 + 2][6][0], m_Vector_Weight[i * 3 + 2][7][0]);
VT.weight0 = new Vector4(m_Vector_Weight[i * 3 + 2][0][1], m_Vector_Weight[i * 3 + 2][1][1], m_Vector_Weight[i * 3 + 2][2][1], m_Vector_Weight[i * 3 + 2][3][1]);
VT.weight1 = new Vector4(m_Vector_Weight[i * 3 + 2][4][1], m_Vector_Weight[i * 3 + 2][5][1], m_Vector_Weight[i * 3 + 2][6][1], m_Vector_Weight[i * 3 + 2][7][1]);

tmp[m_Vector_Materials[i]].Add(VT);

}

m_Ready_To_Buffer_Anim = tmp;

}


void Apply_Object_Transform(int Nbr_Triangles, float[] Object_Scaling, float[] Object_Quaternion, float[] Object_Location)
{
for (int i = 0; i < Nbr_Triangles * 3; i++)
{
m_Vector_Vertex[i][0] *= Object_Scaling[0];
m_Vector_Vertex[i][1] *= Object_Scaling[1];
m_Vector_Vertex[i][2] *= Object_Scaling[2];
}

//ofstream test("test.txt");

for (int i = 0; i < Nbr_Triangles * 3; i++)
{
float a, b, c, w, x, y, z, r1, r2, r3, r4, r5, r6, r7, r8;

a = m_Vector_Vertex[i][0];
b = m_Vector_Vertex[i][1];
c = m_Vector_Vertex[i][2];


x = y = z = w = 0;

Quaternion_Normalize(Object_Quaternion[1], Object_Quaternion[2], Object_Quaternion[3], Object_Quaternion[0], out x, out y, out z, out w);

//test << Object_Quaternion[0] << " " << Object_Quaternion[1] << " " << Object_Quaternion[2] << " " << Object_Quaternion[3] << "\n";

Hamilton(out r1, out r2, out r3, out r4, w, x, y, z, 0, a, b, c);
Hamilton(out r5, out r6, out r7, out r8, r1, r2, r3, r4, w, -x, -y, -z);

m_Vector_Vertex[i][0] = r6;
m_Vector_Vertex[i][1] = r7;
m_Vector_Vertex[i][2] = r8;

//test << r6 << " " << r7 << " " << r8 << "\n";
}

for (int i = 0; i < Nbr_Triangles * 3; i++)
{
float a, b, c, w, x, y, z, r1, r2, r3, r4, r5, r6, r7, r8;

a = m_Vector_Normals[i][0];
b = m_Vector_Normals[i][1];
c = m_Vector_Normals[i][2];


x = y = z = w = 0;

Quaternion_Normalize(Object_Quaternion[1], Object_Quaternion[2], Object_Quaternion[3], Object_Quaternion[0], out x, out y, out z, out w);


Hamilton(out r1, out r2, out r3, out r4, w, x, y, z, 0, a, b, c);
Hamilton(out r5, out r6, out r7, out r8, r1, r2, r3, r4, w, -x, -y, -z);

m_Vector_Normals[i][0] = r6;
m_Vector_Normals[i][1] = r7;
m_Vector_Normals[i][2] = r8;
}

for (int i = 0; i < Nbr_Triangles * 3; i++)
{
m_Vector_Vertex[i][0] += Object_Location[0];
m_Vector_Vertex[i][1] += Object_Location[1];
m_Vector_Vertex[i][2] += Object_Location[2];
}

}

void Hamilton(out float a, out float b, out float c, out float d, float a1, float b1, float c1, float d1, float a2, float b2, float c2, float d2)
{
a = a1 * a2 - b1 * b2 - c1 * c2 - d1 * d2;
b = a1 * b2 + b1 * a2 + c1 * d2 - d1 * c2;
c = a1 * c2 - b1 * d2 + c1 * a2 + d1 * b2;
d = a1 * d2 + b1 * c2 - c1 * b2 + d1 * a2;
}

float Quaternion_Length(float X, float Y, float Z, float W)
{
return (float)Math.Sqrt((X * X) + (Y * Y) + (Z * Z) + (W * W));
}

void Quaternion_Normalize(float X, float Y, float Z, float W, out float a, out float b, out float c, out float d)
{
a = b = c = d = 0;
float length = Quaternion_Length(X, Y, Z, W);
if (length > 0.1f)
{
float inverse = 1.0f / length;
a = X * inverse;
b = Y * inverse;
c = Z * inverse;
d = W * inverse;
}
}


void Read_Vertex_Coordinates(List data, int linecntr, out int linecntrout, int nbr_Triangles, out Collection Vertex_Array, bool Is_BB)
{
string line;

linecntr++; // formating
linecntr++; // formating

Collection tmp = new Collection();

Vector3 max = new Vector3(float.MinValue, float.MinValue, float.MinValue);
Vector3 min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);


for (int m = 0; m < nbr_Triangles * 3; m++)
{
linecntr++;
line = data[linecntr];


float[] Vertices_Array = new float[3];
Vertices_Array[0] = float.Parse(line.Split(' ')[0]);
Vertices_Array[1] = float.Parse(line.Split(' ')[1]);
Vertices_Array[2] = float.Parse(line.Split(' ')[2]);

tmp.Add(Vertices_Array);
//--------------------------;

if (max.X < Vertices_Array[0]) max.X = Vertices_Array[0];
if (max.Y < Vertices_Array[1]) max.Y = Vertices_Array[1];
if (max.Z < Vertices_Array[2]) max.Z = Vertices_Array[2];

if (min.X > Vertices_Array[0]) min.X = Vertices_Array[0];
if (min.Y > Vertices_Array[1]) min.Y = Vertices_Array[1];
if (min.Z > Vertices_Array[2]) min.Z = Vertices_Array[2];
}

linecntrout = linecntr;
Vertex_Array = tmp;
}

void Read_Materials_Index(List data, int linecntr, out int linecntrout, int nbr_Triangles, out Collection Materials_Array)
{
string line;

linecntr++;

Collection tmp = new Collection();

for (int m = 0; m < nbr_Triangles; m++)
{
linecntr++;
line = data[linecntr];

tmp.Add(int.Parse(line));
//MessageBox.Show(tmp[0].ToString());
}

linecntrout = linecntr;
Materials_Array = tmp;
}

void Read_Textures(List data, int linecntr, out int linecntrout, int nbr_Triangles, out Collection Textures_Array)
{
string line;

linecntr++; // formating
linecntr++; // formating

Collection tmp = new Collection();

//linecntr++;
line = data[linecntr];

for (int m = 0; m < line.Split(' ').Count()-1; m++)
{
tmp.Add(line.Split(' ')[m]);
}

linecntrout = linecntr;
Textures_Array = tmp;
}

void Read_UV_Coordinates(List data, int linecntr, out int lineconter, int nbr_Triangles, out Collection Vertex_Array)
{
string line;

linecntr++; // formating

Collection tmp = new Collection();

for (int m = 0; m < nbr_Triangles * 3; m++)
{
linecntr++;
line = data[linecntr];


float[] Vertices_Array = new float[2];
Vertices_Array[0] = float.Parse(line.Split(' ')[0]);
Vertices_Array[1] = -float.Parse(line.Split(' ')[1]);

tmp.Add(Vertices_Array);
}
lineconter = linecntr;
Vertex_Array = tmp;
}

void Read_Normals_Coordinates(List data, int linecntr, out int lineconter, int nbr_Triangles, out Collection Vertex_Array)
{
string line;

linecntr++; // formating
//linecntr++; // formating
Collection tmp = new Collection();

for (int m = 0; m < nbr_Triangles * 3; m++)
{
linecntr++;
line = data[linecntr];


float[] Vertices_Array = new float[3];
Vertices_Array[0] = float.Parse(line.Split(' ')[0]);
Vertices_Array[1] = float.Parse(line.Split(' ')[1]);
Vertices_Array[2] = float.Parse(line.Split(' ')[2]);

tmp.Add(Vertices_Array);
}

lineconter = linecntr;
Vertex_Array = tmp;
}


private bool Initialize(SharpDX.Direct3D11.Device device, SharpDX.Direct3D11.DeviceContext context)
{
InitializeBuffers(device, context);

textureView = new ShaderResourceView[m_Ready_To_Buffer_Anim.Count()];
for (int i = 0; i < m_Ready_To_Buffer_Anim.Count(); i++)
{
//MessageBox.Show(m_Vector_Textures[i]);
SharpDX.Direct3D11.Resource R2;

R2 = TextureLoader.CreateTex2DFromFile(device, (Bitmap)Properties.Resources.ResourceManager.GetObject(m_Vector_Textures[i].Split('.')[0]));
ShaderResourceView effects2 = new ShaderResourceView(device, R2);
textureView[i] = effects2;
}

return true;
}

bool InitializeBuffers(SharpDX.Direct3D11.Device device, DeviceContext context)
{

// shaders TexturePixelShader
var vertexShaderByteCode = ShaderBytecode.Compile(Properties.Resources.Dynamic1, "VSMain", "vs_5_0");
vertexShader = new VertexShader(device, vertexShaderByteCode);


var pixelShaderByteCode = ShaderBytecode.Compile(Properties.Resources.Dynamic, "PSMain", "ps_5_0");
pixelShader = new PixelShader(device, pixelShaderByteCode);

Vertex_Buffer_Anim[][] tmpf = new Vertex_Buffer_Anim[m_Ready_To_Buffer_Anim.Count][];

for (int k = 0; k < m_Ready_To_Buffer_Anim.Count; k++)
{
Vertex_Buffer_Anim[] tmp = new Vertex_Buffer_Anim[m_Ready_To_Buffer_Anim[k].Count()];
int cntr = 0;
foreach (Vertex_Buffer_Anim V in m_Ready_To_Buffer_Anim[k])
{
tmp[cntr] = V;
cntr++;
}

tmpf[k] = tmp;
}

verticesBuffer = new SharpDX.Direct3D11.Buffer[m_Ready_To_Buffer_Anim.Count];

for (int k = 0; k < m_Ready_To_Buffer_Anim.Count; k++)
{
verticesBuffer[k] = SharpDX.Direct3D11.Buffer.Create(device, BindFlags.VertexBuffer, tmpf[k], sizeof(float) * 24 * m_Ready_To_Buffer_Anim[k].Count, ResourceUsage.Dynamic, CpuAccessFlags.Write, ResourceOptionFlags.None);
}

// Layout
layout = new InputLayout(
device,
ShaderSignature.GetInputSignature(vertexShaderByteCode),
new[] {
new InputElement("POSITION", 0, Format.R32G32B32_Float,0,0),
new InputElement("TEXCOORD", 0, Format.R32G32_Float,12,0),
new InputElement("NORMAL", 0, Format.R32G32B32_Float,20,0),
new InputElement("POSITION", 1, Format.R32G32B32A32_Float,32,0),
new InputElement("POSITION", 2, Format.R32G32B32A32_Float,48,0),
new InputElement("POSITION", 3, Format.R32G32B32A32_Float,64,0),
new InputElement("POSITION", 4, Format.R32G32B32A32_Float,80,0)
});

contantBuffer = new SharpDX.Direct3D11.Buffer(device, sizeof(float) * 16 * 128, ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);



var sampler = (new SamplerState(device, new SamplerStateDescription()
{
Filter = Filter.MinMagMipLinear,
AddressU = TextureAddressMode.Wrap,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
BorderColor = new Color4(0, 0, 0, 0),
ComparisonFunction = Comparison.Never,
MaximumAnisotropy = 16,
MipLodBias = 0,
MinimumLod = -float.MaxValue,
MaximumLod = float.MaxValue
}));

// this is how you bind the sampler to slot 1, I dont know how to do it in toolkit:
context.PixelShader.SetSampler(0, sampler);

//TextureLoader.CreateTex2DFromFile(device, "test.jpg");
var rdesc = RasterizerStateDescription.Default();
rdesc.CullMode = CullMode.None;
//rdesc.FillMode = FillMode.Wireframe;
_rasterState = new RasterizerState(device, rdesc);
context.Rasterizer.State = _rasterState;




return true;
}

public void Set_Wireframe(SharpDX.Direct3D11.Device device, bool Wireframe)
{
var rdesc = RasterizerStateDescription.Default();
rdesc.CullMode = CullMode.Back;

if (Wireframe);// rdesc.FillMode = FillMode.Wireframe;
else rdesc.FillMode = FillMode.Solid;


_rasterState = new RasterizerState(device, rdesc);
}



public Matrix Get_Animation_Transformation(int bone0, float Arm_Pitch, float Top_Rot, Vector3 Transl)
{
int bone = 0;

if (Liste_BB_Name[bone0].Contains("Torso")) bone = 5;
else if (Liste_BB_Name[bone0].Contains("R_Femur")) bone = 1;
else if (Liste_BB_Name[bone0].Contains("R_Tibia")) bone = 2;
else if (Liste_BB_Name[bone0].Contains("L_Femur")) bone = 3;
else if (Liste_BB_Name[bone0].Contains("L_Tibia")) bone = 4;
else if (Liste_BB_Name[bone0].Contains("R_Arm") && Nbr_Bones != 6) bone = 6;
else if (Liste_BB_Name[bone0].Contains("L_Arm") && Nbr_Bones != 6) bone = 7;
else if (Liste_BB_Name[bone0].Contains("R_Arm") && Nbr_Bones == 6) bone = 5;
else if (Liste_BB_Name[bone0].Contains("L_Arm") && Nbr_Bones == 6) bone = 5;
//else MessageBox.Show("GetAnimationTransform bones Problem!");

Matrix animation;

string listeB;
listeB = m_Vector_Animations[0][0][bone].name;


Collection> anim = new Collection>();
bool booltest = false;
anim = Tree_Node[frame_Current].Get_Cumulative(listeB, anim, out booltest);

Matrix totalM = CalculateCumulativeMatrix(anim);
//Vector3 VectCummul = CalculateCumulativeTranslation(anim);
//Vector3 VectCummul0 = CalculateCumulativeTranslation0(anim);
//Vector3 diff = (anim[0].Data.translation - VectCummul) - (anim[0].Data.TransF0 - VectCummul0);
Vector3 retrans = m_Vector_Animations[0][frame_Current][bone].TransF0;
Vector3 sup = m_Vector_Animations[0][frame_Current][bone].translation;
if (listeB.Contains("Arm"))
{
animation = ((Matrix.Translation(-retrans) * Matrix.RotationY(Arm_Pitch)) * Matrix.Translation(sup) * (Matrix.Translation(-retrans.X, 0, 0) * Matrix.RotationZ(Top_Rot) * Matrix.Translation(retrans.X, 0, 0)));
}
else if (Nbr_Bones == 6 && listeB.Contains("Torso")) animation = Matrix.Transpose((Matrix.Translation(-retrans) * (Matrix.RotationY(Arm_Pitch) * Matrix.RotationZ(Top_Rot)) * Matrix.Translation(sup)));
else if (listeB.Contains("Torso")) animation = ((Matrix.Translation(-retrans) * (Matrix.RotationZ(Top_Rot)) * Matrix.Translation(sup)));
else animation = ((Matrix.Translation(-retrans) * (totalM) * Matrix.Translation(sup/* + diff*/)));


return animation;
}

public void Render(Matrix view, Matrix Proj, Matrix world, DeviceContext context, float Arm_Pitch, float Top_Rot, float RunSpeed)
{
if (RunSpeed > 0)
{
frame_skiper++;

if (frame_skiper >= 8 - RunSpeed * 150)
{
frame_skiper = 0;
frame_Current++;
if (frame_Current == Tree_Node.Count - 1)
{
frame_Current = 0;
}
}
}

context.VertexShader.Set(vertexShader);
context.PixelShader.Set(pixelShader);

// Prepare All the stages
context.InputAssembler.InputLayout = layout;
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
context.VertexShader.SetConstantBuffer(0, contantBuffer);
context.Rasterizer.State = _rasterState;

Matrix[] bones = new Matrix[128];

/*view.M31 *= -1;
view.M32 *= -1;
view.M33 *= -1;
view.M34 *= -1;*/

bones[0] = Matrix.Transpose(/*m_AdjustmentMatrix **/ world);
bones[1] = Matrix.Transpose(view);
bones[2] = Matrix.Transpose(Proj);


string[] listeB = new string[Nbr_Bones];
for (int l = 0; l < Nbr_Bones; l++)
{
listeB[l] = m_Vector_Animations[0][0][l].name;
}

for (int l = 3; l < Nbr_Bones + 3; l++)
{
Collection> anim = new Collection>();
bool booltest = false;
anim = Tree_Node[frame_Current].Get_Cumulative(listeB[l - 3], anim, out booltest);

Matrix totalM = CalculateCumulativeMatrix(anim);
//Vector3 VectCummul = CalculateCumulativeTranslation(anim);
//Vector3 VectCummul0 = CalculateCumulativeTranslation0(anim);
//Vector3 diff = (anim[0].Data.translation - VectCummul) - (anim[0].Data.TransF0 - VectCummul0);
Vector3 retrans = m_Vector_Animations[0][frame_Current][l - 3].TransF0;
Vector3 sup = m_Vector_Animations[0][frame_Current][l - 3].translation;
if (listeB[l - 3].Contains("Arm"))
{
bones[l] = Matrix.Transpose((Matrix.Translation(-retrans) * Matrix.RotationY(Arm_Pitch)) * Matrix.Translation(sup) * (Matrix.Translation(-retrans.X, 0, 0) * Matrix.RotationZ(Top_Rot) * Matrix.Translation(retrans.X, 0, 0)));
}
else if (Nbr_Bones == 6 && listeB[l - 3] == "Torso") bones[l] = Matrix.Transpose((Matrix.Translation(-retrans) * (Matrix.RotationY(Arm_Pitch) * Matrix.RotationZ(Top_Rot)) * Matrix.Translation(sup)));
else if (listeB[l - 3] == "Torso") bones[l] = Matrix.Transpose((Matrix.Translation(-retrans) * (Matrix.RotationZ(Top_Rot)) * Matrix.Translation(sup)));
else bones[l] = Matrix.Transpose((Matrix.Translation(-retrans) * (totalM) * Matrix.Translation(sup/* + diff*/)));
}




/*for (int l = 3; l < Nbr_Bones + 3; l++)
{
if (l == 4 || l == 6 || l == 8)
{
if (l == 4) bones[l] = Matrix.Transpose(m_Vector_Animations.ElementAt(0)[frame_Current][l - 3].rotation * Matrix.RotationY(-Top_Rot / 1000.0f));
else bones[l] = Matrix.Transpose(/*m_Vector_Animations.ElementAt(0)[frame_Current][l - 3] * /*Matrix.Invert(Matrix.Scaling(1/0.15f)) Matrix.Translation(1.0f, 0.0f, -11.0f) * Matrix.RotationY(-Top_Rot / 200.0f)); /** Matrix.RotationZ(-Top_Rot / 1000.0f) * Matrix.Translation(-1.0f, 0.0f, 11.0f);*/ /////// 0.15f is for bone scaling of 0.150 in blender
/*}
else
{
//if (true) bones[l] = Matrix.Transpose(m_Vector_Animations.ElementAt(0)[frame_Current][l - 3].rotPivot * m_Vector_Animations.ElementAt(0)[frame_Current][l - 3].rotation * Matrix.Invert(m_Vector_Animations.ElementAt(0)[frame_Current][l - 3].rotPivot));
//else bones[l] = Matrix.Transpose(m_Vector_Animations.ElementAt(0)[frame_Current][l - 3].rotation);
}
}*/



context.UpdateSubresource(bones, contantBuffer);

for (int i = 0; i < m_Ready_To_Buffer_Anim.Count(); i++)
{
context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(verticesBuffer[i], Utilities.SizeOf() * 24, 0));

context.PixelShader.SetShaderResource(0, textureView[i]); // new ShaderResourceView(device, texture));

// Draw the cube
context.Draw(m_Ready_To_Buffer_Anim[i].Count(), 0);
}

//context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(verticesBufferBB[0], Utilities.SizeOf() * 24, 0));

//context.PixelShader.SetShaderResource(0, textureView[1]); // new ShaderResourceView(device, texture));

// Draw the cube
//context.Draw(vcount, 0);

/*frame_skiper++;
if (frame_skiper == 10)
{
frame_skiper = 0;
frame_Current++;
}*/
//frame_Current++;

}

public Matrix CalculateCumulativeMatrix(Collection> data)
{
Matrix M = Matrix.Identity;
for (int i = 0; i < data.Count(); i++)
{
M *= data[i].Data.rotation;
}

return Matrix.Orthogonalize(M);
}

public Vector3 CalculateCumulativeTranslation(Collection> data)
{
Vector3 M = new Vector3(0, 0, 0);
for (int i = 0; i < data.Count() - 1; i++)
{
M += data[data.Count() - 1 - i].Data.translation;
}

return M;
}

public Vector3 CalculateCumulativeTranslation0(Collection> data)
{
Vector3 M = new Vector3(0, 0, 0);
for (int i = 0; i < data.Count() - 1; i++)
{
M += data[data.Count() - 1 - i].Data.TransF0;
}

return M;
}
}
}