当前位置: 首页 > wzjs >正文

网站建设与管理中专专业青岛网站制作

网站建设与管理中专专业,青岛网站制作,宝安网站设计项目,top域名注册结果 能用,不是很理想,从左到右,分别是body,眼睛,演睫毛,手指套(如果你知道这是什么)结果不是很理想 (下面代码已包含,修复的切线只能传Vector3参数,Unity2022测试) 你们帮我看看…

结果

能用,不是很理想,从左到右,分别是body,眼睛,演睫毛,手指套(如果你知道这是什么)结果不是很理想 

(下面代码已包含,修复的切线只能传Vector3参数,Unity2022测试)

你们帮我看看,到底这个代码的质量如何,是否能用

明显它是知道的

using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using UnityEngine.UIElements;public class SkinnedMeshSplitterWindow : EditorWindow
{private GameObject targetObject;private Vector2 scrollPos;[MenuItem("Tools/Skinned--Mesh Splitter")]public static void ShowWindow(){GetWindow<SkinnedMeshSplitterWindow>("Mesh Splitter");}void OnGUI(){scrollPos = EditorGUILayout.BeginScrollView(scrollPos);// 目标对象选择targetObject = (GameObject)EditorGUILayout.ObjectField("Target Object", targetObject, typeof(GameObject), true);EditorGUILayout.Space(10);if (targetObject != null){DrawMeshInfo();EditorGUILayout.Space(10);if (GUILayout.Button("Split SubMeshes", GUILayout.Height(30))){SplitMeshes(targetObject);}}else{EditorGUILayout.HelpBox("Select a GameObject with MeshFilter or SkinnedMeshRenderer", MessageType.Info);}EditorGUILayout.EndScrollView();}void DrawMeshInfo(){var smr = targetObject.GetComponent<SkinnedMeshRenderer>();var mf = targetObject.GetComponent<MeshFilter>();if (smr != null && smr.sharedMesh != null){EditorGUILayout.LabelField("Skinned Mesh Info:", EditorStyles.boldLabel);EditorGUILayout.LabelField($"SubMeshes: {smr.sharedMesh.subMeshCount}");EditorGUILayout.LabelField($"Materials: {smr.sharedMaterials.Length}");}else if (mf != null && mf.sharedMesh != null){EditorGUILayout.LabelField("Static Mesh Info:", EditorStyles.boldLabel);EditorGUILayout.LabelField($"SubMeshes: {mf.sharedMesh.subMeshCount}");EditorGUILayout.LabelField($"Materials: {targetObject.GetComponent<MeshRenderer>()?.sharedMaterials.Length ?? 0}");}else{EditorGUILayout.HelpBox("No valid mesh component found", MessageType.Warning);}}void SplitMeshes(GameObject originalObject){// 处理SkinnedMeshRenderervar skinnedRenderer = originalObject.GetComponent<SkinnedMeshRenderer>();if (skinnedRenderer != null){SplitSkinnedMesh(skinnedRenderer);}// 处理MeshFiltervar meshFilter = originalObject.GetComponent<MeshFilter>();if (meshFilter != null){SplitStaticMesh(meshFilter);}}void SplitSkinnedMesh(SkinnedMeshRenderer originalRenderer){Mesh originalMesh = originalRenderer.sharedMesh;Transform rootBone = originalRenderer.rootBone;Transform[] bones = originalRenderer.bones;Material[] materials = originalRenderer.sharedMaterials;for (int subMeshIndex = 0; subMeshIndex < originalMesh.subMeshCount; subMeshIndex++){GameObject newGo = CreateNewObject(originalRenderer.gameObject, subMeshIndex, "Skinned");SkinnedMeshRenderer newRenderer = newGo.AddComponent<SkinnedMeshRenderer>();newRenderer.sharedMesh = ProcessSubMesh(originalMesh, subMeshIndex);newRenderer.bones = bones;newRenderer.rootBone = rootBone;newRenderer.sharedMaterials = GetSubMaterials(materials, subMeshIndex);}}void SplitStaticMesh(MeshFilter originalFilter){Mesh originalMesh = originalFilter.sharedMesh;MeshRenderer originalRenderer = originalFilter.GetComponent<MeshRenderer>();Material[] materials = originalRenderer?.sharedMaterials;for (int subMeshIndex = 0; subMeshIndex < originalMesh.subMeshCount; subMeshIndex++){GameObject newGo = CreateNewObject(originalFilter.gameObject, subMeshIndex, "Static");MeshFilter newFilter = newGo.AddComponent<MeshFilter>();newFilter.sharedMesh = ProcessSubMesh(originalMesh, subMeshIndex);MeshRenderer newRenderer = newGo.AddComponent<MeshRenderer>();newRenderer.sharedMaterials = GetSubMaterials(materials, subMeshIndex);}}GameObject CreateNewObject(GameObject original, int index, string typePrefix){GameObject newGo = new GameObject($"{original.name}_{typePrefix}_submesh_{index}");newGo.transform.SetParent(original.transform.parent);newGo.transform.localPosition = original.transform.localPosition;newGo.transform.localRotation = original.transform.localRotation;newGo.transform.localScale = original.transform.localScale;return newGo;}Mesh ProcessSubMesh(Mesh originalMesh, int subMeshIndex){Mesh newMesh = new Mesh();// 获取三角形数据int[] triangles = originalMesh.GetTriangles(subMeshIndex);HashSet<int> vertexSet = new HashSet<int>(triangles);// 创建顶点映射表Dictionary<int, int> vertexMap = new Dictionary<int, int>();List<Vector3> newVertices = new List<Vector3>();// 收集所有顶点属性List<Vector3> newNormals = new List<Vector3>();List<Vector4> newTangents = new List<Vector4>();List<Vector2> newUV = new List<Vector2>();List<BoneWeight> newBoneWeights = new List<BoneWeight>();foreach (int index in vertexSet){vertexMap[index] = newVertices.Count;newVertices.Add(originalMesh.vertices[index]);if (originalMesh.normals.Length > index)newNormals.Add(originalMesh.normals[index]);if (originalMesh.tangents.Length > index)newTangents.Add(originalMesh.tangents[index]);if (originalMesh.uv.Length > index)newUV.Add(originalMesh.uv[index]);if (originalMesh.boneWeights.Length > index)newBoneWeights.Add(originalMesh.boneWeights[index]);}// 重新映射三角形int[] newTriangles = new int[triangles.Length];for (int i = 0; i < triangles.Length; i++){newTriangles[i] = vertexMap[triangles[i]];}// 设置网格数据newMesh.SetVertices(newVertices);if (newNormals.Count > 0) newMesh.SetNormals(newNormals);if (newTangents.Count > 0) newMesh.SetTangents(newTangents);if (newUV.Count > 0) newMesh.SetUVs(0, newUV);if (newBoneWeights.Count > 0) newMesh.boneWeights = newBoneWeights.ToArray();newMesh.triangles = newTriangles;newMesh.RecalculateBounds();// 复制混合形状(如果需要)if (originalMesh.blendShapeCount > 0){for (int i = 0; i < originalMesh.blendShapeCount; i++){Vector3[] deltaVertices = new Vector3[originalMesh.vertexCount];Vector3[] deltaNormals = new Vector3[originalMesh.vertexCount];Vector3[] deltaTangents = new Vector3[originalMesh.vertexCount];originalMesh.GetBlendShapeFrameVertices(i, 0, deltaVertices, deltaNormals, deltaTangents);List<Vector3> newDeltaVerts = new List<Vector3>();foreach (int index in vertexSet){newDeltaVerts.Add(deltaVertices[index]);}//做一个转换,不要最后切线的 w;第四个分量(w)是一个符号值(通常为1或-1),用于确定副切线(Bitangent)的方向。List<Vector3> temps = new List<Vector3>();for (int j =0; j< newTangents.Count; j++) {Vector3 t = newTangents[i];temps.Add(t);}newMesh.AddBlendShapeFrame(originalMesh.GetBlendShapeName(i),originalMesh.GetBlendShapeFrameWeight(i, 0),newDeltaVerts.ToArray(),deltaNormals.Length > 0 ? newNormals.ToArray() : null,deltaTangents.Length > 0 ? temps.ToArray() : null);}}return newMesh;}Material[] GetSubMaterials(Material[] originalMaterials, int subMeshIndex){if (originalMaterials == null || originalMaterials.Length == 0)return new Material[0];int materialIndex = Mathf.Clamp(subMeshIndex, 0, originalMaterials.Length - 1);return new Material[] { originalMaterials[materialIndex] };}
}

结果,我之后再截图吧

<最终生成结果在倒装,放文章最上面了。。。>

修复切线,切线对不上的。。。

指的是mesh 读取的是 tangents:Vector4,但是add mesh 只能 tangetns:Vector3// unity 的skinnedmesh 万年没有更新,想要对上,全靠“蒙”

1. 为什么有时是Vector3,有时是Vector4

  • Vector4的普遍性
    在Unity的网格数据(Mesh.tangents)中,切线默认存储为Vector4数组。这是因为法线贴图(Normal Mapping)需要完整的切线空间信息,而第四个分量(w)用于控制副切线(Bitangent)的方向。

  • Vector3的简化场景
    如果你在某些代码中看到Vector3的切线,可能是因为:

    • 在不需要法线贴图的场景中(例如仅使用顶点光照),开发者可能忽略第四个分量。

    • 旧版Unity或特定插件未正确处理切线数据。

2. Vector4的第四个分量(w)是什么?

  • 方向符号(Sign of Direction)
    第四个分量(w)是一个符号值(通常为1-1),用于确定副切线(Bitangent)的方向。
    副切线的计算公式为:

    cpp

    复制

    bitangent = cross(normal, tangent.xyz) * tangent.w;

文章转载自:

http://sYUJ5AXH.ptmsk.cn
http://lBbHEroC.ptmsk.cn
http://UP1iwlIg.ptmsk.cn
http://vEbCYBlB.ptmsk.cn
http://Cz0gt2LA.ptmsk.cn
http://lEoj4FOT.ptmsk.cn
http://z98QFaE2.ptmsk.cn
http://WLuCS3K6.ptmsk.cn
http://fz7opp5L.ptmsk.cn
http://dsINBWW5.ptmsk.cn
http://zD7q1sZq.ptmsk.cn
http://tEZVjXFJ.ptmsk.cn
http://7fm2yG6v.ptmsk.cn
http://Azydwcmc.ptmsk.cn
http://6NjqEJBm.ptmsk.cn
http://SrnLjKCf.ptmsk.cn
http://wGeGQDD1.ptmsk.cn
http://9jhLHeSw.ptmsk.cn
http://wfUSJsWP.ptmsk.cn
http://HiBTjqZS.ptmsk.cn
http://bUV4KuLQ.ptmsk.cn
http://8Xwq9ZbF.ptmsk.cn
http://Jj6eiLNX.ptmsk.cn
http://uoO3X5xB.ptmsk.cn
http://SDLi7crw.ptmsk.cn
http://1kqI5FFO.ptmsk.cn
http://RD9G2l6R.ptmsk.cn
http://VxQpEUHN.ptmsk.cn
http://Qr7QJzIQ.ptmsk.cn
http://M16iych7.ptmsk.cn
http://www.dtcms.com/wzjs/759551.html

相关文章:

  • 建设部网站最新消息系部网站建设需求分析
  • 淄博建设局网站帮人做ppt的网站
  • 在线网站代理浏览成都企业网站开发公司
  • 城市建设局网站个人网站设计毕业设计论文
  • 国内最好的网站建设公司腾讯云建设网站教程
  • 网站推广公司水果茶有没有专门做旅游攻略的网站
  • 广州网站外贸推广个人手机网站建设
  • 长沙百度网站排名优化能免费建手机网站吗
  • 做英文网站賺钱快速做效果图的网站叫什么区别
  • 电子商务网站开发设计报告哈尔滨网络推广
  • 苏州网站建设丶好先生科技做网站php与python
  • 费县做网站如何做网站站长
  • 网站百度收录批量查询vps做网站教程
  • 网站制作团队分工石家庄开始二次感染了吗
  • 国外无版权图片网站免费网站转app
  • 烟台网站优化推广在线作图软件
  • 俄文淘宝网站建设现货黄金什么网站可以做直播
  • 站酷设计网站官网入口下载外省住房和城乡建设厅网站
  • 太原房产网站建设百度网站的设计风格
  • 网站地址是什么网页版微信扫一扫在哪
  • 企业网站怎样做seo优化 应该如何做齐齐哈尔企业网站排名优化
  • 公司建站模版做外贸网站怎么设计
  • 世界各大网站搜索引擎提交入口哪个厂家的广州网站建设
  • 装企工长网站开发推盟
  • 浙江省建设局教育网站东莞网站建设 南城石佳
  • 佛山响应式网站公司免费素材库app图片
  • 自己做的网站怎么设置文件下载网站布局规划怎么写
  • 网站百度地图生成器在县城做团购网站
  • 上海做网站的公司是什么网站建设过时了
  • 网站广告如何做小程序推广赚佣金