unity2018.4.2f1
vs2017
最近项目需求,需要实现动态读物外部obj模型,并加载到场景中,研究了好几天,终于实现了,在此做个记录。
1、首先随便找个.obj模型,带贴图,我的资源截图如下:
.mtl文件是负责记录模型与贴图的对应关系
obj问价与mtl文件均可以用记事本打开,查看内部数据
obj文件截图:
mtllib Tifa.mtl 记录当前obj文件对应的mtl文件的名称(一个mtl文件可以包含多个材质)
v:模型顶点数据
vt:模型顶点纹理坐标数据
vn:模型顶点法线数据
usemtl diss_00.png 表示当前模型分组使用的材质,每一个模型分组以usemtl 开始(一个模型存在有多个子物体的情况)
比如我这个:
mtl文件截图:
newmtl diss_00.png:表示当前的材质名称
illum:照明度(0-10)
kd:当前材质的散射光
ka:当前材质的环境光
ks:当前材质的镜面光
ke:当前材质的散射光
Ns:材质的光亮度
map_Kd:当前材质对应的贴图名称
2、根据模型文本文件分析,编写模型数据结构,直接上代码
ObjPart:obj文件数据结构
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjPart
{
/// <summary>
/// 材质名称
/// </summary>
public string strMatName;
/// <summary>
/// UV坐标数组
/// </summary>
public List<Vector2> listUV; //vt
/// <summary>
/// 法线数组
/// </summary>
public List<Vector3> listNormal;//vn
/// <summary>
/// 切线数组
/// </summary>
public List<Vector4> listTangent;
/// <summary>
/// 顶点数组
/// </summary>
public List<Vector3> listVertex; //v
/// <summary>
/// 面数组 面索引
/// </summary>
public List<int> listTriangle;
public ObjPart()
{
strMatName = "";
listUV = new List<Vector2>();
listNormal = new List<Vector3>();
listVertex = new List<Vector3>();
listTriangle = new List<int>();
listTangent = new List<Vector4>();
}
}
ObjMatItem:mtl文件数据结构
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//mtl数据结构(记录的是材质对应的贴图)
public class ObjMatItem
{
/// <summary>
/// 材质名称
/// </summary>
public string strMatName;
public int illum;
public Vector3 Kd;
public Vector3 Ka;
public Vector3 Tf;
public Vector2 widthHeight;
public string map_Kd;
public float Ni;
public ObjMatItem()
{
strMatName = "";
illum = -1;
Kd = new Vector3(0.0f, 0.0f, 0.0f);
Ka = new Vector3(0.0f, 0.0f, 0.0f);
Tf = new Vector3(0.0f, 0.0f, 0.0f);
map_Kd = "";
Ni = 1.0f;
widthHeight.x = 0.0f;
widthHeight.y = 0.0f;
}
}
ObjModel:模型数据结构
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 完整模型=网格+材质
/// </summary>
public class ObjModel
{
public List<ObjPart> objParts; //网格
public List<ObjMatItem> ObjMats; //材质
}
3、从文本文件中加载obj数据以及mtl数据
ObjMesh:负责从.obj文件中加载数据
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
/// <summary>
/// 负责从.obj文件中加载数据
/// </summary>
public class ObjMesh
{
/// <summary>
/// UV坐标列表
/// </summary>
private List<Vector3> uvArrayList;
/// <summary>
/// 法线列表
/// </summary>
private List<Vector3> normalArr