using System; using System.Collections.Generic; using System.Linq; using System.Text; using OpenGL4NET; using OpenGLRenderer; using OpenGLRenderer.Geometry; using System.IO; using System.Windows.Forms; using System.Text.RegularExpressions; namespace ZPG_2_Rotacni_teleso { class Program { /// /// Počet bodů tvoricich polovinu prurezu telesa /// Number Of Points /// private static int NOP; /// /// Pocet bodu na kruznici (jedné vrstevnici) /// Number Of Points On Circle /// private static int NOPOC = 20; /// /// Pocet vsech bodu /// Number Of All Points /// private static int NOAP; /// /// Number Of Triangles /// Pocet trojuhelniku /// private static int NOT; /// /// Number Of Triangles In Row /// Pocet trojuhelniku v radku (v jednom pasu) /// private static int NOTIR; /// /// points2D[-,0] - x-ova souradnice /// points2D[-,1] - y-ova souradnice /// private static float[,] loadPoints; /// /// points[-,0] - x-ova souradnice /// points[-,1] - y-ova souradnice /// points[-,2] - z-ova souradnice /// private static float[,] points; /// /// triangles[i,0,-] - sousedi i-teho trojuhelniky /// triangles[i,1,-] - body i-teho trojuhelniku /// private static int[, ,] triangles; //private static int[,] neighbours; /// /// Normalove vektory trojuhelniku /// vectors[i,x] - x-ova slozka normaloveho vektoru i-teho trojuhelniku /// vectors[i,y] - y-ova slozka /// vectors[i,z] - z-ova slozka /// private static float[,] vectors; /// /// Normalove vektory bodu /// vectors[i,x] - x-ova slozka normaloveho vektoru i-teho bodu /// vectors[i,y] - y-ova slozka /// vectors[i,z] - z-ova slozka /// private static float[,] vectorsPoint; static void Main(String[] args) { Renderer r = new Renderer(); //objekt pro renderovani if (args.Length == 0) { MessageBox.Show("No input arguments.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Environment.Exit(1); } else { LoadPoints(args[0]); //načte body NOAP = NOP * NOPOC; NOT = 2 * NOPOC * (NOP - 1); NOTIR = 2 * NOPOC; PointPlace(NOPOC); //rozmístí body po kružnici triangles = new int[NOT,2,3]; CreateTriangles(); //vytvoří trojúhelníky GetNormalVectors(); //spočítá normálové vektory pro všechny trojúhelníky GetNormalVectorsPoints();//spočítá normálové vektory pro všechny body SetTrianglesNeighbour(); //najde sousedící trojúhelníky SaveOutput(args[0]); //uloží data do výstupního souboru } //gl.Enable(GL.CULL_FACE); //vykreslovani pouze trojuhelniku se spravnou orientaci //Nastaveni projekcni matice Matrix proj = new Matrix(); // uhel = 50°; near = 0.1; far = 100; proj = Matrix.Perspective(50, (float)(r.Resolution.Width / r.Resolution.Height), 0.1f, 100); r.SetProjectionMatrix(ref proj); //pouzit misto "r.SetDefaultTransformations()" //matice rotace + posunutí tělesa pro správné zobrazení Matrix rotace = new Matrix(); rotace.SetIdentity(); rotace.Translate(0, -0.5f, -3); //pomocné matice pro rotace Matrix rotazeZ = new Matrix(); Matrix rotazeY = new Matrix(); //úhlové rychlosti otáčení (q2 = 2 rad*s-1; q1 = 1 rad*s-1) float omega1 = 0.01f; float omega2 = 0.02f; //Natsaveni pocatecni rotace rotazeZ = RotaceZ(-30); rotace.Mult(ref rotazeZ); rotazeY = RotaceY(omega2); rotace.Mult(ref rotazeY); int t = 0; float angle = omega2; while (r.IsAlive) { int time = Environment.TickCount & Int32.MaxValue; //Vypocet rotacnich matic každých 10 ms if (t != (time / 10) % 10) { t = (time / 10) % 10; //návrat do počáteční pozice rotazeY = RotaceY(-angle); rotace.Mult(ref rotazeY); rotazeZ = RotaceZ(+30); rotace.Mult(ref rotazeZ); //nastavení úhlu angle = angle + omega2; //if (angle == 2 * Math.PI) angle = omega2; //výpočet aktuální pozice rotazeY = RotaceY(-omega1); rotace.Mult(ref rotazeY); rotazeZ = RotaceZ(-30); rotace.Mult(ref rotazeZ); rotazeY = RotaceY(+angle); rotace.Mult(ref rotazeY); } //r.SetDefaultTransformations(); r.SetModelViewMatrix(ref rotace); //pouzit misto "r.SetDefaultTransformations()" //vyklesnení tělesa z 1. části /*int a,b,c; for (int i = 0; i < NOT; i++) { a = triangles[i, 1, 0]; b = triangles[i, 1, 1]; c = triangles[i, 1, 2]; r.AddTriangle( new Float3((float)points[a, 0], (float)points[a, 1], (float)points[a, 2]), new Float3((float)points[b, 0], (float)points[b, 1], (float)points[b, 2]), new Float3((float)points[c, 0], (float)points[c, 1], (float)points[c, 2]), new Float3((float)vectors[i, 0], (float)vectors[i, 1], (float)vectors[i, 2]) ); }*/ // ukazka vykresleni trojuhelniku - trojuhelnik obsahuje normalu //r.AddTriangle(new Float3(0, 0, 0), new Float3(0.5f, 0, 0), new Float3(0.3f, 1, 0), new Float3(0, 0, 1)); // ukazka vykresleni trojuhelniku - vrcholy obsahuji normalu //r.AddTriangle(new Point(new Float3(0, 0, 0), new Float3(-1, 0.5f, 0)), new Point(new Float3(0, 0, 0.5f), new Float3(-0.3f, 1, 1)), new Point(new Float3(0, 1, 0.3f), new Float3(0.8f, -0.5f, -0.4f))); //vyklesnení tělesa ze 2. části int a,b,c; for (int i = 0; i < NOT; i++) { a = triangles[i, 1, 0]; b = triangles[i, 1, 1]; c = triangles[i, 1, 2]; r.AddTriangle( new Point( new Float3((float)points[a, 0], (float)points[a, 1], (float)points[a, 2]), new Float3((float)vectorsPoint[a, 1], (float)vectorsPoint[a, 0], (float)vectorsPoint[a, 2]) ), new Point( new Float3((float)points[b, 0], (float)points[b, 1], (float)points[b, 2]), new Float3((float)vectorsPoint[b, 1], (float)vectorsPoint[b, 0], (float)vectorsPoint[b, 2]) ), new Point( new Float3((float)points[c, 0], (float)points[c, 1], (float)points[c, 2]), new Float3((float)vectorsPoint[c, 1], (float)vectorsPoint[c, 0], (float)vectorsPoint[c, 2]) ) ); } r.Render(); //zobrazeni aktualniho snimku } } /// /// Nacte vstupni soubor /// public static void LoadPoints(String inputFile) { string line; try { StreamReader sr = new StreamReader(inputFile); line = sr.ReadLine(); string[] data; data = Regex.Split(line, " "); NOP = Int32.Parse(data[2]); loadPoints = new float[NOP, 2]; Console.WriteLine("---NACTENE BODY ("+NOP+")---"); for (int i = 0, j = 0; j < NOP; i = i + 2, j++) { loadPoints[j, 0] = float.Parse(data[i + 3]); loadPoints[j, 1] = float.Parse(data[i + 4]); Console.WriteLine(""+j+"["+loadPoints[j,0]+"; "+loadPoints[j,1]+"]"); } sr.Close(); } catch (Exception e) { MessageBox.Show("Exception ("+e.Source+"): " + e.Message + "\n"+e.ToString(), "Can not read input file", MessageBoxButtons.OK, MessageBoxIcon.Error); } } /// /// Vypocita rovnomerne rozlozeni bodu. /// Pocet bodu na kruznici. /// public static void PointPlace(int N) { double radius; double fi = 2 * Math.PI / N; double currentFI; points = new float[NOAP, 3]; int k = 0; for (int j = 0; j < NOP; j++) { radius = loadPoints[j, 0]; //polomer je x-ova vzdalenost bodu od pocatku for (int i = 0; i < N; i++) { currentFI = i * fi;//(i + 1) * fi; points[k, 0] = (float)(radius * Math.Sin(currentFI)); points[k, 1] = loadPoints[j, 1]; points[k, 2] = (float)(radius * Math.Cos(currentFI)); k++; //String text = "" + RadianToDegree(actuallyFI) + "° = " + actuallyFI + "\n X = " + x + "(" + pointsX[i] + ")\n Y = " + y + "(" + pointsY[i] + ")"; //MessageBox.Show(text, "Variable Dump", MessageBoxButtons.OK, MessageBoxIcon.Information); } } } /// /// Vypocita a ulozi trojuhelnikovou sit /// public static void CreateTriangles() { //Console.WriteLine("Pocet trojuhelniku: " + NOT + "; pocet bodu: " + NOAP + "; bodu na radku: " + NOPOC); // t - číslo aktuálně zpracovávaného trojúhelníku // i - čislo aktuálně zpracovávaného bodu // u - čítač pro uzavření kružnice for (int i = 0, t = 0, u = 0; t < NOT; i++, u++) { if (u < (NOPOC - 1)){ triangles[t, 1, 0] = i; triangles[t, 1, 1] = i + 1; triangles[t, 1, 2] = i + NOPOC; //if(t<200)Console.Write("TR č: " + t + " = [" + triangles[t, 1, 0] + "," + triangles[t, 1, 1] + "," + triangles[t, 1, 2] + "] "); t++; triangles[t, 1, 0] = i + NOPOC; triangles[t, 1, 1] = i + 1; triangles[t, 1, 2] = i + NOPOC + 1; //if (t < 200) Console.WriteLine("TR č: " + t + " = [" + triangles[t, 1, 0] + "," + triangles[t, 1, 1] + "," + triangles[t, 1, 2] + "] u = "+u); t++; } else { triangles[t, 1, 0] = i; triangles[t, 1, 1] = i - (NOPOC - 1); triangles[t, 1, 2] = i + NOPOC; //if (t < 200) Console.Write("TR č: " + t + " = [" + triangles[t, 1, 0] + "," + triangles[t, 1, 1] + "," + triangles[t, 1, 2] + "] "); t++; triangles[t, 1, 0] = i + NOPOC; triangles[t, 1, 1] = i - (NOPOC - 1); triangles[t, 1, 2] = i + 1; //if (t < 200) Console.WriteLine("TR č: " + t + " = [" + triangles[t, 1, 0] + "," + triangles[t, 1, 1] + "," + triangles[t, 1, 2] + "] u = "+u); t++; u = -1; //nakonci cyklu se zvýší o 1 a dostane se tím vlastně na nulu } } //Console.WriteLine("Počet trojúhelníků: " + NOT); } /// /// Nastavi vsem trojuhelnikum jejich sousedy /// public static void SetTrianglesNeighbour() { int A, B, C; for (int i = 0; i < NOT; i++) { if (i % 2 == 0) //sude trojuhelniky { /*A = i + NOTIR + 1; if(A > NOT || A < 0) A = -1; B = i + 1; //odvesna -> ta je bez komplikaci C = (i + NOTIR - 1) % NOTIR;*/ A = i + 1; //odvesna -> ta je bez komplikaci B = i - NOTIR + 1; if (B > NOT || B < 0) B = -1; //trojuhelnik C if ((i % NOTIR) == 0) C = i + NOTIR - 1; else C = i - 1; //------------- triangles[i, 0, 0] = A; triangles[i, 0, 1] = B; triangles[i, 0, 2] = C; } else //liche trojuhelniky { /*A = (i + 1) % NOTIR; B = i - (NOTIR + 1); if(B < 0 || B > NOT) B = -1; C = i - 1; //odvesna -> ta je bez komplikaci*/ A = (i + 1); if ((A % NOTIR) == 0) A = A - NOTIR; B = i + NOTIR - 1; if (B < 0 || B > NOT) B = -1; C = i - 1; //odvesna -> ta je bez komplikaci triangles[i, 0, 0] = A; triangles[i, 0, 1] = B; triangles[i, 0, 2] = C; } } } /// /// Vypocita normalove vektory pro vsechny trojuhelniky (ze 2 vektorů / 3 bodů) /// public static void GetNormalVectors() { int a, b, c; float[] vectorAB, vectorAC; float x, y, z; vectors = new float[NOT, 3]; for (int i = 0; i < NOT; i++) { //body trojuhelnika a = triangles[i, 1, 0]; b = triangles[i, 1, 1]; c = triangles[i, 1, 2]; //vectory vectorAB = GetVector(a, b); vectorAC = GetVector(a, c); //slozky normaloveho vektoru //vector [x,y,z] // [0,1,2] //vzorec: AB x AC = (ABy * ACz - ABz*ACy; ABz*ACx - ABx*ACz; ABx*ACy - ABy*ACx) x = vectorAB[1] * vectorAC[2] - vectorAB[2] * vectorAC[1]; y = vectorAB[2] * vectorAC[0] - vectorAB[0] * vectorAC[2]; z = vectorAB[0] * vectorAC[1] - vectorAB[1] * vectorAC[0]; //normálový vektor trojúhelníku i vectors[i, 0] = x; vectors[i, 1] = y; vectors[i, 2] = z; } } /// /// Ze dvou bodu vypocita vektor /// index bodu A /// index bodu B /// public static float[] GetVector(int pointA, int pointB) { pointB = pointB % NOAP; float[] vector = new float[3]; vector[0] = points[pointA, 0] - points[pointB, 0]; //x vector[1] = points[pointA, 1] - points[pointB, 1]; //y vector[2] = points[pointA, 2] - points[pointB, 2]; //z return vector; } /// /// Ulozi datovou strukturu do souboru /// public static void SaveOutput(String inname) { String outname = "" + inname + "_out.txt"; new System.IO.StreamWriter(@outname).Close(); //erase the file for first one using (System.IO.StreamWriter file = new System.IO.StreamWriter(@outname, true)) { file.WriteLine(""+NOT); for (int i = 0; i < NOT; i++) { file.WriteLine("" + triangles[i, 0, 0] + " " + triangles[i, 0, 1] + " " + triangles[i, 0, 2] + " " + triangles[i, 1, 0] + " " + triangles[i, 1, 1] + " " + triangles[i, 1, 2]); } file.WriteLine(""+NOAP); for (int i = 0; i < NOAP; i++) { file.WriteLine("" + points[i, 0] + " " + points[i, 1] + " " + points[i, 2]); } } } /// /// Vypocita normalove vektory pro vsechny body /// public static void GetNormalVectorsPoints() { int a, b, c; vectorsPoint = new float[NOAP, 3]; Vector3[] v = new Vector3[NOAP]; //normalu kazdeho trojuhelniku pripocita k normale bodu for (int i = 0; i < NOT; i++) { a = triangles[i, 1, 0]; //není nutné ověřovat, pole se inicializuje na (0,0,0) implicitně /*if (v[a].x == 0 && v[a].y == 0 && v[a].z == 0) v[a] = new Vector3(0,0,0);*/ v[a].Add(new Vector3(vectors[i, 0], vectors[i, 1], vectors[i, 2])); b = triangles[i, 1, 1]; v[b].Add(new Vector3(vectors[i, 0], vectors[i, 1], vectors[i, 2])); c = triangles[i, 1, 2]; v[c].Add(new Vector3(vectors[i, 0], vectors[i, 1], vectors[i, 2])); } //normalizuje normálový vektor a přepíše jej z Vector3 do pole for (int i = 0; i < NOAP; i++) { v[i].Normalize(); vectorsPoint[i, 0] = v[i].x; vectorsPoint[i, 1] = v[i].y; vectorsPoint[i, 2] = v[i].z; } } /// /// Vytvori matici rotace kolem osy Y /// /// Uhel pootoceni (v radianech) /// Matrix public static Matrix RotaceY(float radians) { Matrix rot = new Matrix(); rot.m11 = (float)(Math.Cos(radians)); rot.m31 = (float)(Math.Sin(radians)); rot.m13 = (float)-(Math.Sin(radians)); rot.m33 = (float)(Math.Cos(radians)); rot.m22 = 1; rot.m44 = 1; return rot; } /// /// Vytvori matici rotace kolem osy Z /// /// Uhel nakloneni (v uhlech) /// Matrix public static Matrix RotaceZ(float angle) { float radian = angle / 57.296f; Matrix rot = new Matrix(); rot.m11 = (float)(Math.Cos(radian)); rot.m12 = (float)(Math.Sin(radian)); rot.m21 = (float)-(Math.Sin(radian)); rot.m22 = (float)(Math.Cos(radian)); rot.m33 = 1; rot.m44 = 1; return rot; } } }