unity, editable mesh
一,需求
从fbx载入的模型是不可以在unity里编辑的。
我有一人特殊的需求就是想在unity里为mesh的各顶点K动画。
于是需要自己实现一个可编辑(其实只是顶点可以拖动)的mesh。
二,思路
首先由导入的mesh复制一个新mesh,并将原mesh替换掉,这样是为了以后编辑过程不会破坏原mesh,然后就没有原mesh的事儿了。
假设mesh是一个立方体,则其mesh.vertices会有36个元素,mesh.triangles有12个元素。
我们要创建8个gameObject表示立方体的8个顶点gameObject,并根据mesh.vertices的坐标值设定顶点gameObject的localPosition(注意是localPosition而不是position),并且还要找出各顶点gameObject对象mesh.vertcies中的哪些元素。因为一共有8个顶点gameObject,但mesh.vertices有36个元素,所以一个gameObject对应多个元素。
三,unity里实现
1,创建一个gameObject,命句为editableMesh,并添加Mesh Filter和Mesh Renderer,Mesh Filter中添加模型mesh(例如从3dmax或blender中导出的模型)。
2,为editableMesh节点添加子节点vertexObjTemplate并将勾去掉使其变成Active==false状态,其上挂脚本vertexobjControl.cs:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class vertexObjControl : MonoBehaviour {
public List<int> m_vIDList=new List<int>();
}
3,为editableMesh节点添加脚本convertmeshToEditableMesh.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Assertions.Must;
[ExecuteInEditMode]
public class convertMeshToEditableMesh : MonoBehaviour {
private GameObject m_vertexObjs;
private GameObject m_vertexObjTemplate;
void Awake(){
m_vertexObjTemplate=transform.FindChild("vertexObjTemplate").gameObject;
CreateReplaceMeshFromOriginMesh ();
}
void Update(){
updateMeshVertex ();
}
void updateMeshVertex(){
int vertexCount = gameObject.GetComponent<MeshFilter> ().sharedMesh.vertexCount;
Vector3[] vertices = new Vector3[vertexCount] ;
int vertexObjCount = m_vertexObjs.transform.childCount;
for (int i=0; i<vertexObjCount; i++) {
GameObject vobj=m_vertexObjs.transform.GetChild(i).gameObject;
Vector3 vobjPos=vobj.transform.localPosition;
int nVID=vobj.GetComponent<vertexObjControl>().m_vIDList.Count;
for(int j=0;j<nVID;j++){
int vID=vobj.GetComponent<vertexObjControl>().m_vIDList[j];
vertices[vID]=vobjPos;
}
}
gameObject.GetComponent<MeshFilter> ().sharedMesh.vertices = vertices;
gameObject.GetComponent<MeshFilter> ().sharedMesh.RecalculateNormals();
gameObject.GetComponent<MeshFilter> ().sharedMesh.RecalculateBounds();
}
void CreateReplaceMeshFromOriginMesh()
{
//if vertexObjs is not created, create it
Transform vertexObjsTransform=transform.FindChild("vertexObjs");
if (vertexObjsTransform == null) {
m_vertexObjs = new GameObject ();
m_vertexObjs.name = "vertexObjs";
m_vertexObjs.transform.SetParent (gameObject.transform);
} else {
m_vertexObjs=vertexObjsTransform.gameObject;
}
//if mesh not replaced, replace it
if (gameObject.GetComponent<MeshFilter> ().sharedMesh.name != "replaceMesh") {
Mesh replaceMesh = Instantiate (gameObject.GetComponent<MeshFilter> ().sharedMesh) as Mesh;
replaceMesh.name = "replaceMesh";
gameObject.GetComponent<MeshFilter> ().sharedMesh = replaceMesh;
}
//if vobjs not generated, generate vobjs from replaved mesh
if (m_vertexObjs.transform.childCount == 0) {
int vertexCount = gameObject.GetComponent<MeshFilter> ().sharedMesh.vertexCount;
List<bool> list_isVIDHasAddedToVObj = new List<bool> ();
for (int i=0; i<vertexCount; i++) {
list_isVIDHasAddedToVObj.Add (false);
}
for (int vID=0; vID<vertexCount; vID++) {
if (list_isVIDHasAddedToVObj [vID]) {
continue;
}
//add vID of current vertex to existing vertexObj
Vector3 vPos = gameObject.GetComponent<MeshFilter> ().sharedMesh.vertices [vID];
int vertexObjCount = m_vertexObjs.transform.childCount;
for (int vobjID=0; vobjID<vertexObjCount; vobjID++) {
GameObject vobj = m_vertexObjs.transform.GetChild (vobjID).gameObject;
Vector3 vobjPos = vobj.transform.localPosition;
if (vPos == vobjPos) {
//add vID to vobj
vobj.GetComponent<vertexObjControl> ().m_vIDList.Add (vID);
list_isVIDHasAddedToVObj [vID] = true;
}
}
if (list_isVIDHasAddedToVObj [vID]) {//vID has added to existing vobj
//do nothing
} else {//no existing vobj for vID to add to
//create new vobj, and add vID to it
GameObject vobj = Instantiate (m_vertexObjTemplate);
vobj.SetActive (true);
vobj.name = "vobj_" + m_vertexObjs.transform.childCount;
vobj.transform.SetParent (m_vertexObjs.transform);
vobj.transform.localPosition = vPos;
vobj.GetComponent<vertexObjControl> ().m_vIDList.Add (vID);
list_isVIDHasAddedToVObj [vID] = true;
}
}
}
gameObject.GetComponent<MeshFilter> ().sharedMesh.RecalculateNormals();
gameObject.GetComponent<MeshFilter> ().sharedMesh.RecalculateBounds();
}
}
然后就可以在编辑器里移动mesh的顶点或给顶点K动画了。
----补充:
以上是通用的代码,可将任何mesh转成可编辑(只是移动顶点)的。
如果只想做一个可编辑的四边形面片,可以像下面这样简单实现:
1,创建一个gameObject命名为editableQuad。为editableQuad创建子节点vertexObjs。再为vertexObjs依次创建子节点vertexObj_0,vertexObj_1,vertexObj_2,vertexObj_3(按顺序排列)。
2,再为editableQuad添加脚本editableQuadControl.cs:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Assertions.Must;
[ExecuteInEditMode]
public class editableQuadControl : MonoBehaviour {
private GameObject vertexObjs;
void Awake(){
vertexObjs=transform.FindChild("vertexObjs").gameObject;
int childCount = vertexObjs.transform.childCount;
int n = 4;
for (int i=0; i<n; i++) {
if(i>=childCount){
GameObject vertexObj=new GameObject ();
vertexObj.name="vertexObj_"+i;
vertexObj.transform.SetParent(vertexObjs.transform);
vertexObj.transform.localPosition=Random.insideUnitSphere;
}
}
gameObject.GetComponent<MeshFilter> ().mesh = CreateMesh ();
}
void Update(){
updateMeshVertex ();
}
void updateMeshVertex(){
Vector3 vLU = vertexObjs.transform.GetChild(0).localPosition;
Vector3 vLD = vertexObjs.transform.GetChild(1).localPosition;
Vector3 vRU = vertexObjs.transform.GetChild(2).localPosition;
Vector3 vRD = vertexObjs.transform.GetChild(3).localPosition;
gameObject.GetComponent<MeshFilter> ().sharedMesh.vertices = new Vector3[]{vLD,vLU,vRU,vRD};
}
Mesh CreateMesh()
{
Mesh m = new Mesh();
m.name = "ScriptedMesh";
//note: unity is left-hand system
Vector3 vLU = vertexObjs.transform.GetChild(0).localPosition;
Vector3 vLD = vertexObjs.transform.GetChild(1).localPosition;
Vector3 vRU = vertexObjs.transform.GetChild(2).localPosition;
Vector3 vRD = vertexObjs.transform.GetChild(3).localPosition;
m.vertices = new Vector3[] {
vLD,//LD
vLU,//LU
vRU,//RU
vRD//RD
};
m.uv = new Vector2[] {
new Vector2 (0, 0),
new Vector2 (0, 1),
new Vector2 (1, 1),
new Vector2 (1, 0)
};
m.triangles = new int[] { 0, 1, 2, 0, 2, 3};
m.RecalculateNormals();
m.RecalculateBounds();
return m;
}
}
unity, editable mesh的更多相关文章
- Unity中Mesh分解与边缘高亮加上深度检测
一个比较简单的需求,不过遇到些坑,记录下. 房间有多个模型,每个模型可能多个SubMesh,点击后,需要能具体到是那个SubMesh,并且在这个SubMesh上显示边缘高光,以及能个性这单个SubMe ...
- Unity的Mesh压缩:为什么我的内存没有变化?
0x00 前言 最近和朋友聊天,谈到了Mesh的内存优化问题,他发现开启Model Importer面板上的Mesh Compression选项之后,内存并没有什么变化.事实上,期望开启Mesh Co ...
- 关于Unity中Mesh网格的详解
3D模型 通过3D建模软件所建出来的点和面,如以三角形为主的点和面,比如人的脑袋一个球,就是由各种各样的三角形组成的点和面. 点和面以及纹理坐标都是通过3D建模软件建模出来的. Unity会帮我们把模 ...
- unity, 获取mesh名称
正确的获取mesh名称的方法: MeshFilter meshFilter=node.GetComponent<MeshFilter>(); string meshName=mesh ...
- unity中mesh属性的uv坐标讨论
http://blog.sina.com.cn/s/blog_427cf00b0102vp0j.html 之前在做连连看游戏中,也用到贴图坐标,当时我们讲到,不管是平铺(Tiling)还是偏移(Off ...
- Unity中用Mesh画一个圆环
Probuider 前几天在做一个小项目的时候,用到了Unity自带的一个包ProBuilder其中的Arch生成1/4圆. 挺好玩的,可以在直接Unity中根据需要用Mesh定制生成图形,而不用建模 ...
- unity替换mesh测试
直接替换SkinnedMeshRender的Mesh,实现所谓断肢效果(不过最近发现,绑定多mesh似乎更好实现这样的效果.有时间准备写一篇): 只要不改变两个Mesh原始文件的层级,就不会出现权重的 ...
- Unity中用Mesh画一个圆环(二)
中目标-生成完整面 在之前的内容中我们已经成功生成了一个面,接下来我们要生成剩下的面就很容易了. 我们把之前生成的面当作顶面,接着我们来生成底面. 还记得前面说过\(\color{#1E90FF}{D ...
- Unity 绘制Mesh线条
using UnityEngine; using System.Collections; using System.Collections.Generic; public struct Segme ...
随机推荐
- MySql_安装及简单命令
一.下载MySql http://dev.mysql.com/downloads/file/?id=461390 版本位5.7.11.0.msi,32位的,但是该版本在64位机器上也可以使用 二.安装 ...
- OpenShift蓝绿及灰度部署
内容转自https://blog.csdn.net/jj_tyro/article/details/80136316, 并不断补充,感谢作者. 1.蓝绿部署 蓝绿部署实现的是全流量切换,适合于在测试完 ...
- $stateProvider resovle 无法找到的原因
$stateProvider 在写resolve的时候,也要写上controller,不能直接在页面上用ng-controller 来指定!!!! 不然的话,就是报依赖注入异常,找不到该provide ...
- Android 开发之 ---- bootloader (LK)
LK是什么 LK 是 Little Kernel 它是 appsbl (Applications ARM Boot Loader)流程代码 ,little kernel 是小内核小操作系统. LK ...
- 【云计算】Docker容器时间同步如何配置?
示例: # 3.8 配置时区.时钟同步 # configure timezone & ntp RUN echo ${TIME_ZONE} > /etc/timezone \ && ...
- github下fork后如何同步源的新更新
当然,那是完全不用命令行的办法,其实我还是更推荐命令行,流程如下: 首先要先确定一下是否建立了主repo的远程源: git remote -v 如果里面只能看到你自己的两个源(fetch 和 push ...
- Helpers.parallel_bulk in Python not working?
Helpers.parallel_bulk in Python not working? 学习了:https://discuss.elastic.co/t/helpers-parallel-bulk- ...
- HDU 3726 Graph and Queries treap树
题目来源:HDU 3726 Graph and Queries 题意:见白书 思路:刚学treap 參考白皮书 #include <cstdio> #include <cstring ...
- Android adb shell学习心得(四)
1.awk中的sub sub为替换函数.形式如 sub(/1/,"",$2) 将第二个变量的第一个1替换为空,若将sub替换为gsub.则替换全部的1. 2.awk中的-F 分隔符 ...
- Fireworks层与蒙版的概念和用法
添加热点也是可以嵌套的 切片工具将自动保存在网页图层,并且可以导出为图像 组合为蒙版就是让一部分图形显示的填充为一幅图片的东西,删除蒙版即可将其转换为一个普通的图层,否则还可以移动位置