目前基本实现了导入,注意只能打开含有单个模型的obj文件

四边面模型:

全三角面模型(测试单一材质,自动分了下UV):

这里介绍下obj格式:

obj格式是waveFront推出的一种3D模型格式,可以存放静态模型以及一些诸如曲线的附加信息。

其格式以文本形式存放,所以解析起来比较方便,它的大体格式如下:

# WaveFront *.obj file (generated by CINEMA 4D)

mtllib ./test.mtl

v -100.00000000000000 -100.00000000000000 -100.00000000000000
v -100.00000000000000 100.00000000000000 -100.00000000000000
v 100.00000000000000 -100.00000000000000 -100.00000000000000
v 100.00000000000000 100.00000000000000 -100.00000000000000
v 100.00000000000000 -100.00000000000000 100.00000000000000
v 100.00000000000000 100.00000000000000 100.00000000000000
v -100.00000000000000 -100.00000000000000 100.00000000000000
v -100.00000000000000 100.00000000000000 100.00000000000000
# vertices vn 0.00000000000000 0.00000000000000 -1.00000000000000
vn 1.00000000000000 0.00000000000000 0.00000000000000
vn 0.00000000000000 0.00000000000000 1.00000000000000
vn -1.00000000000000 0.00000000000000 0.00000000000000
vn 0.00000000000000 1.00000000000000 0.00000000000000
vn 0.00000000000000 -1.00000000000000 0.00000000000000
# normals vt 0.00000000000000 -1.00000000000000 0.00000000000000
vt 0.00000000000000 -0.00000000000000 0.00000000000000
vt 1.00000000000000 -0.00000000000000 0.00000000000000
vt 1.00000000000000 -1.00000000000000 0.00000000000000
# texture coordinates o Cube
usemtl default
f // // // //
f // // // //
f // // // //
f // // // //
f // // // //
f // // // //

Cube(Obj)

常用类型:

#开头表示注释

v表示顶点

vn表示法线,可以共用法线

vt表示uv坐标

f表示一个面,比如参数1/4/1,表示顶点索引/UV索引/法线索引

下面贴一下工具类的代码:

using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic; namespace Hont
{
public class ObjFormatAnalyzer
{
public struct Vector
{
public float X;
public float Y;
public float Z;
} public struct FacePoint
{
public int VertexIndex;
public int TextureIndex;
public int NormalIndex;
} public struct Face
{
public FacePoint[] Points;
public bool IsQuad;
} public Vector[] VertexArr;
public Vector[] VertexNormalArr;
public Vector[] VertexTextureArr;
public Face[] FaceArr; public void Analyze(string content)
{
content = content.Replace('\r', ' ').Replace('\t', ' '); var lines = content.Split('\n');
var vertexList = new List<Vector>();
var vertexNormalList = new List<Vector>();
var vertexTextureList = new List<Vector>();
var faceList = new List<Face>(); for (int i = ; i < lines.Length; i++)
{
var currentLine = lines[i]; if (currentLine.Contains("#") || currentLine.Length == )
{
continue;
} if (currentLine.Contains("v "))
{
var splitInfo = currentLine.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
vertexList.Add(new Vector() { X = float.Parse(splitInfo[]), Y = float.Parse(splitInfo[]), Z = float.Parse(splitInfo[]) });
}
else if (currentLine.Contains("vt "))
{
var splitInfo = currentLine.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
vertexTextureList.Add(new Vector() { X = splitInfo.Length > ? float.Parse(splitInfo[]) : , Y = splitInfo.Length > ? float.Parse(splitInfo[]) : , Z = splitInfo.Length > ? float.Parse(splitInfo[]) : });
}
else if (currentLine.Contains("vn "))
{
var splitInfo = currentLine.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
vertexNormalList.Add(new Vector() { X = float.Parse(splitInfo[]), Y = float.Parse(splitInfo[]), Z = float.Parse(splitInfo[]) });
}
else if (currentLine.Contains("f "))
{
Func<string, int> tryParse = (inArg) =>
{
var outValue = -;
return int.TryParse(inArg, out outValue) ? outValue : ;
}; var splitInfo = currentLine.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
var isQuad = splitInfo.Length > ;
var face1 = splitInfo[].Split('/');
var face2 = splitInfo[].Split('/');
var face3 = splitInfo[].Split('/');
var face4 = isQuad ? splitInfo[].Split('/') : null;
var face = new Face();
face.Points = new FacePoint[];
face.Points[] = new FacePoint() { VertexIndex = tryParse(face1[]), TextureIndex = tryParse(face1[]), NormalIndex = tryParse(face1[]) };
face.Points[] = new FacePoint() { VertexIndex = tryParse(face2[]), TextureIndex = tryParse(face2[]), NormalIndex = tryParse(face2[]) };
face.Points[] = new FacePoint() { VertexIndex = tryParse(face3[]), TextureIndex = tryParse(face3[]), NormalIndex = tryParse(face3[]) };
face.Points[] = isQuad ? new FacePoint() { VertexIndex = tryParse(face4[]), TextureIndex = tryParse(face4[]), NormalIndex = tryParse(face4[]) } : default(FacePoint);
face.IsQuad = isQuad; faceList.Add(face);
}
} VertexArr = vertexList.ToArray();
VertexNormalArr = vertexNormalList.ToArray();
VertexTextureArr = vertexTextureList.ToArray();
FaceArr = faceList.ToArray();
}
}
}

ObjFormatAnalyzer

工厂类,目前只有输出GameObject:

using UnityEngine;
using System.IO;
using System.Linq;
using System.Collections;
using System.Collections.Generic; namespace Hont
{
public static class ObjFormatAnalyzerFactory
{
public static GameObject AnalyzeToGameObject(string objFilePath)
{
if (!File.Exists(objFilePath)) return null; var objFormatAnalyzer = new ObjFormatAnalyzer(); objFormatAnalyzer.Analyze(File.ReadAllText(objFilePath)); var go = new GameObject();
var meshRenderer = go.AddComponent<MeshRenderer>();
var meshFilter = go.AddComponent<MeshFilter>(); var mesh = new Mesh(); var sourceVertexArr = objFormatAnalyzer.VertexArr;
var sourceUVArr = objFormatAnalyzer.VertexTextureArr;
var faceArr = objFormatAnalyzer.FaceArr;
var notQuadFaceArr = objFormatAnalyzer.FaceArr.Where(m => !m.IsQuad).ToArray();
var quadFaceArr = objFormatAnalyzer.FaceArr.Where(m => m.IsQuad).ToArray();
var vertexList = new List<Vector3>();
var uvList = new List<Vector2>(); var triangles = new int[notQuadFaceArr.Length * + quadFaceArr.Length * ];
for (int i = , j = ; i < faceArr.Length; i++)
{
var currentFace = faceArr[i]; triangles[j] = j;
triangles[j + ] = j + ;
triangles[j + ] = j + ; var vec = sourceVertexArr[currentFace.Points[].VertexIndex - ];
vertexList.Add(new Vector3(vec.X, vec.Y, vec.Z)); var uv = sourceUVArr[currentFace.Points[].TextureIndex - ];
uvList.Add(new Vector2(uv.X, uv.Y)); vec = sourceVertexArr[currentFace.Points[].VertexIndex - ];
vertexList.Add(new Vector3(vec.X, vec.Y, vec.Z)); uv = sourceUVArr[currentFace.Points[].TextureIndex - ];
uvList.Add(new Vector2(uv.X, uv.Y)); vec = sourceVertexArr[currentFace.Points[].VertexIndex - ];
vertexList.Add(new Vector3(vec.X, vec.Y, vec.Z)); uv = sourceUVArr[currentFace.Points[].TextureIndex - ];
uvList.Add(new Vector2(uv.X, uv.Y)); if (currentFace.IsQuad)
{
triangles[j + ] = j + ;
triangles[j + ] = j + ;
triangles[j + ] = j + ;
j += ; vec = sourceVertexArr[currentFace.Points[].VertexIndex - ];
vertexList.Add(new Vector3(vec.X, vec.Y, vec.Z)); uv = sourceUVArr[currentFace.Points[].TextureIndex - ];
uvList.Add(new Vector2(uv.X, uv.Y)); vec = sourceVertexArr[currentFace.Points[].VertexIndex - ];
vertexList.Add(new Vector3(vec.X, vec.Y, vec.Z)); uv = sourceUVArr[currentFace.Points[].TextureIndex - ];
uvList.Add(new Vector2(uv.X, uv.Y)); vec = sourceVertexArr[currentFace.Points[].VertexIndex - ];
vertexList.Add(new Vector3(vec.X, vec.Y, vec.Z)); uv = sourceUVArr[currentFace.Points[].TextureIndex - ];
uvList.Add(new Vector2(uv.X, uv.Y));
} j += ;
} mesh.vertices = vertexList.ToArray();
mesh.uv = uvList.ToArray();
mesh.triangles = triangles; meshFilter.mesh = mesh;
meshRenderer.material = new Material(Shader.Find("Standard")); return go;
}
}
}

ObjFormatAnalyzerFactory

测试使用脚本:

public class ObjFormatAnalyzerTest : MonoBehaviour
{
void Start()
{
var go = ObjFormatAnalyzerFactory.AnalyzeToGameObject(@"D:\TestObj\centaur.obj"); WWW www = new WWW("file:/D:/TestObj/texture.jpg"); while (!www.isDone) { } go.GetComponent<MeshRenderer>().material.mainTexture = www.texture;
}
}

然后挂载运行即可。

目前可能还有点小问题,因为没有实现材质的绑定,所以只能支持单一材质。

Obj格式解析以及在Unity3D下导入测试的更多相关文章

  1. flash画图API:解析obj格式

    又到了周末的时间,依旧的例牌菜.只是近期在和一些同事交流下,学习了一些新的知识.过去一直没有明确的问题,如今总算有点感觉了. 平时编程偶然会用到数学,特别是在做3d的时候.相信看过rokix的3d,那 ...

  2. DirectX11 With Windows SDK--19 模型加载:obj格式的读取及使用二进制文件提升读取效率

    前言 一个模型通常是由三个部分组成:网格.纹理.材质.在一开始的时候,我们是通过Geometry类来生成简单几何体的网格.但现在我们需要寻找合适的方式去表述一个复杂的网格,而且包含网格的文件类型多种多 ...

  3. Unity NavMesh 格式 解析 分析 对比 Recast Navigation

    工具软件 Excel Nodepad++ Sublime Unity 5.4 / 5.6 VS RecastDemo CodeBlocks 分析过程以Unity项目-Demo13为例 一. 创建测试模 ...

  4. 【腾讯Bugly干货分享】手游热更新方案xLua开源:Unity3D下Lua编程解决方案

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:http://mp.weixin.qq.com/s/2bY7A6ihK9IMcA0bOFyB-Q 导语 xL ...

  5. Unity3d 下websocket的使用

    今天介绍一下如何在Unity3D下使用WebSocket. 首先介绍一下什么是websocket,以及与socket,和http的区别与联系,然后介绍一下websocket的一些开源的项目. WebS ...

  6. 腾讯开源手游热更新方案,Unity3D下的Lua编程

    原文:http://www.sohu.com/a/123334175_355140 作者|车雄生 编辑|木环 腾讯最近在开源方面的动作不断:先是微信跨平台基础组件Mars宣布开源,腾讯手游又于近期开源 ...

  7. [iTyran原创]iPhone中OpenGL ES显示3DS MAX模型之一:OBJ格式分析

    [iTyran原创]iPhone中OpenGL ES显示3DS MAX模型之一:OBJ文件格式分析作者:yuezang - iTyran     在iOS的3D开发中常常需要导入通过3DS MAX之类 ...

  8. plist文件、NSUserDefault 对文件进行存储的类、json格式解析

    ========================== 文件操作 ========================== Δ一 .plist文件 .plist文件是一个属性字典数组的一个文件: .plis ...

  9. IE8下导入EXCEL数据传到客户端以附件下载

    IE8下导入EXCEL数据传到客户端以附件下载方式出现,而不显示数据,解决方法:以text/html格式返回. HttpResponseMessage message = new HttpRespon ...

随机推荐

  1. Leetcode: Palindrome Pairs

    Given a list of unique words, find all pairs of distinct indices (i, j) in the given list, so that t ...

  2. Lintcode: Interval Minimum Number

    Given an integer array (index from 0 to n-1, where n is the size of this array), and an query list. ...

  3. Java日志管理方法(转载)

    原文地址:http://www.cnblogs.com/leocook/p/log_java.html java开发中常见的几种日志管理方案有以下4种: 1. Commons-logging + lo ...

  4. js eventhandler

    1.获取所有eventhandler 使用 getEventHandler(target) 2.target.addEventHandler(type,handler,userCapture?) 3. ...

  5. android 修改系统的dialog样式

    android 修改系统的dialog样式 一.觉得自定义配置文件麻烦?那就来修改系统自定义XML文件来实现修改系统dialog的样式吧. 如果是在XML中样式:首先来说下样式.  在 Style.x ...

  6. paper 82:边缘检测的各种微分算子比较(Sobel,Robert,Prewitt,Laplacian,Canny)

    不同图像灰度不同,边界处一般会有明显的边缘,利用此特征可以分割图像.需要说明的是:边缘和物体间的边界并不等同,边缘指的是图像中像素的值有突变的地方,而物体间的边界指的是现实场景中的存在于物体之间的边界 ...

  7. app_field.clear_dependent_fields

    可以调用APP_FIELD.clear_dependent_fields和APP_FIELD.set_dependent_field来将两个(或多个)Item建立关联,当一个为空时,另一个不可录入,反 ...

  8. 夺命雷公狗---node.js---2node.js中的npm的常用命令

    npm install <name> 安装nodejs的依赖包 例如npm install express 就会默认安装express的最新版本,也可以通过在后面加版本号的方式安装指定版本 ...

  9. 0-9、a-z、A-Z 随机数

    MXS&Vincene  ─╄OvЁ  &0000006 ─╄OvЁ  MXS&Vincene MXS&Vincene  ─╄OvЁ:今天很残酷,明天更残酷,后天很美好 ...

  10. Ul li 竖排 菜单

    Ul li 竖排 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://ww ...