Unity3D:是否可以在不重新计算三角形、uv 和法线的情况下动态更改网格中的顶点?
Unity3D : is it possible to dynamically change a vertex in a mesh without recalculating trianglaes, uv and normals?
我已经按照以下代码成功创建了一个立方体:http://wiki.unity3d.com/index.php/ProceduralPrimitives 并且使用纹理得到了这个:
但是如果我尝试改变一个顶点的位置,一半的三角形会倒转,如下图所示。
我还尝试通过为它们提供完全相同的值(我复制/粘贴用于创建顶点的代码)并使用 mesh.vertices = vertices
重新分配顶点来一次更改所有顶点,但我得到完全相同的三角形问题
所有的三角形都在那里,但其中一半最终镜像到网格内部,立方体的形状消失了。
当我还重新计算三角形时,纹理不合适,如果我想要一个看起来正常的立方体,我需要重新计算法线和 UV。
这对我来说似乎不对,因为我正在更改顶点的位置但没有更改任何边/三角形。我不明白为什么我必须重新计算它们。
有没有一种方法可以改变立方体的形状而无需重新计算所有内容?
我没有添加/删除顶点并且立方体没有被扭曲/变形(左上角的顶点仍然是左上角的顶点等等)
注意 : 我想在运行时间
改变顶点的位置
编辑:这是导致错误的代码:
float width = 10f;
float height = 10f;
float length = 10f;
Vector3 p0 = new Vector3(-width * .5f, -height * .5f, length * .5f);
Vector3 p1 = new Vector3(width * .5f, -height * .5f, length * .5f);
Vector3 p2 = new Vector3(width * .5f, -height * .5f, -length * .5f);
Vector3 p3 = new Vector3(-width * .5f, -height * .5f, -length * .5f);
Vector3 p4 = new Vector3(-width * .5f, height * .5f, length * .5f);
Vector3 p5 = new Vector3(width * .5f, height * .5f, length * .5f);
Vector3 p6 = new Vector3(width * .5f, height * .5f, -length * .5f);
Vector3 p7 = new Vector3(-width * .5f, height * .5f, -length * .5f);
Vector3[] vertices = new Vector3[] {
// Bottom
p0, p1, p2, p3,
// Left
p7, p4, p0, p3,
// Front
p4, p5, p1, p0,
// Back
p6, p7, p3, p2,
// Right
p5, p6, p2, p1,
// Top
p7, p6, p5, p4
};
_selectionBoxMeshFilter.mesh.vertices = vertices;
它与最初用于创建网格的代码完全相同。在创建网格后调用它时,网格会做一些奇怪的事情。
mesh.Optimize
重新排序 vertices
和 re-arranges triangles
以提高渲染效率。
您没有用相同的值替换 vertices
的当前值,因为在这种情况下顺序恰好不同。
要解决此问题,请不要假设顶点将与它们分配给 mech.vertices
时的位置相同。
一个解决方案可能是在调用 mesh.Optimize
之后为每个顶点制作一个索引映射,并基于此映射assign/edit 个顶点:
private List<int> indicesOfP0;
// ...
_selectionBoxMeshFilter.mesh.Optimize();
indicesOfP0 = new List<int>();
for (int i = 0 ; i < _selectionBoxMeshFilter.mesh.vertices.Length ; i++)
{
if (_selectionBoxMeshFilter.mesh.vertices[i] == p0)
{
indicesOfP0.Add(i);
}
}
// ...
Vector3[] vertices = _selectionBoxMeshFilter.mesh.vertices;
foreach (int i in indicesOfP0)
{
vertices[i] += Vector3.up * Time.deltaTime;
}
_selectionBoxMeshFilter.mesh.vertices = vertices;
更好的选择可能是根据每个顶点的位置计算如何处理每个顶点:
Vector3[] vertices = _selectionBoxMeshFilter.mesh.vertices;
for (int i = 0; i < vertices.Length; i++)
{
if (vertices[i].y>0)
{
vertices[i] += Vector3.up * Time.deltaTime;
}
}
_selectionBoxMeshFilter.mesh.vertices = vertices;
但是如果您必须分配一个位置数组,请考虑在调用 mesh.Optimize
之后将其基于位置:
private Vector3[] startPos;
// ...
_selectionBoxMeshFilter.mesh.Optimize();
startPos = _selectionBoxMeshFilter.mesh.vertices;
// ...
_selectionBoxMeshFilter.mesh.vertices = startPos;
我已经按照以下代码成功创建了一个立方体:http://wiki.unity3d.com/index.php/ProceduralPrimitives 并且使用纹理得到了这个:
但是如果我尝试改变一个顶点的位置,一半的三角形会倒转,如下图所示。
我还尝试通过为它们提供完全相同的值(我复制/粘贴用于创建顶点的代码)并使用 mesh.vertices = vertices
重新分配顶点来一次更改所有顶点,但我得到完全相同的三角形问题
所有的三角形都在那里,但其中一半最终镜像到网格内部,立方体的形状消失了。
当我还重新计算三角形时,纹理不合适,如果我想要一个看起来正常的立方体,我需要重新计算法线和 UV。
这对我来说似乎不对,因为我正在更改顶点的位置但没有更改任何边/三角形。我不明白为什么我必须重新计算它们。
有没有一种方法可以改变立方体的形状而无需重新计算所有内容?
我没有添加/删除顶点并且立方体没有被扭曲/变形(左上角的顶点仍然是左上角的顶点等等)
注意 : 我想在运行时间
改变顶点的位置编辑:这是导致错误的代码:
float width = 10f;
float height = 10f;
float length = 10f;
Vector3 p0 = new Vector3(-width * .5f, -height * .5f, length * .5f);
Vector3 p1 = new Vector3(width * .5f, -height * .5f, length * .5f);
Vector3 p2 = new Vector3(width * .5f, -height * .5f, -length * .5f);
Vector3 p3 = new Vector3(-width * .5f, -height * .5f, -length * .5f);
Vector3 p4 = new Vector3(-width * .5f, height * .5f, length * .5f);
Vector3 p5 = new Vector3(width * .5f, height * .5f, length * .5f);
Vector3 p6 = new Vector3(width * .5f, height * .5f, -length * .5f);
Vector3 p7 = new Vector3(-width * .5f, height * .5f, -length * .5f);
Vector3[] vertices = new Vector3[] {
// Bottom
p0, p1, p2, p3,
// Left
p7, p4, p0, p3,
// Front
p4, p5, p1, p0,
// Back
p6, p7, p3, p2,
// Right
p5, p6, p2, p1,
// Top
p7, p6, p5, p4
};
_selectionBoxMeshFilter.mesh.vertices = vertices;
它与最初用于创建网格的代码完全相同。在创建网格后调用它时,网格会做一些奇怪的事情。
mesh.Optimize
重新排序 vertices
和 re-arranges triangles
以提高渲染效率。
您没有用相同的值替换 vertices
的当前值,因为在这种情况下顺序恰好不同。
要解决此问题,请不要假设顶点将与它们分配给 mech.vertices
时的位置相同。
一个解决方案可能是在调用 mesh.Optimize
之后为每个顶点制作一个索引映射,并基于此映射assign/edit 个顶点:
private List<int> indicesOfP0;
// ...
_selectionBoxMeshFilter.mesh.Optimize();
indicesOfP0 = new List<int>();
for (int i = 0 ; i < _selectionBoxMeshFilter.mesh.vertices.Length ; i++)
{
if (_selectionBoxMeshFilter.mesh.vertices[i] == p0)
{
indicesOfP0.Add(i);
}
}
// ...
Vector3[] vertices = _selectionBoxMeshFilter.mesh.vertices;
foreach (int i in indicesOfP0)
{
vertices[i] += Vector3.up * Time.deltaTime;
}
_selectionBoxMeshFilter.mesh.vertices = vertices;
更好的选择可能是根据每个顶点的位置计算如何处理每个顶点:
Vector3[] vertices = _selectionBoxMeshFilter.mesh.vertices;
for (int i = 0; i < vertices.Length; i++)
{
if (vertices[i].y>0)
{
vertices[i] += Vector3.up * Time.deltaTime;
}
}
_selectionBoxMeshFilter.mesh.vertices = vertices;
但是如果您必须分配一个位置数组,请考虑在调用 mesh.Optimize
之后将其基于位置:
private Vector3[] startPos;
// ...
_selectionBoxMeshFilter.mesh.Optimize();
startPos = _selectionBoxMeshFilter.mesh.vertices;
// ...
_selectionBoxMeshFilter.mesh.vertices = startPos;