[Unity]硬表面模型描边断裂问题解决过程记录( 二 )

< meshNormals.Length; i++){Vector3 tNormal;tNormal = Vector3.zero;tNormal.x = Vector3.Dot(((Vector3[])OtoTMatrixs[i])[0], meshNormals[i]);tNormal.y = Vector3.Dot(((Vector3[])OtoTMatrixs[i])[1], meshNormals[i]);tNormal.z = Vector3.Dot(((Vector3[])OtoTMatrixs[i])[2], meshNormals[i]);meshNormals[i] = tNormal;}//新建一个颜色数组把光滑处理后的法线值存入其中Color[] meshColors = new Color[mesh.colors.Length];for (int i = 0; i < meshColors.Length; i++){meshColors[i].r = meshNormals[i].x * 0.5f + 0.5f;meshColors[i].g = meshNormals[i].y * 0.5f + 0.5f;meshColors[i].b = meshNormals[i].z * 0.5f + 0.5f;meshColors[i].a = mesh.colors[i].a ;}//新建一个mesh , 将之前mesh的所有信息copy过去Mesh newMesh = new Mesh();newMesh.vertices = mesh.vertices;newMesh.triangles = mesh.triangles;newMesh.normals = mesh.normals;newMesh.tangents = mesh.tangents;newMesh.uv = mesh.uv;newMesh.uv2 = mesh.uv2;newMesh.uv3 = mesh.uv3;newMesh.uv4 = mesh.uv4;newMesh.uv5 = mesh.uv5;newMesh.uv6 = mesh.uv6;newMesh.uv7 = mesh.uv7;newMesh.uv8 = mesh.uv8;//将新模型的颜色赋值为计算好的颜色newMesh.colors = meshColors;newMesh.colors32 = mesh.colors32;newMesh.bounds = mesh.bounds;newMesh.indexFormat = mesh.indexFormat;newMesh.bindposes = mesh.bindposes;newMesh.boneWeights = mesh.boneWeights;//将新mesh保存为.asset文件 , 路径可以是"Assets/Character/Shader/VertexColorTest/TestMesh2.asset"AssetDatabase.CreateAsset( newMesh, NewMeshPath);AssetDatabase.SaveAssets();Debug.Log("Done");}}
然后将该脚本挂载到要处理的模型上面 , play一下就行了 , 新模型就会出现在设置好的路径下 。必须要说的是 , 需要处理的模型本身必须要有顶点色通道 , 也就是说在模型软件导出时必须要设置过顶点色 , 要不然导出的模型没有顶点色通道 , 当然即便没有顶点色通道在脚本中也可以处理 , 但是我懒得研究了ε=(′ο`*)))
方案二:由于在Unity中无法对fbx资源进行修改 , 这就使得整个资源导入的流程不够流畅 。于是我决定研究一下Fbx SDK , 用C++写个小程序直接对Fbx文件进行操作 , 操作的内容与方案一完全一样:计算法线→空间转换→写入顶点色→导出文件 。需要处理的模型本身必须要有顶点色通道 , 也就是说在模型软件导出时必须要设置过顶点色 , 否则导出的模型没有顶点色通道 , 当然即便没有顶点色通道在脚本中也可以处理 , 但是我懒得研究了ε=(′ο`*)))
按照Fbx sdk的文档所示 , 下载配置好sdk , 代码如下:
#include "pch.h"#include #include void StoreNormalsToVertColor(FbxNode* node) {if (node->GetChildCount()){for (int i = 0; i < node->GetChildCount(); i++){if (node->GetChild(i)->GetMesh()){//获取meshFbxMesh* mesh = node->GetChild(i)->GetMesh();//获取layer , 顶点色、法切线之类的顶点信息几乎存在layer中FbxLayer* layer0 = mesh->GetLayer(0);//依次获取layer中的顶点色层、法线层、切线层、副法线(或者叫副切线)层FbxLayerElementVertexColor* VertColor = layer0->GetVertexColors();FbxLayerElementNormal* VertNormal = layer0->GetNormals();FbxLayerElementTangent* VertTangent = layer0->GetTangents();FbxLayerElementBinormal* VertBinomral = layer0->GetBinormals();//逐顶点遍历操作for (int j = 0; j < mesh->GetPolygonVertexCount(); j++){//声明一个整型数组 , 用于存放与当前遍历顶点同属一个控制点的顶点序列//数组用的是FbxSdk内置的数组 , 是动态数组 , 比较好使FbxArray SameControlPointsIndex;for (int k = 0; k < mesh->GetPolygonVertexCount(); k++){if (mesh->GetPolygonVertices()[k] == mesh->GetPolygonVertices()[j]){SameControlPointsIndex.Add(k);}}//声明一个Vector4数组 , 获取并存放上面声明的顶点序列数组中所有不同方向的法线//需要注意的是 , 与Unity的顶点不同 , 这里的顶点中有很多法线的方向是重复的//如果将重复的法线也参与计算则算出来的值是错误的 , 轮廓线会扭曲 , 说出来都是泪//所以使用AddUnique保证去掉重复的法线方向FbxArray