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;
}
}
}