游戏蛮牛学习群(纯技术交流,不闲聊):159852603
游戏蛮牛 手机端
开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:2354

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 731|回复: 39

[MemoryC] MemoryC杂记(三)【obj模型的加载和解析】

[复制链接]  [移动端链接]
排名
1460
昨日变化
6

27

主题

251

帖子

2534

积分

Rank: 9Rank: 9Rank: 9

UID
175038
好友
42
蛮牛币
2731
威望
0
注册时间
2016-10-12
在线时间
558 小时
最后登录
2018-11-20

专栏作家活力之星

发表于 2018-10-15 20:14:02 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
Unity动态加载和解析obj模型


最近在做的项目中有这个模块觉得可能大家有人需要,就分享出来。当然,你也可能找到其他人写的解析模块,我这篇文章虽有重复部分,但是也包含一些针对Unity平台的特殊处理。

1、Unity平台的Mesh一般都是三角网格,而实际上obj模型不仅可能是三角网格,还有可能是四边形网格。为了让obj解析之后更好地兼容Unity,这里对四边形网格进行了三角化操作;

2、在Unity中,Mesh.uv是一个Vector2类型数组,第i个元素表示第i个顶点对应的UV贴图的二维坐标。不同的是,Unity中Mesh.uv每个元素的顺序是与Mesh.vertices相对应的,而实际上obj 文件并没有这个约束。obj文件中v(顶点)的顺序和vt(UV坐标)的顺序不需要保持一致,甚至个数都可以不相同,只是在表示每个f时,标注每个顶点对应的vt的序号。本期MemoryC杂记中,我们将在解析obj中的uv的时候,将vt的数目和顺序按照Unity的规范来调整。

3、在Unity中,Mesh.normals(法线)也是与顶点顺序相对应的,类似的,我也做了相应的处理使之保持一致。

4、obj模型中表示面的行有以下几种方式 :[f va vb vc]、[f va/vta/vna vb/vtb/vnb vc/vtc/vnc]、[f va//vna vb//vnb vc//vnc]、[f va/vta vb/vtb vc/vtc]等。本文所给的方法均进行了适配。

5、返回Mesh前,重新计算了模型的切线和边界等信息。

6、出处http://www.manew.com/forum-47-453-1.html,如果转载请注 游戏蛮牛、MemoryC字样,否则皆为侵权行为。


【代码】

[C#] 纯文本查看 复制代码
using System.Collections;

using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// author:MemoryC
/// date:2018.09.16
/// description:ObjReader by MemoryC
/// support:load .obj file from external storage and convert it to mesh file with uvCoord and vertice normals
/// </summary>
public class ObjReader{
    /// <summary>
    /// 通过文件路径读取obj文件
    /// </summary>
    /// <param name="filename">最好用绝对路径</param>
    /// <param name="scale">比例,默认1</param>
    /// <a href="http://www.manew.com/forum-47-453-1.html"></a>
    /// <returns></returns>
    public static Mesh ReadMeshByObj(string filename,float scale=1f) {

        Mesh mesh = new Mesh();
        mesh.name = filename.Substring((int)Mathf.Max(filename.LastIndexOf("/"), filename.LastIndexOf("\\"))+1);

        List<Vector3> verticies = new List<Vector3>();
        List<Vector2> uvs = new List<Vector2>();
        List<Vector3> normals = new List<Vector3>();
        List<int> triangles = new List<int>();
        Vector2[] uUV=null;
        Vector3[] uNorm = null;

        System.IO.StreamReader sr = new System.IO.StreamReader(filename);
        string line;
        int lineNum = 0;
        while ((line = sr.ReadLine()) != null) {
            lineNum++;
            if (line.StartsWith("v ")) {//顶点
                line = line.Substring(2).Trim();
                string[] pos = line.Split(' ');
                if (pos.Length == 3) {
                    verticies.Add(new Vector3(float.Parse(pos[0]) / scale, float.Parse(pos[1]) / scale, float.Parse(pos[2]) / scale));
                } else {
                    Debug.Log("第" + lineNum + "行数据故障:" + line);
                }
            } else if (line.StartsWith("vt ")) {//纹理坐标
                line = line.Substring(3).Trim();
                string[] pos = line.Split(' '); 
                if (pos.Length == 2) {
                    uvs.Add(new Vector2(float.Parse(pos[0]), float.Parse(pos[1])));
                    
                } else {
                    Debug.Log("第" + lineNum + "行数据故障:" + line);
                }
            } else if(line .StartsWith("vn ")) {
                line = line.Substring(3).Trim();
                string[] pos = line.Split(' ');
                if (pos.Length == 3) {
                    normals.Add(new Vector3(float.Parse(pos[0]), float.Parse(pos[1]), float.Parse(pos[2])));
                } else {
                    Debug.Log("第" + lineNum + "行数据故障:" + line);
                }
            } else if (line.StartsWith("f ")){
                line = line.Substring(2).Trim();
                string[] pos = line.Split(' ');
                if (uUV == null) {
                    uUV = new Vector2[verticies.Count];
                }
                if (uNorm == null) {
                    uNorm = new Vector3[verticies.Count];
                }
                if (pos.Length == 3|| pos.Length == 4) {
                    if (pos[0].Contains("/")) {
                        //预处理
                        for (int i = 0; i < pos.Length; i++) {
                            pos.Replace("//", "/-/");
                            if (pos.EndsWith("/")) {
                                pos = pos + "-";
                            }
                        }
                        int[] vIndexes = new int[pos.Length];
                        
                        //解析
                        for (int i = 0; i < pos.Length; i++) {
                            string[] v_vt_vn = pos.Split('/');
                            int vIndex = int.Parse(v_vt_vn[0]);
                            if (!v_vt_vn[1].Equals("-")) {
                                int vtIndex = int.Parse(v_vt_vn[1]);
                                if(uUV[vIndex - 1].magnitude==0) {
                                    uUV[vIndex - 1] = uvs[vtIndex - 1];
                                }
                                
                            }
                            if (!v_vt_vn[2].Equals("-")) {
                                int vnIndex = int.Parse(v_vt_vn[2]);
                                if ( uNorm[vIndex - 1].magnitude == 0) {
                                    uNorm[vIndex - 1] = normals[vnIndex - 1];
                                }
                            }
                            vIndexes = vIndex;
                          
                        }
                        //加入三角形
                        for (int i = 0; i < 3; i++) {
                            triangles.Add(vIndexes - 1);
                        }
                        if (vIndexes.Length == 4) {
                            triangles.Add(vIndexes[0] - 1);
                            triangles.Add(vIndexes[2] - 1);
                            triangles.Add(vIndexes[3] - 1);
                        } 

                    } else {
                        triangles.Add(int.Parse(pos[0]) - 1);
                        triangles.Add(int.Parse(pos[1]) - 1);
                        triangles.Add(int.Parse(pos[2]) - 1);
                        if (pos.Length == 4) {
                            triangles.Add(int.Parse(pos[0]) - 1);
                            triangles.Add(int.Parse(pos[2]) - 1);
                            triangles.Add(int.Parse(pos[3]) - 1);
                        }
                    }
                } else {
                    Debug.Log("第" + lineNum + "行数据故障:" + line);
                }
            }
        }
        mesh.vertices = verticies.ToArray();
        mesh.normals = uNorm;
        mesh.triangles = triangles.ToArray();
        mesh.uv = uUV;//uvs.ToArray();
        mesh.RecalculateNormals();
        mesh.RecalculateTangents();
        mesh.RecalculateBounds();
        Debug.Log(string.Format("模型加载完成,面数:{0}点数:{1}",triangles.Count/3,verticies.Count))
        return mesh;
    }
}

展示效果

游客,如果您要查看本帖隐藏内容请回复


如果本文感动了您,别忘了点文章下方的"支持""评分"哦~

评分所用鲜花为系统赠送,不用就浪费了~

评分

参与人数 1鲜花 +2 收起 理由
2542397398 + 2 很给力!

查看全部评分


回复

使用道具 举报

排名
23378
昨日变化
9

0

主题

13

帖子

55

积分

Rank: 2Rank: 2

UID
224263
好友
0
蛮牛币
4
威望
0
注册时间
2017-5-30
在线时间
25 小时
最后登录
2018-11-19
发表于 2018-10-15 21:30:17 | 显示全部楼层

感谢分享

回复

使用道具 举报

3偶尔光临
228/300
排名
14249
昨日变化
9

9

主题

95

帖子

228

积分

Rank: 3Rank: 3Rank: 3

UID
288527
好友
0
蛮牛币
1377
威望
0
注册时间
2018-7-4
在线时间
58 小时
最后登录
2018-11-19
发表于 2018-10-15 21:45:37 | 显示全部楼层
66666666666666666666666666666

回复 支持 反对

使用道具 举报

排名
674
昨日变化

3

主题

440

帖子

2913

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
16063
好友
0
蛮牛币
1090
威望
0
注册时间
2014-3-1
在线时间
1200 小时
最后登录
2018-11-20
QQ
发表于 2018-10-15 23:08:31 | 显示全部楼层
感谢分享感谢分享感谢分享

回复 支持 反对

使用道具 举报

5熟悉之中
830/1000
排名
6057
昨日变化
38

29

主题

259

帖子

830

积分

Rank: 5Rank: 5

UID
254245
好友
3
蛮牛币
8902
威望
0
注册时间
2017-11-14
在线时间
350 小时
最后登录
2018-11-20
发表于 2018-10-16 09:07:08 | 显示全部楼层
感谢楼主分享

回复

使用道具 举报

7日久生情
1697/5000
排名
2362
昨日变化
14

12

主题

789

帖子

1697

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
218409
好友
3
蛮牛币
5204
威望
0
注册时间
2017-4-19
在线时间
332 小时
最后登录
2018-11-20
发表于 2018-10-16 09:11:54 | 显示全部楼层
6666666666666666

回复 支持 反对

使用道具 举报

7日久生情
1569/5000
排名
2489
昨日变化
2

12

主题

634

帖子

1569

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
214924
好友
3
蛮牛币
4066
威望
0
注册时间
2017-3-28
在线时间
367 小时
最后登录
2018-11-20
发表于 2018-10-16 09:20:56 | 显示全部楼层
大神就是大神

回复

使用道具 举报

4四处流浪
396/500
排名
7057
昨日变化
3

1

主题

46

帖子

396

积分

Rank: 4

UID
234627
好友
0
蛮牛币
494
威望
0
注册时间
2017-7-27
在线时间
171 小时
最后登录
2018-11-20
发表于 2018-10-16 09:25:28 | 显示全部楼层
谢谢分享。。。。。。。。。。。。。。。。

回复

使用道具 举报

6蛮牛粉丝
1256/1500
排名
1567
昨日变化
2

0

主题

171

帖子

1256

积分

Rank: 6Rank: 6Rank: 6

UID
137070
好友
0
蛮牛币
2472
威望
0
注册时间
2016-2-20
在线时间
305 小时
最后登录
2018-11-20
发表于 2018-10-16 09:50:44 | 显示全部楼层
感谢大佬百忙之中抽空进行的无私分享!
[发帖际遇]: kckbkckb2 被钱袋砸中进医院,看病花了 1 蛮牛币. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1256/1500
排名
1507
昨日变化
2

1

主题

224

帖子

1256

积分

Rank: 6Rank: 6Rank: 6

UID
2627
好友
0
蛮牛币
1161
威望
0
注册时间
2013-8-26
在线时间
221 小时
最后登录
2018-11-13

社区QQ达人

发表于 2018-10-16 09:53:23 | 显示全部楼层
感谢分享

回复

使用道具 举报

5熟悉之中
614/1000
排名
6057
昨日变化
38

3

主题

125

帖子

614

积分

Rank: 5Rank: 5

UID
168522
好友
0
蛮牛币
176
威望
0
注册时间
2016-9-14
在线时间
268 小时
最后登录
2018-11-20
发表于 2018-10-16 10:41:09 | 显示全部楼层
感谢分享感谢分享感谢分享666

回复 支持 反对

使用道具 举报

7日久生情
3183/5000
排名
206
昨日变化

0

主题

68

帖子

3183

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
3194
好友
0
蛮牛币
5173
威望
0
注册时间
2013-9-4
在线时间
1045 小时
最后登录
2018-11-20
发表于 2018-10-16 10:46:18 | 显示全部楼层
感谢分享感谢分享感谢分享感谢分享感谢分享
[发帖际遇]: saint0818 发帖时在路边捡到 2 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

7日久生情
1693/5000
排名
19290
昨日变化
8

12

主题

781

帖子

1693

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
158776
好友
2
蛮牛币
153
威望
0
注册时间
2016-7-26
在线时间
872 小时
最后登录
2018-11-13
发表于 2018-10-16 11:38:42 | 显示全部楼层
6666666666666666666666
[发帖际遇]: Hao521314 发帖时在路边捡到 1 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

3偶尔光临
272/300
排名
17679
昨日变化
5

1

主题

39

帖子

272

积分

Rank: 3Rank: 3Rank: 3

UID
180232
好友
0
蛮牛币
152
威望
0
注册时间
2016-11-2
在线时间
198 小时
最后登录
2018-11-16
发表于 2018-10-16 11:53:55 | 显示全部楼层
,,,,,,,,,,,,,,,,,,,,,,,

回复

使用道具 举报

4四处流浪
370/500
排名
11270
昨日变化
6

3

主题

84

帖子

370

积分

Rank: 4

UID
130020
好友
0
蛮牛币
114
威望
0
注册时间
2015-11-26
在线时间
201 小时
最后登录
2018-11-12
发表于 2018-10-16 12:30:14 | 显示全部楼层
展示效果

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

关闭

站长推荐 上一条 /1 下一条

快速回复 返回顶部 返回列表