在Unity3D C#中使用曲线将纹理拆分

3
我有一张纹理想要用Vector2数组分成两部分。我已经有了曲线上所有的Vector2点。
问题:
如何使用这些点将纹理切割成两部分?
备选方案/问题:
如何使用'像素'填充一个Vector2[]形状以创建纹理?

我的尝试

1)生成Vector2点以创建正方形,其中顶部为曲线边缘。看起来很有前途,但当我尝试生成网格时,点的排序是不正确的。

2)动态创建Polygon2D碰撞器-模仿切片纹理的底部部分-这与尝试1具有相同的问题,即点的排序。因此,当将Collider转换为Mesh时,结果显然与尝试相同。


在下面的图片中:
  1. 红线模拟我的Vector2数组
  2. 灰绿色的正方形是1024 x 1024像素的纹理
  3. 绿色区域是我想要的目标区域

Texture Slice Example


1
你在Unity文档和Stack Overflow上寻找过什么,但没有找到任何结果吗?(主要是因为你的问题似乎缺少解释你已经搜索/研究和尝试了什么部分) - Mike 'Pomax' Kamermans
所以...你需要两个新的纹理,可以用原始纹理的像素数据或透明度进行写入... - Draco18s no longer trusts SE
@Mike'Pomax'Kamermans会编辑我的问题并包含我尝试过的内容,谢谢。 - Marc Uberstein
@Draco18s 只需要1个纹理,然后使用Vector2数组来去除“线”上方的像素。 - Marc Uberstein
我会选择使用Mesh进行工作。我将通过从您的2D曲线填充其顶点数组以及在正方形的顶部(或底部)边缘上添加2个顶点来生成一个Mesh。然后,在这个新的Mesh上进行UV贴图,就好像我在整个正方形Mesh上进行贴图一样。然后将其渲染到RenderTexture中。我的意思是,这不是最优解决方案,您可能会遇到分辨率问题,它可能不是像素完美的等等,但它很健壮。 - Nika Kasradze
1个回答

1
这将创建一个您想要的形状的网格(但顶部边缘会有锯齿),希望这是朝着正确方向迈出的一步。Vector2 points[]数组包含您的红线。它应该按x坐标排序,并且所有数字应在0和1之间。需要使用纹理的网格过滤器和网格渲染器。
using UnityEngine;

[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class createMesh : MonoBehaviour {

    void Start () {
        Vector2[] points = new Vector2[4];
        points [0] = new Vector2 (0, .5f);
        points [1] = new Vector2 (.33f, 1f);
        points [2] = new Vector2 (.66f, .5f);
        points [3] = new Vector2 (1, 1f);

        MeshFilter mf = GetComponent<MeshFilter> ();
        Mesh mesh = new Mesh();


        Vector3[] verticies = new Vector3[points.Length * 2];
        int[] triangles = new int[(points.Length - 1)*6];
        Vector3[] normals = new Vector3[points.Length * 2];
        Vector2[] uv = new Vector2[points.Length * 2];

        int vIndex = 0;
        int tIndex = 0;
        int nIndex = 0;
        int uvIndex = 0;

        for (int i = 0; i< points.Length; i++) {
            Vector3 topVert = points[i];
            Vector3 bottomVert = topVert;
            bottomVert.y = 0;
            verticies[vIndex++]= bottomVert;
            verticies[vIndex++]=topVert;

            //uv
            uv[uvIndex++] = bottomVert;
            uv[uvIndex++] = topVert;

            //normals
            normals[nIndex++] = -Vector3.forward;
            normals[nIndex++] = -Vector3.forward;

            if (i<points.Length - 1) {
                //triangles
                triangles[tIndex++] = (i)*2;
                triangles[tIndex++] = (i)*2+1;
                triangles[tIndex++] = (i)*2+2;
                triangles[tIndex++] = (i)*2+2;
                triangles[tIndex++] = (i)*2+1;
                triangles[tIndex++] = (i)*2+3;

            }
        }

        mesh.vertices = verticies;
        mesh.triangles = triangles;
        mesh.normals = normals;
        mesh.uv = uv;

        mf.mesh = mesh;
    }
}

奖励:以下是一种仅使用纹理来完成的方法。为了使用此方法,必须将位图设置为高级,并在导入设置中启用读/写。该方法使用0到1023(或您纹理的大小)的坐标,并且应该也适用于超出该范围的数字。

using UnityEngine;
using System.Collections;


public class tex2d : MonoBehaviour {

    public Vector2[] points;

    void Start () {
        MeshRenderer mr;
        Texture2D t2d;
        Texture2D newTex = new Texture2D (1024, 1024);

        mr = GetComponent<MeshRenderer> ();
        t2d = mr.material.GetTexture (0) as Texture2D;
        MakeTex (points, t2d, ref newTex, 1024);
        mr.material.SetTexture (0, newTex);
    }


    void MakeTex(Vector2[] pnts, Texture2D inputTex, ref Texture2D outputTex, int size){

        Color bgcolor = new Color (1, 0, 1, 1);
        for (int i=0; i<(pnts.Length-1); i++) {
            Vector2 p1=pnts[i];
            Vector2 p2=pnts[i+1];

            //skip points that are out of range
            if ((p1.x <0 && p2.x <0) || (p1.x > size && p2.x>size)) continue;

            for (int x =(int)p1.x; x<(int)p2.x; x++) {
                if (x<0) continue;
                if (x>=size) break;

                float interpX = (x-p1.x)/(p2.x-p1.x);
                int interpY = (int) ((p2.y-p1.y)*interpX + p1.y);

                for (int y=0; y<interpY; y++) {
                    outputTex.SetPixel(x,y,inputTex.GetPixel(x,y));
                }
                for (int y= interpY; y<size; y++) {
                    outputTex.SetPixel(x,y,bgcolor);
                }

            }

        }
        outputTex.Apply ();
    }
}

谢谢你的回答。为什么这些值应该在0和1之间? - Marc Uberstein
太好了!我一有时间就会试一下,然后告诉你结果。谢谢。 - Marc Uberstein
我也添加了第二种方法。 - Chris H
请问您能否在这个问题上颁发悬赏奖金? - Chris H
我已经将你的代码应用到我的工作项目中,但是并没有起作用...即使使用了归一化的向量2点。我会快速创建一个测试项目,看看你的代码是否能在不同的情况下工作。 - Marc Uberstein
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接