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