using System; using System.Collections.Generic; using System.Linq; using System.Text; using OpenGL4NET; using System.IO; using System.Runtime.InteropServices; using System.Drawing; using System.Windows.Forms; namespace ZPG_semestralka { class TrojuhelSit { int sirkaMatice; int vyskaMatice; int krokMatice; float deleniByte; String nazev; public Vector3[] vrchol; uint[] index; public float[][] pole; uint vertexVBO, indexVBPO; uint dratenyModelBodyBuff; uint textura2; public Vector3[] normaly; VrcholANormala[] vrcholAnormala;// = new VrcholANormala [n * n]; // metoda načte a vygeneruje trojúhelníkouvou matici + vypočítá normálu každého vrcholu public TrojuhelSit(String nazev, int sirkaMatice, int vyskaMatice, int krokMatice, float deleniByte) { this.nazev = nazev; this.sirkaMatice = sirkaMatice; this.vyskaMatice = vyskaMatice; this.krokMatice = krokMatice; this.deleniByte = deleniByte; vrchol = new Vector3[sirkaMatice * vyskaMatice]; index = new uint[(sirkaMatice - 1) * (vyskaMatice - 1) * 3 * 2]; int u = 0; pole = nactiMatici(nazev, sirkaMatice, vyskaMatice); vrcholAnormala = new VrcholANormala[sirkaMatice * vyskaMatice]; // vytovoření pole jednotlivých bodů for (int j = 0; j < vyskaMatice; j++) { for (int i = 0; i < sirkaMatice; i++) { if (j == 0) { vrchol[i] = new Vector3(krokMatice * (sirkaMatice - 1 - i), krokMatice * (vyskaMatice - 1 - j), pole[j][i]); gl.TexCoord2f((sirkaMatice - 1 - i), (vyskaMatice - 1 - j)); } else { vrchol[j * sirkaMatice + i] = new Vector3(krokMatice * (sirkaMatice - 1 - i), krokMatice * (vyskaMatice - 1 - j), pole[j][i]); gl.TexCoord2f((sirkaMatice - 1 - i), (vyskaMatice - 1 - j)); if (i == 0) { index[u] = (uint)(j * sirkaMatice + i); u++; index[u] = (uint)((j - 1) * sirkaMatice + i); u++; index[u] = (uint)((j - 1) * sirkaMatice + (i + 1)); u++; } else if (i == sirkaMatice - 1) { index[u] = (uint)(j * sirkaMatice + i); u++; index[u] = (uint)((j - 1) * sirkaMatice + i); u++; index[u] = (uint)((j) * sirkaMatice + (i - 1)); u++; } else { index[u] = (uint)(j * sirkaMatice + i); u++; index[u] = (uint)((j - 1) * sirkaMatice + i); u++; index[u] = (uint)((j - 1) * sirkaMatice + (i + 1)); u++; index[u] = (uint)(j * sirkaMatice + i); u++; index[u] = (uint)((j - 1) * sirkaMatice + i); u++; index[u] = (uint)((j) * sirkaMatice + (i - 1)); u++; } } } } normaly = new Vector3[sirkaMatice * vyskaMatice]; for (int j = 0; j < vyskaMatice; j++) // výpočet normál pro jednolivé body { for (int i = 0; i < sirkaMatice; i++) { if ((j == 0) && (i == 0)) { Vector3 v1 = vrchol[j * sirkaMatice + i] - vrchol[j * sirkaMatice + (i + 1)]; Vector3 v2 = vrchol[j * sirkaMatice + i] - vrchol[(j + 1) * sirkaMatice + i]; Vector3 vec4 = Vector3.Cross(ref v1, ref v2); vec4.Normalize(); normaly[j * sirkaMatice + i] = vec4; } else if ((j == 0) && (i == (sirkaMatice - 1))) { Vector3 v1 = vrchol[j * sirkaMatice + i] - vrchol[j * sirkaMatice + (i - 1)]; Vector3 v2 = vrchol[j * sirkaMatice + i] - vrchol[(j + 1) * sirkaMatice + i]; Vector3 vec4 = Vector3.Cross(ref v1, ref v2); vec4.Normalize(); normaly[j * sirkaMatice + i] = vec4; } else if ((j == (vyskaMatice - 1)) && (i == 0)) { Vector3 v1 = vrchol[j * sirkaMatice + i] - vrchol[j * sirkaMatice + (i + 1)]; Vector3 v2 = vrchol[j * sirkaMatice + i] - vrchol[(j - 1) * sirkaMatice + i]; Vector3 vec4 = Vector3.Cross(ref v1, ref v2); vec4.Normalize(); normaly[j * sirkaMatice + i] = vec4; } else if ((j == (vyskaMatice - 1)) && (i == (sirkaMatice - 1))) { Vector3 v1 = vrchol[j * sirkaMatice + i] - vrchol[j * sirkaMatice + (i - 1)]; Vector3 v2 = vrchol[j * sirkaMatice + i] - vrchol[(j - 1) * sirkaMatice + i]; Vector3 vec4 = Vector3.Cross(ref v1, ref v2); vec4.Normalize(); normaly[j * sirkaMatice + i] = vec4; } else if ((j == 0) && ((i != (sirkaMatice - 1)) || (i != 0))) { Vector3 v1 = vrchol[j * sirkaMatice + i] - vrchol[j * sirkaMatice + (i - 1)]; Vector3 v2 = vrchol[j * sirkaMatice + i] - vrchol[(j + 1) * sirkaMatice + i]; Vector3 v3 = vrchol[j * sirkaMatice + i] - vrchol[j * sirkaMatice + i + 1]; Vector3 vec1 = Vector3.Cross(ref v1, ref v2); Vector3 vec2 = Vector3.Cross(ref v2, ref v3); Vector3 normala = vec1 + vec2; normala.Normalize(); normaly[j * sirkaMatice + i] = normala; } else if ((j == (vyskaMatice - 1)) && ((i != (sirkaMatice - 1)) || (i != 0))) // spodní krajní strana { Vector3 v1 = vrchol[j * sirkaMatice + i] - vrchol[j * sirkaMatice + (i - 1)]; Vector3 v2 = vrchol[j * sirkaMatice + i] - vrchol[(j - 1) * sirkaMatice + i]; Vector3 v3 = vrchol[j * sirkaMatice + i] - vrchol[j * sirkaMatice + i + 1]; Vector3 vec1 = Vector3.Cross(ref v1, ref v2); Vector3 vec2 = Vector3.Cross(ref v2, ref v3); Vector3 normala = vec1 + vec2; normala.Normalize(); normaly[j * sirkaMatice + i] = normala; } else if (((j != (vyskaMatice - 1)) || (j != 0)) && (i == 0)) { Vector3 v1 = vrchol[j * sirkaMatice + i] - vrchol[(j - 1) * sirkaMatice + i]; Vector3 v2 = vrchol[j * sirkaMatice + i] - vrchol[j * sirkaMatice + i + 1]; Vector3 v3 = vrchol[j * sirkaMatice + i] - vrchol[(j + 1) * sirkaMatice + i]; Vector3 vec1 = Vector3.Cross(ref v1, ref v2); Vector3 vec2 = Vector3.Cross(ref v2, ref v3); Vector3 normala = vec1 + vec2; normala.Normalize(); normaly[j * sirkaMatice + i] = normala; } else if (((j != (vyskaMatice - 1)) || (j != 0)) && (i == (sirkaMatice - 1))) { Vector3 v1 = vrchol[j * sirkaMatice + i] - vrchol[(j - 1) * sirkaMatice + i]; Vector3 v2 = vrchol[j * sirkaMatice + i] - vrchol[j * sirkaMatice + i - 1]; Vector3 v3 = vrchol[j * sirkaMatice + i] - vrchol[(j + 1) * sirkaMatice + i]; Vector3 vec1 = Vector3.Cross(ref v1, ref v2); Vector3 vec2 = Vector3.Cross(ref v2, ref v3); Vector3 normala = vec1 + vec2; normala.Normalize(); normaly[j * sirkaMatice + i] = normala; } else { Vector3 v1 = vrchol[j * sirkaMatice + i] - vrchol[(j - 1) * sirkaMatice + i]; Vector3 v2 = vrchol[j * sirkaMatice + i] - vrchol[j * sirkaMatice + i + 1]; Vector3 v3 = vrchol[j * sirkaMatice + i] - vrchol[(j + 1) * sirkaMatice + i]; Vector3 v4 = vrchol[j * sirkaMatice + i] - vrchol[j * sirkaMatice + i - 1]; Vector3 vec1 = Vector3.Cross(ref v1, ref v2); Vector3 vec2 = Vector3.Cross(ref v2, ref v3); Vector3 vec3 = Vector3.Cross(ref v3, ref v4); Vector3 vec4 = Vector3.Cross(ref v4, ref v1); Vector3 normala = vec1 + vec2 + vec3 + vec4; normala.Normalize(); normaly[j * sirkaMatice + i] = normala; } } } for (int a = 0; a < vyskaMatice; a++) // vytvoření sruktury pro jednolivé body s normálami a texturami { for (int i = 0; i < sirkaMatice; i++) { int j = a * sirkaMatice + i; if (normaly[j].x == 0 && normaly[j].y == 0 && normaly[j].z == 0) { normaly[j].z = 1; } vrcholAnormala[j] = new VrcholANormala((float)vrchol[j].x, (float)vrchol[j].y, (float)vrchol[j].z, (float)normaly[j].x, (float)normaly[j].y, (float)normaly[j].z, (float)a*(float)0.4, (float)i*(float)0.4); } } Bitmap image = null; // Načtení textury if(!File.Exists("textury/trava.bmp")) { System.Console.Out.WriteLine("Textura nebyla nalezena!"); } else { image = new Bitmap("textury/trava.bmp"); System.Drawing.Imaging.BitmapData bitmapdata; Rectangle rect = new Rectangle(0, 0, image.Width, image.Height); bitmapdata = image.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb); textura2 = gl.GenTexture(); gl.BindTexture(GL.TEXTURE_2D, textura2); gl.TexImage2D(GL.TEXTURE_2D, 0, (int)GL.RGB, image.Width, image.Height, 0, GL.BGR_EXT, GL.UNSIGNED_BYTE, bitmapdata.Scan0); gl.TexParameterf(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR); gl.TexParameterf(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.LINEAR); gl.TexParameterf(GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.REPEAT); gl.TexParameterf(GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.REPEAT); } vertexVBO = gl.GenBuffer(); gl.BindBuffer(GL.ARRAY_BUFFER, vertexVBO); gl.BufferData(GL.ARRAY_BUFFER, (int)(sirkaMatice * vyskaMatice) * VrcholANormala.SizeInBytes, vrcholAnormala, GL.STATIC_DRAW); gl.BindBuffer(GL.ARRAY_BUFFER, 0); dratenyModelBodyBuff = gl.GenBuffer(); gl.BindBuffer(GL.ARRAY_BUFFER, dratenyModelBodyBuff); gl.BufferData(GL.ARRAY_BUFFER, (int)(sirkaMatice * vyskaMatice) * sizeof(float)*3, vrchol, GL.STATIC_DRAW); gl.BindBuffer(GL.ARRAY_BUFFER, 0); // Priiprava ibo indexVBPO = gl.GenBuffer(); gl.BindBuffer(GL.ELEMENT_ARRAY_BUFFER, indexVBPO); gl.BufferData(GL.ELEMENT_ARRAY_BUFFER, index.Length * sizeof(uint), index, GL.STATIC_DRAW); gl.BindBuffer(GL.ELEMENT_ARRAY_BUFFER, 0); gl.BindBuffer(GL.ARRAY_BUFFER, 0); } /* * Hlavní metoda pro renderování */ public void Render(bool dratenyModel) { if (dratenyModel) { nahrajDratenyModel(); } else { gl.ActiveTexture(GL.TEXTURE0); gl.Enable(GL.TEXTURE_2D); gl.BindTexture(GL.TEXTURE_2D, textura2); gl.TexEnvf(GL.TEXTURE_ENV, GL.TEXTURE_ENV_MODE, GL.MODULATE); gl.BindBuffer(GL.ARRAY_BUFFER, vertexVBO); // NAČTENÍ BUFFERU gl.BindBuffer(GL.ELEMENT_ARRAY_BUFFER, indexVBPO); gl.ClientActiveTexture(GL.TEXTURE0); gl.EnableClientState(GL.TEXTURE_COORD_ARRAY); // TEXTURA gl.TexCoordPointer(2, GL.FLOAT, VrcholANormala.SizeInBytes, (IntPtr)24); gl.EnableClientState(GL.NORMAL_ARRAY); // NORMÁLY gl.NormalPointer(GL.FLOAT, VrcholANormala.SizeInBytes, (IntPtr)12); gl.EnableClientState(GL.VERTEX_ARRAY); // POZICE BODU gl.VertexPointer(3, GL.FLOAT, VrcholANormala.SizeInBytes, (IntPtr)0); gl.DrawElements(GL.TRIANGLES, index.Length, GL.UNSIGNED_INT, (IntPtr)0); // VYKRESLENÍ gl.DisableClientState(GL.VERTEX_ARRAY); gl.DisableClientState(GL.NORMAL_ARRAY); gl.DisableClientState(GL.TEXTURE_COORD_ARRAY); gl.BindBuffer(GL.ARRAY_BUFFER, 0); gl.BindBuffer(GL.ELEMENT_ARRAY_BUFFER, 0); gl.BindTexture(GL.TEXTURE_2D, 0); gl.ActiveTexture(GL.TEXTURE0); gl.Disable(GL.TEXTURE_2D); gl.BindTexture(GL.TEXTURE_2D, 0); } } /* * Metoda pro zobrazení drátěného modelu. */ private void nahrajDratenyModel(){ gl.BindBuffer(GL.ARRAY_BUFFER, dratenyModelBodyBuff); // NAČTENÍ BUFFERU gl.BindBuffer(GL.ELEMENT_ARRAY_BUFFER, indexVBPO); gl.EnableClientState(GL.VERTEX_ARRAY); // POZICE BODU gl.VertexPointer(3, GL.FLOAT, sizeof(float)*3, (IntPtr)0); //gl.Color3b(0,0,0); gl.DrawElements(GL.TRIANGLES, index.Length, GL.UNSIGNED_INT, (IntPtr)0); // VYKRESLENÍ gl.DisableClientState(GL.VERTEX_ARRAY); gl.BindBuffer(GL.ARRAY_BUFFER, 0); gl.BindBuffer(GL.ELEMENT_ARRAY_BUFFER, 0); gl.PolygonMode(GL.FRONT_AND_BACK, GL.LINE);//fill gl.BindBuffer(GL.ARRAY_BUFFER, dratenyModelBodyBuff); // NAČTENÍ BUFFERU gl.BindBuffer(GL.ELEMENT_ARRAY_BUFFER, indexVBPO); gl.EnableClientState(GL.VERTEX_ARRAY); // POZICE BODU gl.VertexPointer(3, GL.FLOAT, sizeof(float) * 3, (IntPtr)0); gl.Color3b(0, 0, 255); gl.DrawElements(GL.TRIANGLES, index.Length, GL.UNSIGNED_INT, (IntPtr)0); // VYKRESLENÍ gl.DisableClientState(GL.VERTEX_ARRAY); gl.BindBuffer(GL.ARRAY_BUFFER, 0); gl.BindBuffer(GL.ELEMENT_ARRAY_BUFFER, 0); } /* metoda načte matici ze souboru * nazev - cesta k souboru s maticí * sirka - sirka matice * vyska - vyska matice */ public float[][] nactiMatici(String nazev, int sirka, int vyska) { float[][] pole = new float[vyska][]; BinaryReader vstup = new BinaryReader(File.Open(nazev, FileMode.Open)); for (int i = 0; i < pole.Length; i++) { pole[i] = new float[sirka]; for (int j = pole[i].Length - 1; j >= 0; j--) { pole[i][j] = ((float)vstup.ReadByte()) / deleniByte; } } vstup.Close(); return pole; } // metoda na uvolnění paměti public void Destroy() { gl.DeleteBuffer(vertexVBO); gl.DeleteBuffer(indexVBPO); } } /* * Struktura pro reprezentaci dat v bufferu */ [StructLayout(LayoutKind.Sequential)] struct VrcholANormala { public Vector3 position; public Vector3 normal; public float texX, texY; public VrcholANormala(float x, float y, float z, float nx, float ny, float nz, float texX, float texY) { position = new Vector3(x, y, z); normal = new Vector3(nx, ny, nz); this.texX = texX; this.texY = texY; } //Velikost struktury v bytech public static int SizeInBytes { get { return Marshal.SizeOf(typeof(VrcholANormala)); } } } }