先看图:
原理很简单,就是编写代码时费脑....
简单看了一下官方实例工程bootcamp中的Decal System,也是类似这种原理(Decal System更加复杂些,通过2次剔除三角形,并且切割三角型来生成一个新的面,一两句说不清,有兴趣的朋友可以看看《游戏编程精粹2》中操作几何体那一章,一模一样),通过复制一部分目标对象的网格,贴上图,再将这个有新网格的对象作为目标对象的child。只不过官方的计算速度快得多得多,这个至于为什么还在研究中...下图为使用bootcamp中的Decal System效果
代码:
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.由于每次执行时都要遍历整个对象网格的所有顶点,所以效率可想而知....欢迎各位指教!