unity 编辑mesh顶点位置
2018-02-10 17:09
453 查看
在某些特殊情况下,不得不对模型进行一些简单的修改,所以写了个简单的编辑脚本。
思路就是获取mesh上的所有顶点,然后在每个顶点位置创建一个控制点,控制点可以是任意你喜欢的物体,通过判断控制点的位置信息来修改mesh的顶点位置。
在unity中,mesh上的顶点与几个面相交,就会有几个坐标点,估计是把点为每一个三角形面复制了一份,所以这里在生成控制点时要注意剔除重复的点,不要重复生成。
这里我是把每个顶点的坐标转为字符串,使用该坐标的字符串作为key来把控制点与顶点数据联系起来。
下面给出完整代码
首先是控制点的脚本:using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeshEditorPoint : MonoBehaviour {
//顶点id,(顶点初始位置转字符串)
[HideInInspector] public string pointid;
//记录坐标点上一次移动的位置,用于判断控制点是否移动
[HideInInspector] private Vector3 lastPosition;
public delegate void MoveDelegate(string pid,Vector3 pos);
//控制点移动时的回调
public MoveDelegate onMove = null;
// Use this for initialization
void Start () {
lastPosition = transform.position;
}
// Update is called once per frame
void Update () {
if(transform.position != lastPosition){
if(onMove != null) onMove(pointid, transform.localPosition);
lastPosition = transform.position;
}
}
}然后是顶点编辑脚本:using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Text;
using System;
public class ModelMeshEditor : MonoBehaviour {
//控制点的大小
public float pointScale = 1.0f;
private float lastPointScale = 1.0f;
Mesh mesh;
//顶点列表
List<Vector3> positionList = new List<Vector3>();
//顶点控制物体列表
List<GameObject> positionObjList = new List<GameObject>();
/// <summary>
/// key:顶点字符串
/// value:顶点在列表中的位置
/// </summary>
Dictionary<string, List<int>> pointmap = new Dictionary<string, List<int>>();
// Use this for initialization
void Start () {
lastPointScale = pointScale;
mesh = GetComponent<MeshFilter>().sharedMesh;
CreateEditorPoint();
}
//创建控制点
public void CreateEditorPoint(){
positionList = new List<Vector3>(mesh.vertices);
for (int i = 0; i < mesh.vertices.Length; i++)
{
string vstr = Vector2String(mesh.vertices[i]);
if(!pointmap.ContainsKey(vstr)){
pointmap.Add(vstr,new List<int>());
}
pointmap[vstr].Add(i);
}
foreach (string key in pointmap.Keys)
{
GameObject editorpoint = (GameObject)Resources.Load("Prefabs/MeshEditor/MeshEditorPoint");
editorpoint = Instantiate(editorpoint);
editorpoint.transform.parent = transform;
editorpoint.transform.localPosition = String2Vector(key);
editorpoint.transform.localScale = new Vector3(1f, 1f, 1f);
MeshEditorPoint editorPoint = editorpoint.GetComponent<MeshEditorPoint>();
editorPoint.onMove = PointMove;
editorPoint.pointid = key;
positionObjList.Add(editorpoint);
}
}
//顶点物体被移动时调用此方法
public void PointMove(string pointid,Vector3 position){
if(!pointmap.ContainsKey(pointid)){
return;
}
List<int> _list = pointmap[pointid];
for (int i = 0; i < _list.Count; i ++){
positionList[_list[i]] = position;
}
mesh.vertices = positionList.ToArray();
mesh.RecalculateNormals();
}
// Update is called once per frame
void Update () {
//检测控制点尺寸是否改变
if (Math.Abs(lastPointScale - pointScale) > 0.1f){
lastPointScale = pointScale;
for (int i = 0; i < positionObjList.Count; i ++){
positionObjList[i].transform.localScale = new Vector3(pointScale, pointScale, pointScale);
}
}
}
string Vector2String(Vector3 v){
StringBuilder str = new StringBuilder();
str.Append(v.x).Append(",").Append(v.y).Append(",").Append(v.z);
return str.ToString();
}
Vector3 String2Vector(string vstr)
{
try{
string[] strings = vstr.Split(',');
return new Vector3(float.Parse(strings[0]), float.Parse(strings[1]), float.Parse(strings[2]));
}catch(Exception e){
Debug.LogError(e.ToString());
return Vector3.zero;
}
}
}
使用:
首先制作控制点的prefab,然后挂载上MeshEditorPoint脚本。
在想要编辑的mesh的GameObject上挂载ModelMeshEditor,不要忘记修改ModelMeshEditor中加载prefab的路径。
然后运行场景可就可以看到模型上的控制点了:
然后就可以拖动这些控制点来改变mesh的顶点数据了:
***注意:这里对mesh的修改是即时保存的,并且不能恢复,修改之前请务必做好备份!!!也可以修改我上面的脚本,在开始时复制一个mesh来修改,修改后再决定是否需要保存。
思路就是获取mesh上的所有顶点,然后在每个顶点位置创建一个控制点,控制点可以是任意你喜欢的物体,通过判断控制点的位置信息来修改mesh的顶点位置。
在unity中,mesh上的顶点与几个面相交,就会有几个坐标点,估计是把点为每一个三角形面复制了一份,所以这里在生成控制点时要注意剔除重复的点,不要重复生成。
这里我是把每个顶点的坐标转为字符串,使用该坐标的字符串作为key来把控制点与顶点数据联系起来。
下面给出完整代码
首先是控制点的脚本:using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeshEditorPoint : MonoBehaviour {
//顶点id,(顶点初始位置转字符串)
[HideInInspector] public string pointid;
//记录坐标点上一次移动的位置,用于判断控制点是否移动
[HideInInspector] private Vector3 lastPosition;
public delegate void MoveDelegate(string pid,Vector3 pos);
//控制点移动时的回调
public MoveDelegate onMove = null;
// Use this for initialization
void Start () {
lastPosition = transform.position;
}
// Update is called once per frame
void Update () {
if(transform.position != lastPosition){
if(onMove != null) onMove(pointid, transform.localPosition);
lastPosition = transform.position;
}
}
}然后是顶点编辑脚本:using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Text;
using System;
public class ModelMeshEditor : MonoBehaviour {
//控制点的大小
public float pointScale = 1.0f;
private float lastPointScale = 1.0f;
Mesh mesh;
//顶点列表
List<Vector3> positionList = new List<Vector3>();
//顶点控制物体列表
List<GameObject> positionObjList = new List<GameObject>();
/// <summary>
/// key:顶点字符串
/// value:顶点在列表中的位置
/// </summary>
Dictionary<string, List<int>> pointmap = new Dictionary<string, List<int>>();
// Use this for initialization
void Start () {
lastPointScale = pointScale;
mesh = GetComponent<MeshFilter>().sharedMesh;
CreateEditorPoint();
}
//创建控制点
public void CreateEditorPoint(){
positionList = new List<Vector3>(mesh.vertices);
for (int i = 0; i < mesh.vertices.Length; i++)
{
string vstr = Vector2String(mesh.vertices[i]);
if(!pointmap.ContainsKey(vstr)){
pointmap.Add(vstr,new List<int>());
}
pointmap[vstr].Add(i);
}
foreach (string key in pointmap.Keys)
{
GameObject editorpoint = (GameObject)Resources.Load("Prefabs/MeshEditor/MeshEditorPoint");
editorpoint = Instantiate(editorpoint);
editorpoint.transform.parent = transform;
editorpoint.transform.localPosition = String2Vector(key);
editorpoint.transform.localScale = new Vector3(1f, 1f, 1f);
MeshEditorPoint editorPoint = editorpoint.GetComponent<MeshEditorPoint>();
editorPoint.onMove = PointMove;
editorPoint.pointid = key;
positionObjList.Add(editorpoint);
}
}
//顶点物体被移动时调用此方法
public void PointMove(string pointid,Vector3 position){
if(!pointmap.ContainsKey(pointid)){
return;
}
List<int> _list = pointmap[pointid];
for (int i = 0; i < _list.Count; i ++){
positionList[_list[i]] = position;
}
mesh.vertices = positionList.ToArray();
mesh.RecalculateNormals();
}
// Update is called once per frame
void Update () {
//检测控制点尺寸是否改变
if (Math.Abs(lastPointScale - pointScale) > 0.1f){
lastPointScale = pointScale;
for (int i = 0; i < positionObjList.Count; i ++){
positionObjList[i].transform.localScale = new Vector3(pointScale, pointScale, pointScale);
}
}
}
string Vector2String(Vector3 v){
StringBuilder str = new StringBuilder();
str.Append(v.x).Append(",").Append(v.y).Append(",").Append(v.z);
return str.ToString();
}
Vector3 String2Vector(string vstr)
{
try{
string[] strings = vstr.Split(',');
return new Vector3(float.Parse(strings[0]), float.Parse(strings[1]), float.Parse(strings[2]));
}catch(Exception e){
Debug.LogError(e.ToString());
return Vector3.zero;
}
}
}
使用:
首先制作控制点的prefab,然后挂载上MeshEditorPoint脚本。
在想要编辑的mesh的GameObject上挂载ModelMeshEditor,不要忘记修改ModelMeshEditor中加载prefab的路径。
然后运行场景可就可以看到模型上的控制点了:
然后就可以拖动这些控制点来改变mesh的顶点数据了:
***注意:这里对mesh的修改是即时保存的,并且不能恢复,修改之前请务必做好备份!!!也可以修改我上面的脚本,在开始时复制一个mesh来修改,修改后再决定是否需要保存。
相关文章推荐
- unity 增加顶点数,熟悉mesh的构成
- Unity Mesh Collider 顶点太多报错
- [引擎]之二:unity中查看简单mesh顶点顺序的小工具
- [引擎]之四:unity中查看简单mesh顶点顺序的小工具——修改
- unity 在Mesh中的顶点或者mesh 三角形的中点生成物体
- Unity Shader入门精要笔记(六):由一个简单的顶点/片元着色器谈起
- Android studio 中快捷键 返回上次编辑的位置 ctrl+alt+left/right无法使用
- Unity合并mesh
- 使用vs2010编辑Unity脚本,配置方法
- sublime返回上一编辑位置
- unity中顶点片段shader环境反射
- unity 中playerprefs 会把数据写在什么位置
- 计算Mesh中顶点切线的方法
- error CS1061: Type `UnityEngine.Mesh' does not contain a definition for `GetTriangleStrip' and no ex
- JS在可编辑的div中的光标位置插入内容或表情
- Unity 相机围绕物体指定观察角度和位置
- .viminfo权限引起的vim无法记住上次编辑位置
- Unity教程之-制作闪亮的星星Star(一):动态的创建Mesh
- [Unity]将摄像机移动到Scene视角位置
- [Unity]自适应,动态变化位置的摇杆的实现。