GLModel Class v0.1.0.1 - 01-02-2014

using OpenTK;
using OpenTK.Graphics.OpenGL;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Windows.Forms;

[assembly: AssemblyProduct("OpenTK/OpenGL Library")]
[assembly: AssemblyCopyright("Copyright © Jason Beighel")]
[assembly: AssemblyTrademark("Mindlence")]
[assembly: AssemblyVersion("0.1.0.1")]
[assembly: AssemblyFileVersion("0.1.0.1")]

namespace MDLN {
 namespace GLTools {
  class GLModel {
   private Vector3[] cav3Vertexes, cav3Normals;
   private Vector2[] cav2UVCoords;
   private bool cbVertexChange, cbNormalChange, cbUVCoordsChange;
   private Vector4 cv4BaseColor;
   private int ciUniformBuffer, ciUniformID, ciVertexBuffer, ciVertexID;
   private string cstrErrDesc;

   public GLModel() {
    int[] aiBuffList;

    cbVertexChange = true;
    cbNormalChange = true;
    cbUVCoordsChange = true;

    ciUniformBuffer = -1;
    ciUniformID = -1;
    ciVertexBuffer = -1;
    ciVertexID = -1;

    aiBuffList = new int[1];
    GL.GenBuffers(aiBuffList.Length, aiBuffList);
    ciVertexBuffer = aiBuffList[0];
   }

   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 string ErrorDescription {
    get {
     return cstrErrDesc;
    }
   }

   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 lv3Vertexes, lv3Normals;
    List lv2UVCoords;
    Vector3 v3New;
    Vector2 v2New;
    StreamReader srModel;

    cstrErrDesc = "";

    iFaceCount = 0;

    lv3Vertexes = new List();
    lv3Normals = new List();
    v3New = new Vector3();

    lv2UVCoords = new List();
    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 RenderObject() {
    cstrErrDesc = "";
    float[] afUniformData;

    //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) {
    cstrErrDesc = cstrErrDesc + "Loading cube data, " + cav3Vertexes.Length + " vertices | size : " + (cav3Vertexes.Length * Vector3.SizeInBytes) + " \n";
     GL.BindBuffer(BufferTarget.ArrayBuffer, ciVertexBuffer);
     GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(cav3Vertexes.Length * Vector3.SizeInBytes), cav3Vertexes, BufferUsageHint.DynamicDraw);
     cbVertexChange = false;
    }

    //Set Uniform buffer data
    afUniformData = new float[4];

    afUniformData[0] = cv4BaseColor.X;
    afUniformData[1] = cv4BaseColor.Y;
    afUniformData[2] = cv4BaseColor.Z;
    afUniformData[3] = cv4BaseColor.W;

    GL.BindBuffer(BufferTarget.UniformBuffer, ciUniformBuffer);
    GL.BufferData(BufferTarget.UniformBuffer, (IntPtr)(afUniformData.Length * sizeof(float)), afUniformData, BufferUsageHint.DynamicDraw);
    GL.BindBufferBase(BufferTarget.UniformBuffer, ciUniformID, ciUniformBuffer);

    //Draw the model
    GL.BindBuffer(BufferTarget.ArrayBuffer, ciVertexBuffer);
    GL.EnableVertexAttribArray(ciVertexID);
    GL.VertexAttribPointer(ciVertexID, 3, VertexAttribPointerType.Float, false, Vector3.SizeInBytes, 0);

    GL.DrawArrays(BeginMode.Triangles, 0, cav3Vertexes.Length);
    GL.DisableVertexAttribArray(ciVertexID);

    return true;
   }
  }
 }
}

No comments:

Post a Comment