unity3d - 如何从精灵创建四边形区域(texture2d)
问题描述
我有一个图像并将其作为可读/可写精灵添加到统一中。它是 32x32。但我不知道如何为顶点向量提供坐标,以便它给我一个与我的精灵形状相同的四边形区域。例如,如果我有一个 Heart.png 32x32 像素精灵,那么我想要一个四边形的心形区域
void Awake()
{
texture2D = sprite.texture;
mesh = new Mesh();
mf = GetComponent<MeshFilter>();
for(int i=0; i< texture2D.width; i++)
{
for(int j=0; j< texture2D.height; j++)
{
Color color = texture2D.GetPixel(i, j);
if(color.a == 0)
{
continue;
}
vertices = new Vector3[] { new Vector3(), new Vector3(), new Vector3(), new Vector3() };
indeces = new int[]{ 0, 1, 2, 2, 1, 3 };
mesh.vertices = vertices;
mesh.triangles = indeces;
}
}
mf.sharedMesh = mesh;
}
解决方案
其实这有点棘手。
我会做什么(因为它更容易实现 - 不是因为它更有效!)基本上是为每个像素创建一个具有相应颜色的小四边形(4个顶点-> 2个三角形)。
[SerializeField] private Texture2D texture;
[SerializeField] private Mesh mesh;
[SerializeField] private MeshFilter mf;
[ContextMenu("TEST")]
private void Awake()
{
// Just in case use the mesh format that allows more vertices
if(!mf) mf = GetComponent<MeshFilter>();
mesh = new Mesh {indexFormat = IndexFormat.UInt32};
// Create these ONCE and fill them bit by bit
var verticesList = new List<Vector3>();
var trianglesList = new List<int>();
var colors = new List<Color>();
// Do this in ONE call -> more efficient
var pixels = texture.GetPixels();
// Place the pivot in the center of the texture
var pivotOffset = -new Vector3(texture.width / 2f, texture.height / 2f);
for (var i = 0; i < texture.width; i++)
{
for (var j = 0; j < texture.height; j++)
{
var color = pixels[i + j * texture.width];
if (color.a == 0)
{
continue;
}
// Add the pixel color for the FOUR vertices we create
colors.Add(color);
colors.Add(color);
colors.Add(color);
colors.Add(color);
// Create the four vertices around this pixel position
var vertex0 = pivotOffset + new Vector3(i - 0.5f, j - 0.5f, 0);
var vertex1 = pivotOffset + new Vector3(i + 0.5f, j - 0.5f, 0);
var vertex2 = pivotOffset + new Vector3(i - 0.5f, j + 0.5f, 0);
var vertex3 = pivotOffset + new Vector3(i + 0.5f, j + 0.5f, 0);
// Store the current length of so far vertices => first new vertex index
var currentIndex = verticesList.Count;
// Add the vertices to the list
verticesList.Add(vertex0);
verticesList.Add(vertex1);
verticesList.Add(vertex2);
verticesList.Add(vertex3);
// Two triangles for front side
trianglesList.Add(currentIndex);
trianglesList.Add(currentIndex + 2);
trianglesList.Add(currentIndex + 3);
trianglesList.Add(currentIndex);
trianglesList.Add(currentIndex + 3);
trianglesList.Add(currentIndex + 1);
// For double sided add the inverted faces for the back as well
trianglesList.Add(currentIndex);
trianglesList.Add(currentIndex + 3);
trianglesList.Add(currentIndex + 2);
trianglesList.Add(currentIndex);
trianglesList.Add(currentIndex + 1);
trianglesList.Add(currentIndex + 3);
}
}
// Finally apply them ONCE to the mesh
mesh.vertices = verticesList.ToArray();
mesh.triangles = trianglesList.ToArray();
mesh.colors = colors.ToArray();
mf.sharedMesh = mesh;
}
好像
如您所见,您可以玩这些材料。通过将像素颜色存储到网格颜色中,您可以简单地使用支持顶点颜色的着色器。
进一步说明:
GetPixels
返回一个扁平的一维数组。在该数组中,纹理的像素逐行水平布置。这意味着可以说你有一个像
7 8 9 | 4 5 6 |-height=3 1 2 3 | _____ | width=3
它成为了
1, 2, 3, 4, 5, 6, 7, 8, 9
(Unity纹理坐标从左下角从0开始)
因此,为了访问某个条目
6
,例如位于像素坐标的条目,x=2, y=1
您必须去1, 2, 3, 4, 5, 6, 7, 8, 9 | x(=2) + y(=1) * width(=3)
如前所述,我的简单解决方案是不要像您尝试的那样为每个像素创建一个顶点,而是创建一个正方形。为此,我们需要像这样的顶点
p-0.5x+0.5y p+0.5x+0.5y V------------------V | | | | | p | | (actualPosition) | | | V------------------V p-0.5x-0.5y p+0.5x-0.5y
我希望令人敬畏的 ascii 艺术能以某种方式清楚地说明:D
最后
triangles
,Unity 中的网格是简单的int[]
,其中每个元素都引用vertices
数组中的一个顶点索引,并且总是3
连续的索引形成一个三角形。在一个三角形内,顶点的缠绕顺序定义了它所面向的方向。
- 如果顶点按顺时针顺序排列,则法线朝向您。
- 如果顶点按逆时针顺序排列,法线将背向您。
请参阅Unity 手册 - 创建四边形,我希望这些图形能解释其余部分
在我的每个像素的示例中,我按顺序添加了四个顶点的四边形
2----3 | / | | / | 0----1
然后我顺时针添加两个三角形
0
2
3
0
3
1
和逆时针(让它们双面)
0
3
2
0
1
3
最后,因为我们不希望索引从 0 开始,而是在
currentIndex
成为之前的相同值currentIndex+0
currentIndex+2
currentIndex+3
currentIndex+0
currentIndex+3
currentIndex+1
和
currentIndex+0
currentIndex+3
currentIndex+2
currentIndex+0
currentIndex+1
currentIndex+3
推荐阅读
- couchdb - 如何在 CouchDB 上设置虚拟主机?
- c# - 我怎样才能得到窗口标题以及这个代码
- python - 在 python 的图像处理中使用 for 循环的替代方法?
- angular - 升级到 Angular 7 后如何修复styles.scss?
- python-3.x - 使用 Python3 获取 Bacnet 值
- hash - 比特币中的假链是如何处理的?
- python-3.x - 替换由整数、浮点数和分类字符串组成的单列中的字符串(类别) - Pandas
- vespa - Vespa 的外部数据源
- sql - 需要一种方法来查找两个多对多关系之间的匹配
- scala - Matchers eq 错误地说列表不相等