using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using OpenGL4NET; using OpenGLRenderer; using OpenGLRenderer.Geometry; namespace ZPG_2_Rotacni_teleso { class Program { private static int N; //pocet vrcholu private static int POINTS_IN_LINE = 30; //pocet bodu na jednu kruznici private static readonly float prevod = 57.296f; //prevod z radianu na stupne private static float uhel; //vnitrni uhel private static int POINTS; //celkkovy pocet bodu static void Main(string[] args) { Renderer r = new Renderer(); //objekt pro renderovani //gl.Enable(GL.CULL_FACE); String teleso; teleso = Load_file(args[0]); N = (teleso[4]); //pocet bodu z profilu telesa uhel = (float)((2 * Math.PI) / POINTS_IN_LINE) * prevod; //Console.WriteLine("Stredovy uhel: " + uhel + "°"); POINTS = N * POINTS_IN_LINE; //celkovy pocet bodu v celem objektu /*pole pro souradnice vsech bodu*/ float[,] final = new float[POINTS, 3]; /*zavolani metody pro vypocitani souradnic pro vsechny body*/ final = Prepare_coord(teleso); /*pole pro indexy bodu, znichz se skladaji trojuhelniky*/ int[,] triangle_p = new int[(((POINTS_IN_LINE) * 2) * (N - 1)), 6]; /* zavolani metody pro vytvoreni trojuhelniku*/ triangle_p = Make_triangle(); /*pole pro normaly trojuhelniku*/ float[,] normaly = new float[(((POINTS_IN_LINE) * 2) * (N - 1)), 3]; /*pomocne pole pro ulozeni vypocitane normaly*/ float[] vector = new float[3]; /*Cyklus pro vypocitani normaly pro kazdy trojuhelnik*/ for (int i = 0; i < (triangle_p.Length / 6) - 1; i++) { vector = Make_normal(final[triangle_p[i, 0], 0], final[triangle_p[i, 0], 1], final[triangle_p[i, 0], 2], final[triangle_p[i, 1], 0], final[triangle_p[i, 1], 1], final[triangle_p[i, 1], 2], final[triangle_p[i, 2], 0], final[triangle_p[i, 2], 1], final[triangle_p[i, 2], 2]); normaly[i, 0] = vector[0]; normaly[i, 1] = vector[1]; normaly[i, 2] = vector[2]; } /*Pole pro ulozeni normal vsech bodu*/ float[,] normala = new float[POINTS, 3]; /*cyklus pro vypocitani normal*/ normala = Make_normal_for_each(triangle_p, normaly); /*Nastaveni matice projekce *uhel = 50° *rovina near = 0,1 *rovina far = 100 */ Matrix proj = new Matrix(); proj = Matrix.Perspective(50, (float)(r.Resolution.Width/r.Resolution.Height), 0.1f, 100); r.SetProjectionMatrix(ref proj); //pouzit misto "r.SetDefaultTransformations()" //r.SetDefaultTransformations(); /*Inicializace matice rotace *a posunuti objektu do -3, aby bylo lepe vidět */ Matrix rot = new Matrix(); rot.SetIdentity(); rot.Translate(0, 0, -3); /*Inicializace dvou pomocnych matic pro dve ruzne rotace*/ Matrix r_z = new Matrix(); Matrix r_y = new Matrix(); /*nastaveni uhlove rychlosti otaceni * w2 = 2 rad*s-1 * w1 = 1 rad*s-1 * vypocet probiha kazdych 10 ms */ float w2 = 0.02f; float w1 = 0.01f; /*Natsaveni pocatecni rotace*/ r_z = Rotace_RZ(-30); rot.Mult(ref r_z); r_y = Rotace_RY(w2); rot.Mult(ref r_y); int s = 0; //pomocna promenna pro mereni casu float pom = w2; //pomocna promenna pro mereni uhlu otoceni while (r.IsAlive) { int result = Environment.TickCount & Int32.MaxValue; /*Vypocet rotacnich matic probehne jednou za 10 ms*/ if (s != (result / 10) % 10) { s = (result / 10) % 10; //Console.WriteLine("Tick: " + s); /*Navraceni do puvodni pozice*/ r_y = Rotace_RY(-pom); rot.Mult(ref r_y); r_z = Rotace_RZ(+30); rot.Mult(ref r_z); /*Nastaveni pomocneho uhlu*/ pom = pom +w2 ; if (pom == 2 * Math.PI) pom = w2; /*Vytvareni novych rotacnich matic*/ r_y = Rotace_RY(-w1); rot.Mult(ref r_y); r_z = Rotace_RZ(-30); rot.Mult(ref r_z); r_y = Rotace_RY(+pom); rot.Mult(ref r_y); } r.SetModelViewMatrix(ref rot); //pouzit misto "r.SetDefaultTransformations()" /* for (int i = 0; i < (triangle_p.Length / 6) - 1; i++) { r.AddTriangle(new Float3(final[triangle_p[i, 0], 0], final[triangle_p[i, 0], 1], final[triangle_p[i, 0], 2]), new Float3(final[triangle_p[i, 1], 0], final[triangle_p[i, 1], 1], final[triangle_p[i, 1], 2]), new Float3(final[triangle_p[i, 2], 0], final[triangle_p[i, 2], 1], final[triangle_p[i, 2], 2]), new Float3(normaly[i, 0], normaly[i, 1], normaly[i, 2])); } */ /* ukazka vykresleni trojuhelniku - vrcholy obsahuji normalu */ for (int i = 0; i < (triangle_p.Length / 6) - 1; i++) { r.AddTriangle(new Point(new Float3(final[triangle_p[i, 0], 0], final[triangle_p[i, 0], 1], final[triangle_p[i, 0], 2]), new Float3(normala[triangle_p[i, 0], 0], normala[triangle_p[i, 0], 1], normala[triangle_p[i, 0], 2])), new Point(new Float3(final[triangle_p[i, 1], 0], final[triangle_p[i, 1], 1], final[triangle_p[i, 1], 2]), new Float3(normala[triangle_p[i, 1], 0], normala[triangle_p[i, 1], 1], normala[triangle_p[i, 1], 2])), new Point(new Float3(final[triangle_p[i, 2], 0], final[triangle_p[i, 2], 1], final[triangle_p[i, 2], 2]), new Float3(normala[triangle_p[i, 2], 0], normala[triangle_p[i, 2], 1], normala[triangle_p[i, 2], 2]))); } r.Render(); //zobrazeni aktualniho snimku } /*vypis do souboru*/ Write(final, triangle_p, normaly); } /// /// Vytvoreni matice rotace kolem osy Y /// /// uhel pootoceni (v radianech) /// matice rotace public static Matrix Rotace_RY(float angle) { Matrix ry = new Matrix(); ry.m11 = (float)(Math.Cos(angle)); ry.m31 = (float)(Math.Sin(angle)); ry.m13 = (float)-(Math.Sin(angle)); ry.m33 = (float)(Math.Cos(angle)); ry.m22 = 1; ry.m44 = 1; return ry; } /// /// Vytvoreni matice rotace kolem osy Z /// /// Uhel o ktery se ma vyklonit od osy(v uhlech) /// matice rotace public static Matrix Rotace_RZ(float vyklon) { Matrix rz = new Matrix(); rz.m11 = (float)(Math.Cos(vyklon / prevod)); rz.m12 = (float)(Math.Sin(vyklon / prevod)); rz.m21 = (float)-(Math.Sin(vyklon / prevod)); rz.m22 = (float)(Math.Cos(vyklon / prevod)); rz.m33 = 1; rz.m44 = 1; return rz; } /// /// Vypocitani normaly kazdeho bodu za pomoci souctu vsech normal sousednich trojuhelniku /// /// pole trojuhelniku /// pole normal trojuhelniku /// public static float[,] Make_normal_for_each(int[,] troj, float[,] norm) { float[,] normala_bod = new float[POINTS, 3]; Vector3 v1; Vector3 v2; int i; int tr = 0; for (i = 0; i < POINTS; i++, tr += 2) { //jestlize je vypocitany index mimo rozsah pole if ((tr - 1 >= 0) && (tr < norm.Length/3-1)) { v1 = new Vector3(norm[tr, 0], norm[tr, 1], norm[tr, 2]); } else { v1 = new Vector3(0, 0, 0); } if ((tr - 1 >= 0) && (tr < norm.Length / 3 - 1)) { v2 = new Vector3(norm[tr - 1, 0], norm[tr - 1, 1], norm[tr - 1, 2]); } else { v2 = new Vector3(0, 0, 0); } v1.Add(ref v2); if ((tr - 2 >= 0) && (tr < norm.Length / 3 - 1)) { v2 = new Vector3(norm[tr - 2, 0], norm[tr - 2, 1], norm[tr - 2, 2]); } else { v2 = new Vector3(0, 0, 0); } v1.Add(ref v2); if ((((tr - (POINTS_IN_LINE * 2)) - 1) >= 0) && (tr < norm.Length / 3 - 1)) { v2 = new Vector3(norm[((tr - (POINTS_IN_LINE * 2)) - 1), 0], norm[((tr - (POINTS_IN_LINE * 2)) - 1), 1], norm[((tr - (POINTS_IN_LINE * 2)) - 1), 2]); } else { v2 = new Vector3(0, 0, 0); } v1.Add(ref v2); if ((((tr - (POINTS_IN_LINE * 2))) >= 0) && (tr < norm.Length/3-1)) { v2 = new Vector3(norm[((tr - (POINTS_IN_LINE * 2))), 0], norm[((tr - (POINTS_IN_LINE * 2))), 1], norm[((tr - (POINTS_IN_LINE * 2))), 2]); } else { v2 = new Vector3(0, 0, 0); } v1.Add(ref v2); if ((((tr - (POINTS_IN_LINE * 2)) + 1) >= 0) && (tr < norm.Length / 3 - 1)) { v2 = new Vector3(norm[((tr - (POINTS_IN_LINE * 2)) + 1), 0], norm[((tr - (POINTS_IN_LINE * 2)) + 1), 1], norm[((tr - (POINTS_IN_LINE * 2)) + 1), 2]); } else { v2 = new Vector3(0, 0, 0); } v1.Add(ref v2); v1.Normalize(); normala_bod[i, 0] = v1.x; normala_bod[i, 1] = v1.y; normala_bod[i, 2] = v1.z; } //Console.WriteLine("Normaly pro kazdy bod vytvoreny...OK"); return normala_bod; } /// /// Metoda vypocita normalu pro trojuhelnik /// /// x souradnice bodu 1 /// y souradnice bodu 1 /// z souradnice bodu 1 /// x souradnice bodu 2 /// y souradnice bodu 2 /// z souradnice bodu 2 /// x souradnice bodu 3 /// y souradnice bodu 3 /// z souradnice bodu 3 /// Normala public static float[] Make_normal(float a, float b, float c, float d, float e, float f, float g, float h, float i) { float[] normal = new float[3]; float[] av = new float[3]; float[] bv = new float[3]; /*vypocet vektoru*/ av[0] = d - a; av[1] = e - b; av[2] = f - c; bv[0] = g - d; bv[1] = h - e; bv[2] = i - f; /*vektorovy soucin v × w = [vy·wz - vz·wy, vz·wx - vx·wz, vx·wy - vy·wx]*/ normal[0] = ((av[1] * bv[2]) - (av[2] * bv[1])); normal[1] = ((av[2] * bv[0]) - (av[0] * bv[2])); normal[2] = ((av[0] * bv[1]) - (av[1] * bv[0])); // Console.WriteLine("NORMALA: "+normal[0]+","+normal[1]+","+normal[2]); return normal; } /// /// Generovani trojuhelniku /// /// pole indexů bodu, ze kterych se skladaji trojuhelniky public static int[,] Make_triangle() { int j = 0; /*pocet trojuhelniku*/ int ct = (((POINTS_IN_LINE) * 2) * (N - 1)); int[,] triangle = new int[ct, 6]; //int[,] sousede = new int[ct, 3]; //Console.WriteLine("Pocet trojuhelniku: " + ct); for (int i = 0; j < ct; i++) { triangle[j, 0] = check(i); triangle[j, 1] = check(i + 1); triangle[j, 2] = check(i + POINTS_IN_LINE); triangle[j, 3] = check(j + 1); triangle[j, 4] = check(j - 1); triangle[j, 5] = check((j - (POINTS_IN_LINE * 2)) + 1); //Console.WriteLine("TR č: " + j + " = [" + triangle[j, 0] + "," + triangle[j, 1] + "," + triangle[j, 2] + "] jeho sousede: [" + triangle[j, 3] + ","+ triangle[j, 4] + ","+ triangle[j, 5]+"]"); j++; triangle[j, 0] = check(i + POINTS_IN_LINE); triangle[j, 1] = check(i + 1); triangle[j, 2] = check(i + POINTS_IN_LINE + 1); triangle[j, 3] = check(j + 1); triangle[j, 4] = check((j + (POINTS_IN_LINE * 2)) - 1); triangle[j, 5] = check(j - 1); //Console.WriteLine("TR č: " + j + " = [" + triangle[j, 0] + "," + triangle[j, 1] + "," + triangle[j, 2] + "] jeho sousede: [" + triangle[j, 3] + "," + triangle[j, 4] + "," + triangle[j, 5] + "]"); j++; } return triangle; } /// /// Zkontroluje, zda se vypocitany trojuhelnik nenachazi mimo rozsah /// /// testovany index /// V pripade splneni podminek vraci zpet puvodni hodntou. V pripade neuspechu vraci -1. public static int check(int test) { int max = (((POINTS_IN_LINE) * 2) * (N - 1))-1; if ((0 <= test) && (test <= max)) { return test; } else { return -1; } } /// /// Vypis do souboru okridlene hrany a bodu /// /// souradnice vsech bodu /// body trojuhelniku /// normaly trojuhelniku public static void Write(float[,] final_l, int[,] triangle_p_l, float[,] normaly_l) { StreamWriter sw; /* * sw = new StreamWriter("body.csv"); sw.WriteLine("x;y;z;"); for (int j = 0; j < final_l.Length / 3; j++) { sw.Write(final_l[j, 0] + ";" + final_l[j, 1] + ";" + final_l[j, 2] + ";"); sw.WriteLine(); } sw.Close(); sw = new StreamWriter("trojuhelniky.csv"); for (int j = 0; j < triangle_p_l.Length / 6; j++) { sw.Write(triangle_p_l[j, 0] + ";" + triangle_p_l[j, 1] + ";" + triangle_p_l[j, 2] + ";" + normaly_l[j, 0] + ";"); sw.WriteLine(); } sw.Close(); */ sw = new StreamWriter("sit_out.txt"); sw.WriteLine((((POINTS_IN_LINE) * 2) * (N - 1))); for (int i = 0; i < triangle_p_l.Length / 6; i++) { sw.WriteLine(triangle_p_l[i, 3] + " " + triangle_p_l[i, 4] + " " + triangle_p_l[i, 5] + " " + triangle_p_l[i, 0] + " " + triangle_p_l[i, 1] + " " + triangle_p_l[i, 2]); } sw.WriteLine(POINTS); for (int j = 0; j < final_l.Length / 3; j++) { sw.WriteLine(final_l[j, 0] + " " + final_l[j, 1] + " " + final_l[j, 2]); } sw.Close(); } /// /// Nacteni souboru /// /// nazev souboru /// retezec se souradnicemi public static String Load_file(String file) { try { StreamReader stream = new StreamReader(file); String line = stream.ReadLine(); //Console.WriteLine(line); return line; } catch { Console.WriteLine("Chybny soubor"); Environment.Exit(1); return("chyba"); } } /// /// Rozrezani retezce a vypocet x,y,z souradnic pro kazdy bod /// /// retezec se souradnicemi /// matice se vsemi souradnicemi public static float[,] Prepare_coord(String line) { string[] words = line.Split(' '); N = int.Parse(words[2]); //Console.WriteLine("N: " + N + " kontrola souradnic: " + (words.Length - 3) / 2); float[,] elem = new float[N, 2]; float[,] prim = new float[N * POINTS_IN_LINE, 3]; int j = 0; //vypocet ve 2D for (int i = 3; i < (words.Length - 2); i = i + 2, j++) { elem[j, 0] = float.Parse(words[i]); elem[j, 1] = float.Parse(words[i + 1]); } //vypocet pro 3D int total = 0; j = 0; int n = 0; for (int i = 0; i < N; i++) { for (j = 0; j < POINTS_IN_LINE; j++) { prim[n, 0] = (float)(elem[i, 0] * Math.Sin((j * uhel) / prevod)); prim[n, 1] = elem[i, 1]; prim[n, 2] = (float)(elem[i, 0] * Math.Cos((j * uhel) / prevod)); //Console.WriteLine("i: "+i+" j= "+j+" x= " + prim[n, 0] + "\ty= " + prim[n, 1] + "\tz= " + prim[n, 2]); total++; n++; } } // Console.WriteLine("Celkem " + total + " bodů"); return prim; } } }