Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Runtime.CompilerServices;
- using System.Security.Cryptography.X509Certificates;
- using System.Threading.Tasks;
- using GrimoireTactics.Framework.Maths;
- using GrimoireTactics.Framework.OpenGL.Texturing;
- using OpenTK;
- using OpenTK.Graphics.OpenGL;
- namespace GrimoireTactics.Framework.OpenGL.Modeling
- {
- public class WavefrontModel
- {
- public List<Vector3> Vertices;
- public List<Vector2> TexCoords;
- public List<Vector3> Normals;
- public List<Face> Faces;
- public string ModelSource;
- public string Name;
- public Material Material;
- /// <summary>
- /// A static buffer used by all models when they are loaded.
- /// </summary>
- private static readonly string[] FileBuffer = new string[15];
- /// <summary>
- /// A static buffer used by all models when they are loaded.
- /// </summary>
- private static readonly string[] IndiceBuffer = new string[3];
- /// <summary>
- /// A static buffer used by all models when they are loaded.
- /// </summary>
- private static readonly FaceIndices[] VerticesIndexBuffer = new FaceIndices[3];
- public static readonly WavefrontBufferSettings DefaultBuffer = new WavefrontBufferSettings(300, 300, 300, 300);
- /// <summary>
- /// The Triangle Count of this model.
- /// </summary>
- public int TriCount
- {
- get
- {
- return this.Faces.Count;
- }
- }
- public WavefrontModel()
- {
- Initialize(new WavefrontBufferSettings(0, 0, 0, 0));
- }
- public WavefrontModel(int buffer)
- {
- Initialize(new WavefrontBufferSettings(buffer,buffer,buffer,buffer));
- }
- public WavefrontModel(int verticesBuffer, int texCoordsBuffer, int normalsBuffer, int facesBuffer)
- {
- Initialize(new WavefrontBufferSettings(verticesBuffer,texCoordsBuffer,normalsBuffer,facesBuffer));
- }
- public WavefrontModel(string modelPath, Material material)
- {
- this.ModelSource = modelPath;
- this.Material = material;
- Initialize(new WavefrontBufferSettings(0, 0, 0, 0));
- }
- public WavefrontModel(string modelPath)
- {
- this.ModelSource = modelPath;
- this.Material = null;
- Initialize(new WavefrontBufferSettings(0,0,0,0));
- }
- public WavefrontModel(string modelPath, WavefrontBufferSettings buffers)
- {
- this.ModelSource = modelPath;
- this.Material = null;
- Initialize(buffers);
- }
- public WavefrontModel(string modelPath, Material material, WavefrontBufferSettings buffers)
- {
- this.ModelSource = modelPath;
- this.Material = material;
- Initialize(buffers);
- }
- private void Initialize(WavefrontBufferSettings buffers)
- {
- this.Vertices = new List<Vector3>(buffers.VerticeBuffer);
- this.TexCoords = new List<Vector2>(buffers.TexCoordBuffer);
- this.Normals = new List<Vector3>(buffers.NormalBuffer);
- this.Faces = new List<Face>(buffers.FacesBuffer);
- }
- /// <summary>
- /// Loads a model from the desired Wavefront.obj source given
- /// at constructor initialization.
- /// </summary>
- public void Load()
- {
- Load(this.ModelSource);
- }
- /// <summary>
- /// Loads a model from a Wavefront.obj located on disk.
- /// </summary>
- /// <param name="file"></param>
- public void Load(string file)
- {
- Parse(File.ReadAllLines(file));
- }
- /// <summary>
- /// Initializes this model with the data provided.
- /// </summary>
- /// <param name="data"></param>
- public void Load(string[] data)
- {
- Parse(data);
- }
- /// <summary>
- /// Clears Vertices, TexCoords, Faces, and Normals.
- /// </summary>
- public void ClearData()
- {
- Vertices.Clear();
- TexCoords.Clear();
- Faces.Clear();
- Normals.Clear();
- }
- /// <summary>
- /// Current Benchmarked time(Warm boot)
- ///
- /// 244kb Wavefront OBJ (8297 lines)
- /// 00:00:00.0013752
- ///
- /// If you try to optimize this anymore than I already have,
- /// I feel so very, very, very sorry for you. You poor, pathetic soul.
- /// </summary>
- /// <param name="data"></param>
- private void Parse(string[] data)
- {
- int numberOfLinesInFile = data.Length;
- for (int line = 0; line < numberOfLinesInFile; line++)
- {
- string[] lineTokens = SplitStringFast(data[line], ' ', FileBuffer);
- switch (lineTokens[0])
- {
- case "v": // Vector
- Vector3 vector = new Vector3
- {
- X = ParseFloatFast(lineTokens[1]),
- Y = ParseFloatFast(lineTokens[2]),
- Z = ParseFloatFast(lineTokens[3])
- };
- Vertices.Add(vector);
- break;
- case "vt": // Texture Coordinate
- Vector2 textureCoordinate = new Vector2
- {
- X = ParseFloatFast(lineTokens[1]), // U
- Y = -ParseFloatFast(lineTokens[2]) // V (Inverted)
- };
- TexCoords.Add(textureCoordinate);
- break;
- case "vn": // Normal
- Vector3 normal = new Vector3
- {
- X = ParseFloatFast(lineTokens[1]),
- Y = ParseFloatFast(lineTokens[2]),
- Z = ParseFloatFast(lineTokens[3])
- };
- Normals.Add(normal);
- break;
- case "f": // Face (Triangle indices)
- for (int i = 0; i < 3; i++)
- {
- string[] parameters = SplitStringFast(lineTokens[i + 1], '/', IndiceBuffer);
- FaceIndices indices = new FaceIndices
- {
- Vertex = ParseUInt32Fast(parameters[0]) - 1,
- Texture = ParseUInt32Fast(parameters[1]) - 1,
- Normal = ParseUInt32Fast(parameters[2]) - 1
- };
- VerticesIndexBuffer[i] = indices;
- }
- Faces.Add(new Face(VerticesIndexBuffer[0], VerticesIndexBuffer[1], VerticesIndexBuffer[2]));
- break;
- }
- }
- }
- /// <summary>
- /// A custom implementation of Int32.Parse. This
- /// function is, on average, 5-6x faster than the one
- /// offered by .NET. This function assumes that the string
- /// given will yield a positive integer.
- /// </summary>
- /// <param name="value"></param>
- /// <returns></returns>
- private static int ParseUInt32Fast(string value)
- {
- int result = 0;
- int length = value.Length; // Squeeze out every last drop!
- for (int i = 0; i < length; i++)
- {
- result = 10 * result + (value[i] - 48);
- }
- return result;
- }
- /// <summary>
- /// A custom implementation of String.Split(). Realistically, this
- /// function is not much faster than what .NET offers; it gains speed
- /// more from a preset buffer mechanism.
- /// </summary>
- /// <param name="value"></param>
- /// <param name="delimiter"></param>
- /// <param name="buffer"></param>
- /// <returns></returns>
- private static string[] SplitStringFast(string value, char delimiter, string[] buffer)
- {
- int resultIndex = 0;
- int startIndex = 0;
- int length = value.Length;
- for (int i = 0; i < length; i++)
- {
- if (value[i] == delimiter)
- {
- buffer[resultIndex] = value.Substring(startIndex, i - startIndex);
- resultIndex++;
- startIndex = i + 1;
- }
- }
- buffer[resultIndex] = value.Substring(startIndex, value.Length - startIndex);
- return buffer;
- }
- /// <summary>
- /// A custom implementation of Float.Parse. This
- /// function is, on average, 5-6x faster than the one
- /// offered by .NET
- /// </summary>
- /// <param name="inputData">The inputData.</param>
- /// <returns></returns>
- private static float ParseFloatFast(string inputData)
- {
- float result = 0;
- int position = 0;
- int inputLength = inputData.Length;
- char firstCharacter = inputData[0];
- float negativeSign = 1;
- if (firstCharacter == '-')
- {
- negativeSign = -1;
- ++position;
- }
- while (true)
- {
- if (position >= inputLength)
- {
- return negativeSign * result;
- }
- firstCharacter = inputData[position++];
- if (firstCharacter < '0' || firstCharacter > '9')
- {
- break;
- }
- result = (float)((result * 10.0) + (firstCharacter - '0'));
- }
- float exponent = 0.1f;
- while (position < inputLength)
- {
- firstCharacter = inputData[position++];
- result += (firstCharacter - '0') * exponent;
- exponent *= 0.1f;
- }
- return negativeSign * result;
- }
- /// <summary>
- /// Renders the Model using deprecated immediate mode. This
- /// function exists only for testing purposes.
- /// </summary>
- public void Render()
- {
- GL.Enable(EnableCap.Texture2D);
- GL.Color3(Material.AmbientColor);
- GL.BindTexture(TextureTarget.Texture2D, Material.Diffuse);
- GL.Begin(PrimitiveType.Triangles);
- for (int i = 0; i < Faces.Count; i++)
- {
- for (int index = 0; index < Faces[i].Indices.Length; index++)
- {
- Vector3 v = Vertices[Faces[i].Indices[index].Vertex];
- Vector3 n = Normals[Faces[i].Indices[index].Normal];
- Vector2 tc = TexCoords[Faces[i].Indices[index].Texture];
- GL.Normal3(n.X, n.Y, n.Z);
- GL.TexCoord2(tc.X, tc.Y);
- GL.Vertex3(v.X, v.Y, v.Z);
- }
- }
- GL.End();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement