OpenTK Textures - Transforms

Application, C# Code:
 using System;  
 using System.IO;  
 using System.Windows.Forms;  
 using OpenTK;  
 using OpenTK.Graphics;  
 using OpenTK.Graphics.OpenGL;  
 using MDLN.GLTools;  
   
 namespace OpenTKTest {  
     public class GLForm : Form {  
         protected GLControl cglGLView;  
         protected Label clblLog;  
         protected bool cbGLReady, cbMoveLeft, cbMoveUp;  
         protected GLShader cShader;  
         protected GLModel cModel;  
         protected int ciUniformBuffer;  
   
         public static void Main() {  
             GLForm frmGL;  
   
             //Create the form and give it control  
             frmGL = new GLForm();  
             Application.Run(frmGL);  
   
             return;  
         }  
   
          public GLForm() {  
              //Create redraw timer  
              Timer tmrRedraw;  
              tmrRedraw = new Timer();  
             tmrRedraw.Interval = 20; //20 ms timer  
             tmrRedraw.Tick += new EventHandler(RedrawTimer);  
             tmrRedraw.Start();  
   
             //Initialize Log label  
             clblLog = new Label();  
   
             clblLog.Top = 485;  
             clblLog.Left = 0;  
             clblLog.Width = 800;  
             clblLog.Height = 125;  
             clblLog.Text = "";  
   
             Controls.Add(clblLog);  
   
             cbGLReady = false;  
   
             cglGLView = new GLControl();  
   
             //Position and configure the controls  
             cglGLView.Top = 0;  
             cglGLView.Left = 0;  
             cglGLView.Width = 640;  
             cglGLView.Height = 480;  
   
             //Define callbacks for the controls  
             cglGLView.Load += new EventHandler(GLViewLoading);   
             cglGLView.Paint += new PaintEventHandler(GLViewPainting);   
             Controls.Add(cglGLView);  
   
             //Position and configure the form  
             this.Width = 775;  
             this.Height = 670;  
             this.FormBorderStyle = FormBorderStyle.FixedSingle;  
   
             //Initiailize variables  
             cbMoveLeft = false;  
             cbMoveUp = true;  
   
             return;  
         }  
   
         public int WriteLog(string strText) {  
             string strCurrText, strNewText;  
             string[] astrList;  
             int iCtr;  
   
             strCurrText = clblLog.Text;  
             astrList = strCurrText.Split('\n');  
   
             if (astrList.Length > 9) { //log shows too man lines, truncate  
                 strCurrText = "";  
                 for (iCtr = 0; iCtr < 10; iCtr++) {  
                     strCurrText = astrList[astrList.Length - iCtr - 1] + "\n" + strCurrText;  
                 }  
             } else { //Array has space, just add line  
                 strCurrText = clblLog.Text;  
             }  
   
             strNewText = strCurrText + "\n" + strText;  
   
             //Remove extraneous new lines  
             strNewText = strNewText.Replace("\n\n", "\n");  
             while (strNewText.Substring(0, 1) == "\n") {  
                 strNewText = strNewText.Substring(1, strNewText.Length - 2);  
             }  
   
             //Put the log in the label  
             clblLog.Text = strNewText;  
             return 0;  
          }  
   
         private void GLViewLoading(object oSender, EventArgs eaArgs) {  
             //The GLControl is now loading  
             Matrix4 pmatMatrix;  
             float fAspect;  
             float[] afUniform;  
             int[] aiBuffers;  
   
             WriteLog("GLControl: Loading...");  
             WriteLog("OpenGL Version: " + GL.GetString(StringName.Version));  
   
             //Setup GL  
             GL.ClearColor(0.0f, 0.0f, 0.2f, 0.0f);  
             GL.Enable(EnableCap.DepthTest);  
   
             //Setup the viewport  
             GL.Viewport(0, 0, cglGLView.Width, cglGLView.Height);  
             fAspect = cglGLView.Width / cglGLView.Height;  
             pmatMatrix = Matrix4.CreatePerspectiveFieldOfView(45 * (MathHelper.Pi / 180), fAspect, 0.1f, 100.0f);  
             GL.MatrixMode(MatrixMode.Projection);  
             GL.LoadMatrix(ref pmatMatrix);  
             GL.MatrixMode(MatrixMode.Modelview);  
   
             //Load shader  
             cShader = new GLShader();  
             cShader.AddUniform("Data", 0);  
             cShader.AddUniform("ModelData", 1);  
             cShader.AddAttribute("v3Location", 5);  
             cShader.AddAttribute("v2UVCoord", 6);  
             cShader.VertexFile = "Vertex.glsl";  
             cShader.FragmentFile = "Fragment.glsl";  
             if (cShader.BuildShader() == false) {  
                 WriteLog(cShader.ErrorDescription);  
             }  
   
             //Load model  
             cModel = new GLModel();  
             cModel.LoadOBJFile("Cube.obj");  
             cModel.SetBaseColor(1.0f, 0.0f, 1.0f, 1.0f);  
             cModel.LoadTexture("DiceTexture.png");  
             cModel.UniformID = cShader.FindUniformID("ModelData");  
             cModel.VertexAttributeID = cShader.FindAttributeID("v3Location");  
             cModel.UVCoordsAttributeID = cShader.FindAttributeID("v2UVCoord");  
             cModel.TranslateZ = -10;  
   
             //Setup our uniform data  
             afUniform = new float[20];  
   
             afUniform[0] = pmatMatrix.Row0.X;  
             afUniform[1] = pmatMatrix.Row1.X;  
             afUniform[2] = pmatMatrix.Row2.X;  
             afUniform[3] = pmatMatrix.Row3.X;  
             afUniform[4] = pmatMatrix.Row0.Y;  
             afUniform[5] = pmatMatrix.Row1.Y;  
             afUniform[6] = pmatMatrix.Row2.Y;  
             afUniform[7] = pmatMatrix.Row3.Y;  
             afUniform[8] = pmatMatrix.Row0.Z;  
             afUniform[9] = pmatMatrix.Row1.Z;  
             afUniform[10] = pmatMatrix.Row2.Z;  
             afUniform[11] = pmatMatrix.Row3.Z;  
             afUniform[12] = pmatMatrix.Row0.W;  
             afUniform[13] = pmatMatrix.Row1.W;  
             afUniform[14] = pmatMatrix.Row2.W;  
             afUniform[15] = pmatMatrix.Row3.W;  
   
             afUniform[16] = 0.5f;  
             afUniform[17] = 0.5f;  
             afUniform[18] = 1.0f;  
             afUniform[19] = 1.0f;  
   
             //Load uniform data  
             aiBuffers = new int[1];  
             GL.GenBuffers(aiBuffers.Length, aiBuffers);  
             ciUniformBuffer = aiBuffers[0];  
   
             GL.BindBuffer(BufferTarget.UniformBuffer, ciUniformBuffer);  
             GL.BufferData(BufferTarget.UniformBuffer, (IntPtr)(afUniform.Length * sizeof(float)), afUniform, BufferUsageHint.DynamicDraw);  
             GL.BindBufferBase(BufferTarget.UniformBuffer, cShader.FindUniformID("Data"), ciUniformBuffer);  
   
             //Done setting up GL for use  
             cbGLReady = true;  
   
             return;  
         }  
   
         private void GLViewPainting(object oSender, EventArgs eaArgs) {  
             if (cbGLReady == false) {//Control is not loaded, do nothing  
                 return;  
             }  
   
             //Specify Shader  
             GL.UseProgram(cShader.Program);  
   
             //Clear the GL View  
             GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);  
             GL.MatrixMode(MatrixMode.Modelview);  
   
             //Render the model  
             cModel.RenderObject();  
   
             //Drawing complete  
             cglGLView.SwapBuffers();  
   
             return;  
         }  
   
         private void RedrawTimer(object oSender, EventArgs eaArgs) {  
             if (cbMoveLeft == true) {  
                 cModel.TranslateX -= 0.05f;   
   
                 if (cModel.TranslateX < -3) {  
                     cbMoveLeft = false;  
                 }  
             } else {  
                 cModel.TranslateX += 0.05f;                   
   
                 if (cModel.TranslateX > 3) {  
                     cbMoveLeft = true;  
                 }  
             }  
   
             if (cbMoveUp == false) {  
                 cModel.TranslateY -= 0.05f;   
   
                 if (cModel.TranslateY < -2.5) {  
                     cbMoveUp = true;  
                 }  
             } else {  
                 cModel.TranslateY += 0.05f;                   
   
                 if (cModel.TranslateY > 2.5) {  
                     cbMoveUp = false;  
                 }  
             }  
   
             cModel.RotateX += 1.0f;  
             if (cModel.RotateX >= 360) {  
                 cModel.RotateX = 0.0f;  
             }  
   
             cModel.RotateY += 0.5f;  
             if (cModel.RotateY >= 360) {  
                 cModel.RotateY = 0.0f;  
             }  
   
             cModel.RotateZ += 1.5f;  
             if (cModel.RotateZ >= 360) {  
                 cModel.RotateZ = 0.0f;  
             }  
   
             cModel.ScaleX = (cModel.TranslateY + 3.5f) / 4.0f;  
             cModel.ScaleY = (cModel.TranslateY + 3.5f) / 4.0f;  
             cModel.ScaleZ = (cModel.TranslateY + 3.5f) / 4.0f;   
   
             GLViewPainting(null, null);  
         }  
     }  
 }  


GLTools Library, C# Code:
 using System;  
 using System.Collections.Generic;  
 using System.Drawing;  
 using System.Globalization;  
 using System.Reflection;  
 using System.IO;  
 using System.Windows.Forms;  
 using System.Xml;  
 using OpenTK;  
 using OpenTK.Graphics;  
 using OpenTK.Graphics.OpenGL;  
   
 [assembly: AssemblyProduct("OpenTK/OpenGL Library")]  
 [assembly: AssemblyCopyright("Copyright © Jason Beighel")]  
 [assembly: AssemblyTrademark("Mindlence")]  
 [assembly: AssemblyVersion("0.1.0.3")]  
 [assembly: AssemblyFileVersion("0.1.0.3")]  
   
 namespace MDLN {  
     namespace GLTools {  
         public static class GLUtil{  
             public static bool PackDataIntoUniformBuffer(ref float[] afBuffer, ref int iBaseIndex, Matrix4 m4Data) {  
                 afBuffer[iBaseIndex + 0] = m4Data.Row0.X;  
                 afBuffer[iBaseIndex + 1] = m4Data.Row1.X;  
                 afBuffer[iBaseIndex + 2] = m4Data.Row2.X;  
                 afBuffer[iBaseIndex + 3] = m4Data.Row3.X;  
   
                 afBuffer[iBaseIndex + 4] = m4Data.Row0.Y;  
                 afBuffer[iBaseIndex + 5] = m4Data.Row1.Y;  
                 afBuffer[iBaseIndex + 6] = m4Data.Row2.Y;  
                 afBuffer[iBaseIndex + 7] = m4Data.Row3.Y;  
   
                 afBuffer[iBaseIndex + 8] = m4Data.Row0.Z;  
                 afBuffer[iBaseIndex + 9] = m4Data.Row1.Z;  
                 afBuffer[iBaseIndex + 10] = m4Data.Row2.Z;  
                 afBuffer[iBaseIndex + 11] = m4Data.Row3.Z;  
   
                 afBuffer[iBaseIndex + 12] = m4Data.Row0.W;  
                 afBuffer[iBaseIndex + 13] = m4Data.Row1.W;  
                 afBuffer[iBaseIndex + 14] = m4Data.Row2.W;  
                 afBuffer[iBaseIndex + 15] = m4Data.Row3.W;  
   
                 iBaseIndex += 16;  
   
                 return true;  
             }  
   
             public static bool PackDataIntoUniformBuffer(ref float[] afBuffer, ref int iBaseIndex, Vector3 v3Data) {  
                 afBuffer[iBaseIndex + 0] = v3Data.X;  
                 afBuffer[iBaseIndex + 1] = v3Data.Y;  
                 afBuffer[iBaseIndex + 2] = v3Data.Z;  
                 afBuffer[iBaseIndex + 3] = 0.0f;  
   
                 iBaseIndex += 4;  
   
                 return true;  
             }   
         }  
   
         public class GLShader {  
             public enum ErrorCodes {None, CompileFail, LinkFail, InvalidAttrName};  
   
             private int ciProgram;  
             private ErrorCodes ceErrCode;  
             private string cstrErrDesc, cstrVertexFile, cstrFragmentFile, cstrName;  
             private List<ShaderVar> clUniformList, clAttribList;  
   
             public GLShader() {  
                 //Initilize class variables  
                 ciProgram = -1;  
                 ceErrCode = ErrorCodes.None;  
                 cstrErrDesc = "";  
                 clUniformList = new List<ShaderVar>();  
                 clAttribList = new List<ShaderVar>();  
             }  
   
             public string VertexFile {  
                 get {  
                     return cstrVertexFile;  
                 }  
   
                 set {  
                     cstrVertexFile = value;  
   
                     return;  
                 }  
             }  
   
             public string FragmentFile {  
                 get {  
                     return cstrFragmentFile;  
                 }  
   
                 set {  
                     cstrFragmentFile = value;  
   
                     return;  
                 }  
             }  
   
             public string Name {  
                 get {  
                     return cstrName;  
                 }  
   
                 set {  
                     cstrName = value;  
   
                     return;  
                 }  
             }  
   
             public int Program {  
                 get {  
                     if (ciProgram == -1) {  
                         BuildShader();  
                     }  
   
                     return ciProgram;  
                 }  
             }  
   
             public string ErrorDescription {  
                 get {  
                     return cstrErrDesc;  
                 }  
             }  
   
             public ErrorCodes ErrorCode {  
                 get {  
                     return ceErrCode;  
                 }  
             }  
   
             public bool AddUniform(string strName, int iID) {  
                 ShaderVar oNewVar;  
   
                 oNewVar = new ShaderVar(iID, strName);  
   
                 clUniformList.Add(oNewVar);  
   
                 return true;  
             }  
   
             public bool AddAttribute(string strName, int iID) {  
                 ShaderVar oNewVar;  
   
                 oNewVar = new ShaderVar(iID, strName);  
   
                 clAttribList.Add(oNewVar);  
   
                 return true;  
             }  
   
             public int FindUniformID(string strName) {  
                 foreach (ShaderVar oUniform in clUniformList) {  
                     if (oUniform.VariableName == strName) {  
                         return oUniform.VariableID;  
                     }  
                 }  
   
                 return -1;  
             }  
   
             public int FindAttributeID(string strName) {  
                 ceErrCode = ErrorCodes.None;  
                 cstrErrDesc = "";  
   
                 foreach (ShaderVar oAttr in clAttribList) {  
                     if (oAttr.VariableName == strName) {  
                         return oAttr.VariableID;  
                     }  
                 }  
   
                 ceErrCode = ErrorCodes.InvalidAttrName;  
                 cstrErrDesc = "Unable to find an attribute with the name " + strName;  
   
                 return -1;  
             }  
   
             public bool BuildShader() {  
                 int iUniformID, iStatus, iVertShader, iFragShader, iNewProgram;  
                 bool bRetVal = true;  
   
                 cstrErrDesc = "";  
                 ceErrCode = ErrorCodes.None;  
   
                 //Create Vertex shader  
                 iVertShader = GL.CreateShader(ShaderType.VertexShader);  
                 using (StreamReader srShader = new StreamReader(cstrVertexFile)) {  
                     GL.ShaderSource(iVertShader, srShader.ReadToEnd());  
                 }  
                 GL.CompileShader(iVertShader);  
           
                 GL.GetShader(iVertShader, ShaderParameter.CompileStatus, out iStatus);  
                 if (iStatus != 1) { //Failed to compile  
                     bRetVal = false;  
                     ceErrCode = ErrorCodes.CompileFail;  
                     cstrErrDesc = "Vertex Shader failed to compile.\n" + GL.GetShaderInfoLog(iVertShader) + "\n";  
                 }  
   
                 //Create Fragment shader  
                 iFragShader = GL.CreateShader(ShaderType.FragmentShader);  
                 using (StreamReader srShader = new StreamReader(cstrFragmentFile)) {  
                     GL.ShaderSource(iFragShader, srShader.ReadToEnd());  
                 }  
                 GL.CompileShader(iFragShader);  
           
                 GL.GetShader(iFragShader, ShaderParameter.CompileStatus, out iStatus);  
                 if (iStatus != 1) { //Failed to compile  
                     bRetVal = false;  
                     ceErrCode = ErrorCodes.CompileFail;  
                     cstrErrDesc = cstrErrDesc + "Fragment Shader failed to compile.\n" + GL.GetShaderInfoLog(iFragShader);  
                 }  
   
                 if (bRetVal != true) { //If a compile error happens, stop  
                     return bRetVal;  
                 }  
   
                 //Build the program  
                 iNewProgram = GL.CreateProgram();  
   
                 GL.AttachShader(iNewProgram, iVertShader);  
                 GL.AttachShader(iNewProgram, iFragShader);  
   
                 //Assign attribute buffers]  
                 foreach (ShaderVar oAttr in clAttribList) {  
                     GL.BindAttribLocation(iNewProgram, oAttr.VariableID, oAttr.VariableName);  
                 }  
   
                 //Link the program  
                 GL.LinkProgram(iNewProgram);  
                 GL.GetProgram(iNewProgram, ProgramParameter.LinkStatus, out iStatus);  
                 if (iStatus != 1) { //Failed to link  
                     bRetVal = false;  
                     ceErrCode = ErrorCodes.LinkFail;  
                     cstrErrDesc = "Shading program failed to link.\n" + GL.GetProgramInfoLog(iNewProgram);  
                 }  
   
                 if (bRetVal != true) { //If a link error happens, stop  
                     return bRetVal;  
                 }  
   
                 //Define uniform blocks  
                 foreach (ShaderVar oUniform in clUniformList) {  
                     iUniformID = GL.GetUniformBlockIndex(iNewProgram, oUniform.VariableName);  
                     GL.UniformBlockBinding(iNewProgram, iUniformID, oUniform.VariableID);  
                 }  
   
                 ciProgram = iNewProgram;  
   
                 //Cleanup  
                 GL.DeleteShader(iVertShader);  
                 GL.DeleteShader(iFragShader);  
                 return true;  
             }  
   
             private class ShaderVar {  
                 private int ciVarID;  
                 private string cstrVarName;  
   
                 public ShaderVar() : this(0, "") {} //Chained constructor  
   
                 public ShaderVar(int iID, string strName) {  
                     ciVarID = iID;  
                     cstrVarName = strName;  
                 }  
   
                 public string VariableName {  
                     get {  
                         return cstrVarName;  
                     }  
   
                     set {  
                         cstrVarName = value;  
                     }  
                 }  
   
                 public int VariableID {  
                     get {  
                         return ciVarID;  
                     }  
   
                     set {  
                         ciVarID = value;  
                     }  
                 }  
             }  
         }  
   
         public class GLModel {  
             private Vector3[] cav3Vertexes, cav3Normals, cav3Transforms;  
             private Vector2[] cav2UVCoords;  
             private bool cbUniformChange, cbVertexChange, cbNormalChange, cbUVCoordsChange;  
             private Vector4 cv4BaseColor;  
             private int ciUniformBuffer, ciUniformID, ciVertexBuffer, ciVertexID, ciTextureID, ciUVCoordsBuffer, ciUVCoordsID;  
             private string cstrErrDesc;  
   
             public GLModel() {  
                 int[] aiBuffList;  
   
                 cbVertexChange = true;  
                 cbNormalChange = true;  
                 cbUVCoordsChange = true;  
                 cbUniformChange = true;  
   
                 ciUniformBuffer = -1;  
                 ciUniformID = -1;  
                 ciVertexBuffer = -1;  
                 ciVertexID = -1;  
                 ciTextureID = -1;  
                 ciUVCoordsID = -1;  
   
                 cav3Transforms = new Vector3[3]; //0 = scale, 1 = rotation, 2 = translate  
                 cav3Transforms[0].X = 1.0f;  
                 cav3Transforms[0].Y = 1.0f;  
                 cav3Transforms[0].Z = 1.0f;  
   
                 cav3Transforms[1].X = 0.0f;  
                 cav3Transforms[1].Y = 0.0f;  
                 cav3Transforms[1].Z = 0.0f;  
   
                 cav3Transforms[2].X = 0.0f;  
                 cav3Transforms[2].Y = 0.0f;  
                 cav3Transforms[2].Z = 0.0f;  
   
                 aiBuffList = new int[4];  
                 GL.GenBuffers(aiBuffList.Length, aiBuffList);  
                 ciVertexBuffer = aiBuffList[0];  
                 ciUniformBuffer = aiBuffList[1];  
                 ciUVCoordsBuffer = aiBuffList[2];  
             }  
   
             public Vector4 BaseColor {  
                 get {  
                     return cv4BaseColor;  
                 }  
             }  
   
             public int UniformBuffer {  
                 get {  
                     return ciUniformBuffer;  
                 }  
   
                 set {  
                     ciUniformBuffer = value;  
                 }  
             }  
   
             public int UniformID {  
                 get {  
                     return ciUniformID;  
                 }  
   
                 set {  
                     ciUniformID = value;  
                 }  
             }  
   
             public int VertexAttributeID {  
                 get {  
                     return ciVertexID;  
                 }  
   
                 set {  
                     ciVertexID = value;  
                 }  
             }  
   
             public int UVCoordsAttributeID {  
                 get {  
                     return ciUVCoordsID;  
                 }  
   
                 set {  
                     ciUVCoordsID = value;  
                 }  
             }  
   
             public string ErrorDescription {  
                 get {  
                     return cstrErrDesc;  
                 }  
             }  
   
             public float TranslateX {  
                 get {  
                     return cav3Transforms[2].X;  
                 }  
   
                 set {  
                     cbNormalChange = true;  
                     cav3Transforms[2].X = value;  
                 }  
             }  
   
             public float TranslateY {  
                 get {  
                     return cav3Transforms[2].Y;  
                 }  
   
                 set {  
                     cbNormalChange = true;  
                     cav3Transforms[2].Y = value;  
                 }  
             }  
   
             public float TranslateZ {  
                 get {  
                     return cav3Transforms[2].Z;  
                 }  
   
                 set {  
                     cbNormalChange = true;  
                     cav3Transforms[2].Z = value;  
                 }  
             }  
   
             public float ScaleX {  
                 get {  
                     return cav3Transforms[0].X;  
                 }  
   
                 set {  
                     cbNormalChange = true;  
                     cav3Transforms[0].X = value;  
                 }  
             }  
   
             public float ScaleY {  
                 get {  
                     return cav3Transforms[0].Y;  
                 }  
   
                 set {  
                     cbNormalChange = true;  
                     cav3Transforms[0].Y = value;  
                 }  
             }  
   
             public float ScaleZ {  
                 get {  
                     return cav3Transforms[0].Z;  
                 }  
   
                 set {  
                     cbNormalChange = true;  
                     cav3Transforms[0].Z = value;  
                 }  
             }  
   
             public float RotateX {  
                 get {  
                     return cav3Transforms[1].X * (180 / MathHelper.Pi);  
                 }  
   
                 set {  
                     cbNormalChange = true;  
                     cav3Transforms[1].X = value * (MathHelper.Pi / 180);  
                 }  
             }  
   
             public float RotateY {  
                 get {  
                     return cav3Transforms[1].Y * (180 / MathHelper.Pi);  
                 }  
   
                 set {  
                     cbNormalChange = true;  
                     cav3Transforms[1].Y = value * (MathHelper.Pi / 180);  
                 }  
             }  
   
             public float RotateZ {  
                 get {  
                     return cav3Transforms[1].Z * (180 / MathHelper.Pi);  
                 }  
   
                 set {  
                     cbNormalChange = true;  
                     cav3Transforms[1].Z = value * (MathHelper.Pi / 180);  
                 }  
             }  
   
             public bool SetBaseColor(float fRed, float fGreen, float fBlue, float fAlpha) {  
                 cv4BaseColor.X = fRed;  
                 cv4BaseColor.Y = fGreen;  
                 cv4BaseColor.Z = fBlue;  
                 cv4BaseColor.W = fAlpha;  
   
                 return true;  
             }  
   
             public bool LoadOBJFile(string strFile) {  
                 string strChunk;  
                 string[] astrLines, astrLineParts, astrFaceParts;  
                 int iCtr, iCnt, iFaceCount, iCurrVert, iSrcIndex;  
                 List<Vector3> lv3Vertexes, lv3Normals;  
                 List<Vector2> lv2UVCoords;  
                 Vector3 v3New;  
                 Vector2 v2New;  
                 StreamReader srModel;  
   
                 cstrErrDesc = "";  
   
                 iFaceCount = 0;  
   
                 lv3Vertexes = new List<Vector3>();  
                 lv3Normals = new List<Vector3>();  
                 v3New = new Vector3();  
   
                 lv2UVCoords = new List<Vector2>();  
                 v2New = new Vector2();  
   
                 srModel = new StreamReader(strFile);  
                 strChunk = srModel.ReadToEnd();  
                 srModel.Close();  
   
                 astrLines = strChunk.Split('\n');  
   
                 //First pass through the file: Load all vertex information  
                 for (iCtr = 0; iCtr < astrLines.Length; iCtr++) {  
                     astrLineParts = astrLines[iCtr].Split(' ');  
   
                     switch (astrLineParts[0]) {  
                         case "v" : //Vertex coordinates  
                             v3New.X = float.Parse(astrLineParts[1], CultureInfo.InvariantCulture.NumberFormat);  
                             v3New.Y = float.Parse(astrLineParts[2], CultureInfo.InvariantCulture.NumberFormat);  
                             v3New.Z = float.Parse(astrLineParts[3], CultureInfo.InvariantCulture.NumberFormat);  
   
                             lv3Vertexes.Add(v3New);  
                             break;  
                         case "vt" : //Vertex texture coordinates (UV Coordinates)  
                             v2New.X = float.Parse(astrLineParts[1], CultureInfo.InvariantCulture.NumberFormat);  
                             v2New.Y = float.Parse(astrLineParts[2], CultureInfo.InvariantCulture.NumberFormat);  
   
                             lv2UVCoords.Add(v2New);  
                             break;  
                         case "vn" : //Vertex normal  
                             v3New.X = float.Parse(astrLineParts[1], CultureInfo.InvariantCulture.NumberFormat);  
                             v3New.Y = float.Parse(astrLineParts[2], CultureInfo.InvariantCulture.NumberFormat);  
                             v3New.Z = float.Parse(astrLineParts[3], CultureInfo.InvariantCulture.NumberFormat);  
   
                             lv3Normals.Add(v3New);  
                             break;  
                         case "f" : //Face information, just count them  
                             iFaceCount++;  
                             break;  
                         default : //Unknown line information, skip it  
                             break;  
                     }  
                 }  
   
                 //Resize the class data arrays based on the number of faces  
                 cav3Vertexes = new Vector3[iFaceCount * 3]; //1FaceCount has the number of faces  
                 cav3Normals = new Vector3[iFaceCount * 3]; //Each face has 3 vertexes  
   
                 cav2UVCoords = new Vector2[iFaceCount * 3];  
   
                 //Second pass through the file: process all faces  
                 iCurrVert = 0;  
                 for (iCtr = 0; iCtr < astrLines.Length; iCtr++) {  
                     astrLineParts = astrLines[iCtr].Split(' ');  
   
                     switch (astrLineParts[0]) {  
                         case "f" : //Face information  
                             for (iCnt = 1; iCnt <= 3; iCnt++) {  
                                 astrFaceParts = astrLineParts[iCnt].Split('/');  
   
                                 //Copy vertex coordinates  
                                 iSrcIndex = Convert.ToInt32(astrFaceParts[0]) - 1; //Obj indexes start at 1, C# arrays start at 0  
                                 cav3Vertexes[iCurrVert].X = lv3Vertexes[iSrcIndex].X;  
                                 cav3Vertexes[iCurrVert].Y = lv3Vertexes[iSrcIndex].Y;  
                                 cav3Vertexes[iCurrVert].Z = lv3Vertexes[iSrcIndex].Z;  
   
                                 //Copy UV Coordinates  
                                 iSrcIndex = Convert.ToInt32(astrFaceParts[1]) - 1;  
                                 cav2UVCoords[iCurrVert].X = lv2UVCoords[iSrcIndex].X;  
                                 cav2UVCoords[iCurrVert].Y = lv2UVCoords[iSrcIndex].Y;  
   
                                 //Copy Normal values  
                                 iSrcIndex = Convert.ToInt32(astrFaceParts[2]) - 1;  
                                 cav3Normals[iCurrVert].X = lv3Normals[iSrcIndex].X;  
                                 cav3Normals[iCurrVert].Y = lv3Normals[iSrcIndex].Y;  
                                 cav3Normals[iCurrVert].Z = lv3Normals[iSrcIndex].Z;  
   
                                 iCurrVert++;  
                             }  
                             break;  
                         default : //Ignore all other lines  
                             break;  
                     }  
                 }  
   
                 //Mark the arrays as needing updated  
                 cbVertexChange = true;  
                 cbNormalChange = true;  
                 cbUVCoordsChange = true;  
   
                 return true;  
             }  
   
             public bool LoadTexture(string strFile) {  
                 Bitmap bmpTexture;  
                 System.Drawing.Imaging.BitmapData oTextureData;  
                 Rectangle rctImageBounds;  
   
                 //Load the image from file  
                 bmpTexture = new Bitmap(strFile);  
   
                 //Convert the image to a form compatible with openGL  
                 rctImageBounds = new Rectangle(0, 0, bmpTexture.Width, bmpTexture.Height);  
   
                 oTextureData = bmpTexture.LockBits(rctImageBounds, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);  
   
                 //Generate a new texture  
                 ciTextureID = GL.GenTexture();  
   
                 //Copy the image data into the texture  
                 GL.BindTexture(TextureTarget.Texture2D, ciTextureID);  
   
                 GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmpTexture.Width, bmpTexture.Height, 0, PixelFormat.Rgb, PixelType.UnsignedByte, oTextureData.Scan0);  
   
                 GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (float)TextureMinFilter.Linear);  
                 GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (float)TextureMagFilter.Linear);  
   
                 bmpTexture.UnlockBits(oTextureData);  
   
                 return true;  
             }  
   
             public bool RenderObject() {  
                 float[] afUniformData;  
                 int iIndex;  
   
                 cstrErrDesc = "";  
   
                 //Be sure the buffer objects have been specified  
                 if ((ciUniformID == -1)||(ciUniformBuffer == -1)) {  
                     cstrErrDesc = "Unable to render with no Uniform Buffer or ID specified.";  
                     return false;  
                 }  
   
                 if ((ciVertexBuffer == -1)||(ciVertexID == -1)) {  
                     cstrErrDesc = "Unable to render with no Vertex Buffer or ID specified.";  
                     return false;      
                 }  
   
                 //Check if buffer data needs refreshed  
                 if (cbVertexChange == true) {  
                     GL.BindBuffer(BufferTarget.ArrayBuffer, ciVertexBuffer);  
                     GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(cav3Vertexes.Length * Vector3.SizeInBytes), cav3Vertexes, BufferUsageHint.DynamicDraw);  
                     cbVertexChange = false;  
                 }  
   
                 if (cbUVCoordsChange == true) {  
                     GL.BindBuffer(BufferTarget.ArrayBuffer, ciUVCoordsBuffer);  
                     GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(cav2UVCoords.Length * Vector2.SizeInBytes), cav2UVCoords, BufferUsageHint.DynamicDraw);  
                     cbVertexChange = false;  
                 }  
   
                 if (cbNormalChange == true) {  
   
                     cbNormalChange = false;  
                 }  
   
                 if (cbUniformChange == true) {  
                     //Set Uniform buffer data  
                     afUniformData = new float[4 * 4];  
   
                     afUniformData[0] = cv4BaseColor.X;  
                     afUniformData[1] = cv4BaseColor.Y;  
                     afUniformData[2] = cv4BaseColor.Z;  
                     afUniformData[3] = cv4BaseColor.W;  
   
                     iIndex = 4;  
   
                     GLUtil.PackDataIntoUniformBuffer(ref afUniformData, ref iIndex, cav3Transforms[0]);  
                     GLUtil.PackDataIntoUniformBuffer(ref afUniformData, ref iIndex, cav3Transforms[1]);  
                     GLUtil.PackDataIntoUniformBuffer(ref afUniformData, ref iIndex, cav3Transforms[2]);  
   
                     GL.BindBuffer(BufferTarget.UniformBuffer, ciUniformBuffer);  
                     GL.BufferData(BufferTarget.UniformBuffer, (IntPtr)(afUniformData.Length * sizeof(float)), afUniformData, BufferUsageHint.DynamicDraw);  
                 }  
   
                 //Draw the model  
                 if (ciTextureID != -1) {//A texture is loaded, use it  
                     GL.BindTexture(TextureTarget.Texture2D, ciTextureID);  
                 }  
   
                 GL.BindBuffer(BufferTarget.UniformBuffer, ciUniformBuffer);  
                 GL.BindBufferBase(BufferTarget.UniformBuffer, ciUniformID, ciUniformBuffer);  
   
                 GL.BindBuffer(BufferTarget.ArrayBuffer, ciVertexBuffer);  
                 GL.EnableVertexAttribArray(ciVertexID);  
                 GL.VertexAttribPointer(ciVertexID, 3, VertexAttribPointerType.Float, false, Vector3.SizeInBytes, 0);  
   
                 GL.BindBuffer(BufferTarget.ArrayBuffer, ciUVCoordsBuffer);  
                 GL.EnableVertexAttribArray(ciUVCoordsID);  
                 GL.VertexAttribPointer(ciUVCoordsID, 2, VertexAttribPointerType.Float, false, Vector2.SizeInBytes, 0);  
   
                 GL.DrawArrays(BeginMode.Triangles, 0, cav3Vertexes.Length);  
                 GL.DisableVertexAttribArray(ciVertexID);  
                 GL.DisableVertexAttribArray(ciUVCoordsID);  
   
                 return true;  
             }  
         }  
     }  
 }  
   


Vertex Shader, GLSL Code:
 #version 130  
 #extension GL_ARB_uniform_buffer_object : enable  
   
 uniform Data {  
     mat4 m4Projection;  
     vec4 v4BaseColor;  
 };  
   
 uniform ModelData {  
     vec4 v4ModelColor;  
     vec4 v3ModelScale;  
     vec4 v3ModelRotate;  
     vec4 v3ModelTranslate;  
 };  
   
 attribute vec3 v3Location;  
 attribute vec2 v2UVCoord;  
   
 varying vec4 v4FragColor;  
 varying vec2 v2UV;  
   
 void main() {  
     mat4 m4Scale, m4Translate, m4RotateX, m4RotateY, m4RotateZ;  
   
     m4Translate = mat4(1.0);  
     m4Translate[0][3] = v3ModelTranslate.x;  
     m4Translate[1][3] = v3ModelTranslate.y;  
     m4Translate[2][3] = v3ModelTranslate.z;  
   
     m4Scale = mat4(1.0);  
     m4Scale[0][0] = v3ModelScale.x;  
     m4Scale[1][1] = v3ModelScale.y;  
     m4Scale[2][2] = v3ModelScale.z;  
   
     m4RotateX = mat4(1.0);  
     m4RotateX[1][1] = cos(v3ModelRotate.x);  
     m4RotateX[1][2] = -1 * sin(v3ModelRotate.x);  
     m4RotateX[2][1] = sin(v3ModelRotate.x);  
     m4RotateX[2][2] = cos(v3ModelRotate.x);  
   
     m4RotateY = mat4(1.0);  
     m4RotateY[0][0] = cos(v3ModelRotate.y);  
     m4RotateY[0][2] = sin(v3ModelRotate.y);  
     m4RotateY[2][0] = -1 * sin(v3ModelRotate.y);  
     m4RotateY[2][2] = cos(v3ModelRotate.y);  
   
     m4RotateZ = mat4(1.0);  
     m4RotateZ[0][0] = cos(v3ModelRotate.z);  
     m4RotateZ[0][1] = -1 * sin(v3ModelRotate.z);  
     m4RotateZ[1][0] = sin(v3ModelRotate.z);  
     m4RotateZ[1][1] = cos(v3ModelRotate.z);  
   
     gl_Position = vec4(v3Location, 1.0) * m4Scale * m4RotateX * m4RotateY * m4RotateZ * m4Translate * m4Projection;  
   
     v4FragColor = v4ModelColor;  
     v2UV = v2UVCoord;  
 }  


Fragment Shader, GLSL Code:
 #version 130  
 #extension GL_ARB_uniform_buffer_object : enable  
   
 uniform Data {  
     mat4 m4Projection;  
     vec4 v4BaseColor;  
 };  
   
 uniform sampler2D sSampler;  
   
 uniform ModelData {  
     vec4 v4ModelColor;  
     vec4 v3ModelScale;  
     vec4 v3ModelRotate;  
     vec4 v3ModelTranslate;  
 };  
   
 varying vec4 v4FragColor;  
 varying vec2 v2UV;  
   
 void main() {  
     gl_FragColor = texture(sSampler, v2UV).rgba;  
 }  


Model Data, OBJ File:
 # Blender v2.69 (sub 0) OBJ File: ''  
 # www.blender.org  
 mtllib Cube.mtl  
 o Cube_Cube.001  
 v 1.000000 -1.000000 -1.000000  
 v 1.000000 -1.000000 1.000000  
 v -1.000000 -1.000000 1.000000  
 v -1.000000 -1.000000 -1.000000  
 v 1.000000 1.000000 -1.000000  
 v 1.000000 1.000000 1.000000  
 v -1.000000 1.000000 1.000000  
 v -1.000000 1.000000 -1.000000  
 #1 face  
 vt 0.000000 0.000000  
 vt 0.000000 0.222656  
 vt 0.222656 0.000000  
 vt 0.222656 0.222656  
 #2 face  
 vt 0.225900 0.000000  
 vt 0.225900 0.222656  
 vt 0.444900 0.000000  
 vt 0.444900 0.222656  
 #3 face  
 vt 0.449900 0.000000  
 vt 0.449900 0.222656  
 vt 0.669400 0.000000  
 vt 0.669400 0.222656  
 #4 face  
 vt 0.674400 0.000000  
 vt 0.674400 0.222656  
 vt 0.893500 0.000000  
 vt 0.893500 0.222656  
 #5 face  
 vt 0.000000 0.225900  
 vt 0.000000 0.444900  
 vt 0.222656 0.225900  
 vt 0.222656 0.444900  
 #6 face  
 vt 0.225900 0.225900  
 vt 0.225900 0.444900  
 vt 0.444900 0.225900  
 vt 0.444900 0.444900  
   
 vn 0.000000 0.000000 -1.000000  
 vn -1.000000 -0.000000 -0.000000  
 vn -0.000000 -0.000000 1.000000  
 vn -0.000001 0.000000 1.000000  
 vn 1.000000 -0.000000 0.000000  
 vn 1.000000 0.000000 0.000001  
 vn 0.000000 1.000000 -0.000000  
 vn -0.000000 -1.000000 0.000000  
 usemtl None  
 s off  
 #left/1 face  
 f 3/4/2 7/3/2 8/1/2  
 f 3/4/2 8/1/2 4/2/2  
 #bottom/2 face  
 f 1/8/8 2/7/8 3/5/8  
 f 1/8/8 3/5/8 4/6/8  
 #back/3 face  
 f 5/9/1 1/10/1 4/12/1  
 f 5/9/1 4/12/1 8/11/1  
 #right/4 face  
 f 1/16/5 5/15/5 2/14/5  
 f 5/15/6 6/13/6 2/14/6  
 #top/5 face  
 f 5/19/7 8/17/7 6/20/7  
 f 8/17/7 7/18/7 6/20/7  
 #front/6 face  
 f 2/24/3 6/23/3 3/22/3  
 f 6/23/4 7/21/4 3/22/4  

No comments:

Post a Comment