Unity3d模型网格复制初探

时间:2024-04-05 11:48:27

先看图:

Unity3d模型网格复制初探

原理很简单,就是编写代码时费脑....

简单看了一下官方实例工程bootcamp中的Decal System,也是类似这种原理(Decal System更加复杂些,通过2次剔除三角形,并且切割三角型来生成一个新的面,一两句说不清,有兴趣的朋友可以看看《游戏编程精粹2》中操作几何体那一章,一模一样),通过复制一部分目标对象的网格,贴上图,再将这个有新网格的对象作为目标对象的child。只不过官方的计算速度快得多得多,这个至于为什么还在研究中...下图为使用bootcamp中的Decal System效果

Unity3d模型网格复制初探

代码:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Decaller : MonoBehaviour {


// Use this for initialization
public Vector3 size = new Vector3(1,1,1);//包围盒尺寸
public Vector3 center = Vector3.zero;//包围盒中心坐标
private Bounds bounds;//包围盒对象
public GameObject target;//目标对象变量
private Mesh targetMesh;//目标对象的网格
private List<Vector3> vertices;//顶点数组
private List<int> triangles;//三角形索引数组

void BoundsCapture()//主要功能就在这个函数中
{
//思路:
//1.找出包围盒包含的三角形
//2.将这些三角形使用的顶点加入vertices数组,并构建triangles数组,最后将这些东西赋值给新的网格
for(int i =0;i<targetMesh.triangles.Length;i+=3)
{
 
int  containCount = 0;
for(int j =0;j<3;j++)
{
    if(bounds.Contains( targetMesh.vertices[targetMesh.triangles[i+j]] ) )
    {
        containCount++;
    }
    else
    {
        containCount--;
    }

    if(containCount == 3)//当前三角形三个顶点都被包围才加入数组
    {
        for( int k = 0 ;k<3 ;k++ )//加入当前测试通过的三个顶点
    { 

    //如果顶点已存在当前顶点数组中时不再添加
    if(!vertices.Contains(targetMesh.vertices[targetMesh.triangles[i+k]]))
        vertices.Add(targetMesh.vertices[targetMesh.triangles[i+k]]);
    

    //将目标顶点在当前vertices数组中的索引值加入triangles数组 
    triangles.Add(vertices.IndexOf(targetMesh.vertices[targetMesh.triangles[i+k]]));
}
}
}
}
//能最少组成一个三角形时才生成新对象
if(vertices.Count>=3 & triangles.Count>0)
{
 
GameObject newGO = new GameObject();
newGO.AddComponent<MeshFilter>();
newGO.AddComponent<MeshRenderer>();
newGO.GetComponent<MeshFilter>().mesh.vertices = vertices.ToArray();
newGO.GetComponent<MeshFilter>().mesh.triangles = triangles.ToArray();
newGO.GetComponent<MeshFilter>().mesh.RecalculateNormals();
newGO.GetComponent<MeshFilter>().mesh.RecalculateBounds();
vertices.Clear();
triangles.Clear();
}


}

void UpdateBounds()//更新包围盒位置信息
{
bounds.center = transform.position;
}

//--------------------------------------------
void Start () 
{
center = transform.position;
bounds = new Bounds(center,size);
vertices = new List<Vector3>();
triangles = new List<int>();
if(target!=null)
targetMesh = target.GetComponent<MeshFilter>().mesh;

}


// Update is called once per frame
void Update ()
{  
UpdateBounds();
if(Input.GetButtonDown("Jump"))//按下空格键就执行复制
{
  BoundsCapture();
}

}

ps.由于每次执行时都要遍历整个对象网格的所有顶点,所以效率可想而知....欢迎各位指教!

转载于:https://my.oschina.net/yuana/blog/110641