This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
zhangyang-libzt/integrations/Unity3D/Assets/OBJ-IO/Plugins/Mesh/OBJ/OBJLoader.cs

219 lines
8.8 KiB
C#
Raw Normal View History


using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using UnityExtension;
/*
* Currently only supports Triangluar Meshes
*/
public class OBJLoader
{
//------------------------------------------------------------------------------------------------------------
private static OBJData m_OBJData = null;
//------------------------------------------------------------------------------------------------------------
private static OBJMaterial m_CurrentMaterial = null;
private static OBJGroup m_CurrentGroup = null;
#region PROCESSORS
//------------------------------------------------------------------------------------------------------------
private static readonly Dictionary<string, Action<string>> m_ParseOBJActionDictionary = new Dictionary<string, Action<string>>
{
{ "mtllib", (lEntry) => { /*Load MTL*/ } },
{ "usemtl", (lEntry) => { PushOBJGroupIfNeeded(); m_CurrentGroup.m_Material = m_OBJData.m_Materials.SingleOrDefault((lX) => { return lX.m_Name.EqualsInvariantCultureIgnoreCase(lEntry); }); } },
{ "v", (lEntry) => { m_OBJData.m_Vertices.Add(Utils.ParseVector3String(lEntry)); } },
{ "vn", (lEntry) => { m_OBJData.m_Normals.Add(Utils.ParseVector3String(lEntry)); } },
{ "vt", (lEntry) => { m_OBJData.m_UVs.Add(Utils.ParseVector2String(lEntry)); } },
{ "vt2", (lEntry) => { m_OBJData.m_UV2s.Add(Utils.ParseVector2String(lEntry)); } },
{ "vc", (lEntry) => { m_OBJData.m_Colors.Add(Utils.ParseVector4String(lEntry).ToColor()); } },
{ "f", PushOBJFace },
{ "g", PushOBJGroup },
};
//------------------------------------------------------------------------------------------------------------
private static readonly Dictionary<string, Action<string>> m_ParseMTLActionDictionary = new Dictionary<string, Action<string>>
{
{ "newmtl", PushOBJMaterial },
{ "Ka", (lEntry) => { m_CurrentMaterial.m_AmbientColor = Utils.ParseVector3String(lEntry).ToColor(); } },
{ "Kd", (lEntry) => { m_CurrentMaterial.m_DiffuseColor = Utils.ParseVector3String(lEntry).ToColor(); } },
{ "Ks", (lEntry) => { m_CurrentMaterial.m_SpecularColor = Utils.ParseVector3String(lEntry).ToColor(); } },
{ "Ns", (lEntry) => { m_CurrentMaterial.m_SpecularCoefficient = lEntry.ParseInvariantFloat(); } },
{ "d", (lEntry) => { m_CurrentMaterial.m_Transparency = lEntry.ParseInvariantFloat(); } },
{ "Tr", (lEntry) => { m_CurrentMaterial.m_Transparency = lEntry.ParseInvariantFloat(); } },
{ "illum", (lEntry) => { m_CurrentMaterial.m_IlluminationModel = lEntry.ParseInvariantInt(); } },
{ "map_Ka", (lEntry) => { m_CurrentMaterial.m_AmbientTextureMap = lEntry; } },
{ "map_Kd", (lEntry) => { m_CurrentMaterial.m_DiffuseTextureMap = lEntry; } },
{ "map_Ks", (lEntry) => { m_CurrentMaterial.m_SpecularTextureMap = lEntry; } },
{ "map_Ns", (lEntry) => { m_CurrentMaterial.m_SpecularHighlightTextureMap = lEntry; } },
{ "map_d", (lEntry) => { m_CurrentMaterial.m_AlphaTextureMap = lEntry; } },
{ "map_bump", (lEntry) => { m_CurrentMaterial.m_BumpMap = lEntry; } },
{ "bump", (lEntry) => { m_CurrentMaterial.m_BumpMap = lEntry; } },
{ "disp", (lEntry) => { m_CurrentMaterial.m_DisplacementMap = lEntry; } },
{ "decal",(lEntry) => { m_CurrentMaterial.m_StencilDecalMap = lEntry; } },
};
#endregion
#region PUBLIC_INTERFACE
//------------------------------------------------------------------------------------------------------------
public static OBJData LoadOBJ(Stream lStream)
{
m_OBJData = new OBJData();
m_CurrentMaterial = null;
m_CurrentGroup = null;
StreamReader lLineStreamReader = new StreamReader(lStream);
Action<string> lAction = null;
string lCurrentLine = null;
string[] lFields = null;
string lKeyword = null;
string lData = null;
while (!lLineStreamReader.EndOfStream)
{
lCurrentLine = lLineStreamReader.ReadLine();
if (StringExt.IsNullOrWhiteSpace(lCurrentLine)
|| lCurrentLine[0] == '#')
{
continue;
}
lFields = lCurrentLine.Trim().Split(null, 2);
if (lFields.Length < 2)
{
continue;
}
lKeyword = lFields[0].Trim();
lData = lFields[1].Trim();
lAction = null;
m_ParseOBJActionDictionary.TryGetValue(lKeyword.ToLowerInvariant(), out lAction);
if (lAction != null)
{
lAction(lData);
}
}
var lOBJData = m_OBJData;
m_OBJData = null;
return lOBJData;
}
//------------------------------------------------------------------------------------------------------------
public static void ExportOBJ(OBJData lData, Stream lStream)
{
StreamWriter lLineStreamWriter = new StreamWriter(lStream);
lLineStreamWriter.WriteLine(string.Format("# File exported by Unity3D version {0}", Application.unityVersion));
for (int lCount = 0; lCount < lData.m_Vertices.Count; ++lCount)
{
lLineStreamWriter.WriteLine(string.Format("v {0} {1} {2}",
lData.m_Vertices[lCount].x.ToString("n8"),
lData.m_Vertices[lCount].y.ToString("n8"),
lData.m_Vertices[lCount].z.ToString("n8")));
}
for (int lCount = 0; lCount < lData.m_UVs.Count; ++lCount)
{
lLineStreamWriter.WriteLine(string.Format("vt {0} {1}",
lData.m_UVs[lCount].x.ToString("n5"),
lData.m_UVs[lCount].y.ToString("n5")));
}
for (int lCount = 0; lCount < lData.m_UV2s.Count; ++lCount)
{
lLineStreamWriter.WriteLine(string.Format("vt2 {0} {1}",
lData.m_UVs[lCount].x.ToString("n5"),
lData.m_UVs[lCount].y.ToString("n5")));
}
for (int lCount = 0; lCount < lData.m_Normals.Count; ++lCount)
{
lLineStreamWriter.WriteLine(string.Format("vn {0} {1} {2}",
lData.m_Normals[lCount].x.ToString("n8"),
lData.m_Normals[lCount].y.ToString("n8"),
lData.m_Normals[lCount].z.ToString("n8")));
}
for (int lCount = 0; lCount < lData.m_Colors.Count; ++lCount)
{
lLineStreamWriter.WriteLine(string.Format("vc {0} {1} {2} {3}",
lData.m_Colors[lCount].r.ToString("n8"),
lData.m_Colors[lCount].g.ToString("n8"),
lData.m_Colors[lCount].b.ToString("n8"),
lData.m_Colors[lCount].a.ToString("n8")));
}
for (int lGroup = 0; lGroup < lData.m_Groups.Count; ++lGroup)
{
lLineStreamWriter.WriteLine(string.Format("g {0}", lData.m_Groups[lGroup].m_Name));
for (int lFace = 0; lFace < lData.m_Groups[lGroup].Faces.Count; ++lFace)
{
lLineStreamWriter.WriteLine(string.Format("f {0} {1} {2}",
lData.m_Groups[lGroup].Faces[lFace].ToString(0),
lData.m_Groups[lGroup].Faces[lFace].ToString(1),
lData.m_Groups[lGroup].Faces[lFace].ToString(2)));
}
}
lLineStreamWriter.Flush();
}
#endregion
//------------------------------------------------------------------------------------------------------------
private static void PushOBJMaterial(string lMaterialName)
{
m_CurrentMaterial = new OBJMaterial(lMaterialName);
m_OBJData.m_Materials.Add(m_CurrentMaterial);
}
//------------------------------------------------------------------------------------------------------------
private static void PushOBJGroup(string lGroupName)
{
m_CurrentGroup = new OBJGroup(lGroupName);
m_OBJData.m_Groups.Add(m_CurrentGroup);
}
//------------------------------------------------------------------------------------------------------------
private static void PushOBJGroupIfNeeded()
{
if (m_CurrentGroup == null)
{
PushOBJGroup("default");
}
}
//------------------------------------------------------------------------------------------------------------
private static void PushOBJFace(string lFaceLine)
{
PushOBJGroupIfNeeded();
var vertices = lFaceLine.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
var face = new OBJFace();
foreach (var vertexString in vertices)
{
face.ParseVertex(vertexString);
}
m_CurrentGroup.AddFace(face);
}
}