Obj格式解析以及在Unity3D下导入测试
目前基本实现了导入,注意只能打开含有单个模型的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下导入测试的更多相关文章
- flash画图API:解析obj格式
又到了周末的时间,依旧的例牌菜.只是近期在和一些同事交流下,学习了一些新的知识.过去一直没有明确的问题,如今总算有点感觉了. 平时编程偶然会用到数学,特别是在做3d的时候.相信看过rokix的3d,那 ...
- DirectX11 With Windows SDK--19 模型加载:obj格式的读取及使用二进制文件提升读取效率
前言 一个模型通常是由三个部分组成:网格.纹理.材质.在一开始的时候,我们是通过Geometry类来生成简单几何体的网格.但现在我们需要寻找合适的方式去表述一个复杂的网格,而且包含网格的文件类型多种多 ...
- Unity NavMesh 格式 解析 分析 对比 Recast Navigation
工具软件 Excel Nodepad++ Sublime Unity 5.4 / 5.6 VS RecastDemo CodeBlocks 分析过程以Unity项目-Demo13为例 一. 创建测试模 ...
- 【腾讯Bugly干货分享】手游热更新方案xLua开源:Unity3D下Lua编程解决方案
本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:http://mp.weixin.qq.com/s/2bY7A6ihK9IMcA0bOFyB-Q 导语 xL ...
- Unity3d 下websocket的使用
今天介绍一下如何在Unity3D下使用WebSocket. 首先介绍一下什么是websocket,以及与socket,和http的区别与联系,然后介绍一下websocket的一些开源的项目. WebS ...
- 腾讯开源手游热更新方案,Unity3D下的Lua编程
原文:http://www.sohu.com/a/123334175_355140 作者|车雄生 编辑|木环 腾讯最近在开源方面的动作不断:先是微信跨平台基础组件Mars宣布开源,腾讯手游又于近期开源 ...
- [iTyran原创]iPhone中OpenGL ES显示3DS MAX模型之一:OBJ格式分析
[iTyran原创]iPhone中OpenGL ES显示3DS MAX模型之一:OBJ文件格式分析作者:yuezang - iTyran 在iOS的3D开发中常常需要导入通过3DS MAX之类 ...
- plist文件、NSUserDefault 对文件进行存储的类、json格式解析
========================== 文件操作 ========================== Δ一 .plist文件 .plist文件是一个属性字典数组的一个文件: .plis ...
- IE8下导入EXCEL数据传到客户端以附件下载
IE8下导入EXCEL数据传到客户端以附件下载方式出现,而不显示数据,解决方法:以text/html格式返回. HttpResponseMessage message = new HttpRespon ...
随机推荐
- Leetcode: Palindrome Pairs
Given a list of unique words, find all pairs of distinct indices (i, j) in the given list, so that t ...
- 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. ...
- Java日志管理方法(转载)
原文地址:http://www.cnblogs.com/leocook/p/log_java.html java开发中常见的几种日志管理方案有以下4种: 1. Commons-logging + lo ...
- js eventhandler
1.获取所有eventhandler 使用 getEventHandler(target) 2.target.addEventHandler(type,handler,userCapture?) 3. ...
- android 修改系统的dialog样式
android 修改系统的dialog样式 一.觉得自定义配置文件麻烦?那就来修改系统自定义XML文件来实现修改系统dialog的样式吧. 如果是在XML中样式:首先来说下样式. 在 Style.x ...
- paper 82:边缘检测的各种微分算子比较(Sobel,Robert,Prewitt,Laplacian,Canny)
不同图像灰度不同,边界处一般会有明显的边缘,利用此特征可以分割图像.需要说明的是:边缘和物体间的边界并不等同,边缘指的是图像中像素的值有突变的地方,而物体间的边界指的是现实场景中的存在于物体之间的边界 ...
- app_field.clear_dependent_fields
可以调用APP_FIELD.clear_dependent_fields和APP_FIELD.set_dependent_field来将两个(或多个)Item建立关联,当一个为空时,另一个不可录入,反 ...
- 夺命雷公狗---node.js---2node.js中的npm的常用命令
npm install <name> 安装nodejs的依赖包 例如npm install express 就会默认安装express的最新版本,也可以通过在后面加版本号的方式安装指定版本 ...
- 0-9、a-z、A-Z 随机数
MXS&Vincene ─╄OvЁ &0000006 ─╄OvЁ MXS&Vincene MXS&Vincene ─╄OvЁ:今天很残酷,明天更残酷,后天很美好 ...
- Ul li 竖排 菜单
Ul li 竖排 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://ww ...