unity3d - 从单色纹理生成网格

标签 unity3d runtime png alpha-transparency vertices

我编写了一个代码来绘制并生成该图的 Sprite 。所以我得到了一个白色背景的 Sprite 和我的画(颜色不同)。

我的问题:如何在运行时去除白色背景?(使用 C# 代码)

我的问题是:我想使用绘图生成网格,但是在白色背景下我有4个顶点(第四个角 Sprite ),我想从我在 Sprite 上绘制的真实形状中获取所有顶点(远远超过 4 个顶点)

我目前的想法是将绘图转换为具有透明背景,然后使用 unity 的 Sprite 打包器从中生成网格。

我的项目:这是一个游戏,我们可以在其中创建自己的游戏电路:用户绘制一个黑白 Sprite —> 我将其转换为带有对撞机的网格并生成新的游戏电路。

我已经精简到清除所有白色像素,但我不认为我会用这种技术得到很多顶点。

感谢帮助, 阿克塞尔 <强> the real shape

最佳答案

using System.IO;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.Networking;
public class scri : MonoBehaviour
{
    // For saving the mesh------------------------ 
    public KeyCode saveKey = KeyCode.F12;
    public string saveName = "SavedMesh";

    // Concerning mesher--------------------------
    public GameObject mesher; //require

    public List<Vector3> vertices;
    public  List<int> triangles;

    public Vector3 point0;
    public Vector3 point1;
    public Vector3 point2;
    public Vector3 point3;
    
    public int loop;
    public float size;

    public Mesh meshFilterMesh;
    public Mesh meshColliderMesh;

    // Sprite work
    public Color[] pixels;

    public Texture2D newTexture;  
    public Texture2D oldTexture;  //require

    private Sprite mySprite;
    private SpriteRenderer spriteRenderer;

    public int pathCount;

    public GameObject displayerComponent; //require

    public PolygonCollider2D polygonColliderAdded; //require

    void Start()
    {
        // Mesher
        vertices = new List<Vector3> (); 
        triangles = new List<int> (); 
        meshFilterMesh= mesher.GetComponent<MeshFilter>().mesh;
        meshColliderMesh= mesher.GetComponent<MeshCollider>().sharedMesh;
        size = 10; // lenght of the mesh in Z direction
        loop=0;

        // Sprite
        pixels = oldTexture.GetPixels();
        newTexture =new Texture2D(oldTexture.width,oldTexture.height,TextureFormat.ARGB32, false);
        spriteRenderer = gameObject.AddComponent<SpriteRenderer>();
        
        ConvertSpriteAndCreateCollider (pixels);
        BrowseColliderToCreateMesh (polygonColliderAdded);
        
    }

    void Update()
    {
        // Save if F12 press
        if (Input.GetKeyDown(saveKey)){SaveAsset();}
    }

    public void ConvertSpriteAndCreateCollider (Color[] pixels) {
        for (int i = 0 ; i < pixels.Length ; i++ ) 
        { 
            // delete all black pixel (black is the circuit, white is the walls)
            if ((pixels[i].r==0 && pixels[i].g==0 && pixels[i].b==0 && pixels[i].a==1)) {
                pixels[i] = Color.clear;
            }
        }
        // Set a new texture with this pixel list
        newTexture.SetPixels(pixels);
        newTexture.Apply();

        // Create a sprite from this texture
        mySprite = Sprite.Create(newTexture, new Rect(0, 0, newTexture.width, newTexture.height), new Vector2(10.0f,10.0f), 10.0f, 0, SpriteMeshType.Tight,new Vector4(0,0,0,0),false);

        // Add it to our displayerComponent
        displayerComponent.GetComponent<SpriteRenderer>().sprite=mySprite;

        // Add the polygon collider to our displayer Component and get his path count
        polygonColliderAdded = displayerComponent.AddComponent<PolygonCollider2D>();

    }

    // Method to browse the collider and launch makemesh
    public void BrowseColliderToCreateMesh (PolygonCollider2D polygonColliderAdded){
        //browse all path from collider
        pathCount=polygonColliderAdded.pathCount;
        for (int i = 0; i < pathCount; i++)
        {
            Vector2[] path = polygonColliderAdded.GetPath(i);

            // browse all path point
            for (int j = 1; j < path.Length; j++)
            {
                if (j != (path.Length - 1)) // if we aren't at the last point
                {
                point0 = new Vector3(path[j-1].x ,path[j-1].y ,0);
                point1 = new Vector3(path[j-1].x ,path[j-1].y ,size);
                point2 = new Vector3(path[j].x ,path[j].y ,size);
                point3 = new Vector3(path[j].x ,path[j].y ,0);
                    MakeMesh(point0,point1,point2,point3);

                } 
                else if(j == (path.Length - 1))// if we are at the last point, we need to close the loop with the first point
                {
                point0 = new Vector3(path[j-1].x ,path[j-1].y ,0);
                point1 = new Vector3(path[j-1].x ,path[j-1].y ,size);
                point2 = new Vector3(path[j].x ,path[j].y ,size);
                point3 = new Vector3(path[j].x ,path[j].y ,0);
                    MakeMesh(point0,point1,point2,point3);
                point0 = new Vector3(path[j].x ,path[j].y ,0);
                point1 = new Vector3(path[j].x ,path[j].y ,size);
                point2 = new Vector3(path[0].x ,path[0].y ,size); // First point
                point3 = new Vector3(path[0].x ,path[0].y ,0); // First point
                    MakeMesh(point0,point1,point2,point3);
                }
            }
        }
    }


    //Method to generate 2 triangles mesh from the 4 points 0 1 2 3 and add it to the collider
    public void MakeMesh (Vector3 point0,Vector3 point1,Vector3 point2, Vector3 point3){
        
        // Vertice add
        vertices.Add(point0);
        vertices.Add(point1);
        vertices.Add(point2);
        vertices.Add(point3);

        //Triangle order
        triangles.Add(0+loop*4);
        triangles.Add(2+loop*4);
        triangles.Add(1+loop*4);
        triangles.Add(0+loop*4);
        triangles.Add(3+loop*4);
        triangles.Add(2+loop*4);
        loop = loop + 1; 

        // create mesh 
        meshFilterMesh.vertices=vertices.ToArray();
        meshFilterMesh.triangles=triangles.ToArray();

        // add this mesh to the MeshCollider
        mesher.GetComponent<MeshCollider>().sharedMesh=meshFilterMesh;
    }

    // Save if F12 press
    public void SaveAsset() 
    {
        var mf = mesher.GetComponent<MeshFilter>();
        if (mf)
        {
            var savePath = "Assets/" + saveName + ".asset";
            Debug.Log("Saved Mesh to:" + savePath);
            AssetDatabase.CreateAsset(mf.mesh, savePath);
        }
    }
}

enter image description here

关于unity3d - 从单色纹理生成网格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53935476/

相关文章:

javascript - 在 Canvas 上,使用 png 绘制图像与使用笔画创建绘图之间的区别?

c# - 将列表转换为父类列表

c# - 如何统一检测单击和双击?

Linux 上的 Java Runtime.exec() 参数

image - OpenCV : Transparent area of imported . png 文件现在是白色的

c# - win2D uwp 不会在 inkcanvas 中保存高亮笔画

visual-studio-2010 - 安装UnityVS时出现套接字异常

unity3d - 拾取的物体移动时晃动

objective-c - 是否可以通过编程方式确定类具有哪些属性?

c++ - 如何在运行时计算 C++ 表达式类型?