|
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Tao.OpenGl;
using AGE_Engine3D.Math;
using AGE_Engine3D.RenderObjects;
namespace AGE_Engine3D.RenderObjects
{
class MeshContainer : IMeshResource
{
#region Fields
public List<BaseMesh> Meshes = null;
public List<AGE_Vector3Df> PositionList;
public List<AGE_Vector3Df> NormalList;
public List<AGE_TextureCoordinate2f> TextureList;
public List<Material> Materials;
string Name = "Untitled";
// Track whether Dispose has been called.
private bool disposed = false;
#endregion
#region ResourceInterface
public string ResourceName { get { return this.Name; } }
#region Implement IDisposable Methods
private void CleanUp()
{
foreach (BaseMesh Mesh in Meshes)
Mesh.Dispose();
}
// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be disposed.
private void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if (!this.disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if (disposing)
{
// Dispose managed resources.
// Nothing Todo...
}
// Call the appropriate methods to clean up
// unmanaged resources here.
// If disposing is false,
// only the following code is executed.
this.CleanUp();
// Note disposing has been done.
disposed = true;
}
}
#endregion
#endregion
#region Methods
#region Constructors
public MeshContainer()
{
this.Meshes = new List<BaseMesh>();
this.PositionList = new List<AGE_Vector3Df>();
this.NormalList = new List<AGE_Vector3Df>();
this.TextureList = new List<AGE_TextureCoordinate2f>();
this.Materials = new List<Material>();
}
#endregion
public void Initialize()
{
foreach (BaseMesh Mesh in this.Meshes)
{
Mesh.Generate_List_ID();
}
}
public void RenderOpenGL()
{
Gl.glEnable(Gl.GL_COLOR_MATERIAL);
Gl.glColorMaterial(Gl.GL_FRONT_AND_BACK, Gl.GL_AMBIENT_AND_DIFFUSE);
foreach (BaseMesh Mesh in Meshes)
{
foreach (string Name in Mesh.MaterialNames)
{
foreach (Material Mat in this.Materials)
{
if (Mat.Name == Name)
{
Mat.LoadMaterial();
Mesh.RenderOpenGL();
}
}
}
}
}
#endregion
#region StaticMethods
public static MeshContainer LoadObjFile(string FilePath)
{
MeshContainer result = null;
List<string> ObjFileCode = new List<string>();
#region Get the Obj File Data
try
{
using (StreamReader ObjFileStream = File.OpenText(FilePath))
{
#region ReadData
string LineInput = "";
while ((LineInput = ObjFileStream.ReadLine()) != null)
{
ObjFileCode.Add(LineInput);
}
#endregion
ObjFileStream.Close();
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
#endregion
#region Parse object File
try
{
if (ObjFileCode.Count > 0)
{
result = new MeshContainer();
result.Name = Path.GetFileNameWithoutExtension(FilePath);
BaseMesh CurrGroup = null;
char[] Deliminator = { ' ' };
foreach (string CurrLine in ObjFileCode)
{
//If the Line length is zero then skip it
if (CurrLine.Length != 0)
{
//If the String Starts with '#' then it is a Comment.
if (CurrLine[0] != '#')
{
string[] arg = CurrLine.Split(Deliminator, StringSplitOptions.RemoveEmptyEntries);
if (arg.Length > 0)
{
#region Parse each Line of the Obj File
switch (arg[0].ToUpper())
{
#region v Geometric vertices
case "V":
if (arg.Length < 4)
throw new FileLoadException();
float Vx = float.Parse(arg[1]);
float Vy = float.Parse(arg[2]);
float Vz = float.Parse(arg[3]);
result.PositionList.Add(new AGE_Vector3Df(Vx, Vy, Vz));
break;
#endregion
#region vt Texture vertices
case "VT":
if (arg.Length < 3)
throw new FileLoadException();
float Vu = float.Parse(arg[1]);
float Vv = float.Parse(arg[2]);
result.TextureList.Add(new AGE_TextureCoordinate2f(Vu, Vv));
break;
#endregion
#region vn Vertex normals
case "VN":
if (arg.Length < 4)
throw new FileLoadException();
float Nx = float.Parse(arg[1]);
float Ny = float.Parse(arg[2]);
float Nz = float.Parse(arg[3]);
AGE_Vector3Df Norm = new AGE_Vector3Df(Nx, Ny, Nz);
result.NormalList.Add(Norm.UnitVector());
break;
#endregion
#region Currently Unused
#region vp Parameter space vertices
case "VP":
break;
#endregion
case "DEG":
break;
case "BMAT":
break;
case "STEP":
break;
case "CSTYPE":
break;
#endregion
#region Group name
//case "G":
// if (CurrGroup != null)
// result.Meshes.Add(CurrGroup);
// CurrGroup = new BaseMesh(ref result.PositionList,
// ref result.NormalList,
// ref result.TextureList);
// CurrGroup.Name = arg[1];
// break;
#endregion
#region Object name
case "O":
if (CurrGroup != null)
result.Meshes.Add(CurrGroup);
CurrGroup = new BaseMesh(ref result.PositionList,
ref result.NormalList,
ref result.TextureList);
CurrGroup.Name = arg[1];
break;
#endregion
#region Smoothing Group
case "S":
//Ignore for now
break;
#endregion
#region Faces
case "F":
FaceIndices NewFace;
if (FaceIndices.ParseObjLine(CurrLine, out NewFace))
{
CurrGroup.Faces.Add(NewFace);
}
break;
#endregion
#region Assign Material Name
case "USEMTL":
if (CurrGroup != null)
CurrGroup.MaterialNames.Add(arg[1]);
break;
#endregion
#region Load Materials from a Material File
case "MTLLIB":
List<Material> TempMatList = ParseMaterialLibrary(arg[1], Path.GetDirectoryName(FilePath));
if (TempMatList != null)
{
if (TempMatList.Count > 0)
{
bool AddMaterial = false;
foreach (Material tmpMat in TempMatList)
{
AddMaterial = true;
for (int i = 0; i < result.Materials.Count; i++)
{
if (result.Materials[i].Name == tmpMat.Name)
{
AddMaterial = false;
break;
}
}
if (AddMaterial)
result.Materials.Add(tmpMat);
}
}
}
break;
#endregion
default:
break;
}
#endregion
}
}
}
}
if (CurrGroup != null)
result.Meshes.Add(CurrGroup);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
result = null;
}
#endregion
return result;
}
static List<Material> ParseMaterialLibrary(string FileName, string FilePath)
{
List<Material> result = null;
List<string> MaterialFileCode = new List<string>();
#region Get the Material File Data
try
{
using (StreamReader MaterialFileStream = File.OpenText(FilePath+"\\"+FileName))
{
#region ReadData
string LineInput = "";
while ((LineInput = MaterialFileStream.ReadLine()) != null)
{
MaterialFileCode.Add(LineInput);
}
#endregion
MaterialFileStream.Close();
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
#endregion
#region Parsing Material file
try
{
if (MaterialFileCode.Count > 0)
{
result = new List<Material>();
Material CurrentMat = null;
char[] Deliminator = { ' ' };
foreach (string CurrLine in MaterialFileCode)
{
//If the Line length is zero then skip it
if (CurrLine.Length != 0)
{
//If the String Starts with '#' then it is a Comment.
if (CurrLine[0] != '#')
{
string[] arg = CurrLine.Split(Deliminator, StringSplitOptions.RemoveEmptyEntries);
if (arg.Length > 0)
{
#region Parse each Line of the Material File
switch (arg[0].ToUpper())
{
#region New Materials
case "NEWMTL":
if (CurrentMat != null)
result.Add(CurrentMat);
CurrentMat = new Material();
CurrentMat.Name = arg[1];
break;
#endregion
#region Shininess
case "NS":
if (CurrentMat != null)
CurrentMat.Shininess = float.Parse(arg[1]);
break;
#endregion
#region Ambient color
case "KA":
if (CurrentMat != null)
{
CurrentMat.AmbientColor.Red = float.Parse(arg[1]);
CurrentMat.AmbientColor.Green = float.Parse(arg[2]);
CurrentMat.AmbientColor.Blue = float.Parse(arg[3]);
}
break;
#endregion
#region Diffuse color
case "KD":
if (CurrentMat != null)
{
CurrentMat.DiffuseColor.Red = float.Parse(arg[1]);
CurrentMat.DiffuseColor.Green = float.Parse(arg[2]);
CurrentMat.DiffuseColor.Blue = float.Parse(arg[3]);
}
break;
#endregion
#region Specular color
case "KS":
if (CurrentMat != null)
{
CurrentMat.SpecularColor.Red = float.Parse(arg[1]);
CurrentMat.SpecularColor.Green = float.Parse(arg[2]);
CurrentMat.SpecularColor.Blue = float.Parse(arg[3]);
}
break;
#endregion
#region Texture
case "MAP_KA":
if (CurrentMat != null)
{
CurrentMat.TextureName = arg[1];
}
break;
#endregion
default:
break;
}
#endregion
}
}
}
}
if (CurrentMat != null)
result.Add(CurrentMat);
}
}
catch (Exception e)
{
}
#endregion
return result;
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I am a licensed Electrical Engineer at Lea+Elliott, Inc. We specialize in the planning, procurement and implementation of transportation systems, with special emphasis on automated and emerging technologies.