Unity Mesh Mesh 立方体Cube贴图以及六个面分别贴不同的图片

Posted 御雪妃舞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity Mesh Mesh 立方体Cube贴图以及六个面分别贴不同的图片相关的知识,希望对你有一定的参考价值。

在前面的篇章中已经有了怎么Mesh画一个立方体,当时的立方体是按照逆时针的画的,其它大都都是按照顺时针画的,当时一开始画立方体顺时针没画出来,有些面看不到就调换了下顺序,没特别注意方向问题,然而这一篇贴图是会暴露出这个问题,下面我们细细说来:


先展示两张最终结果:




一.Cube顺逆时针画的差异

我们用同样的方法画两个除了时针方向不一样,其它都一样的立方体。
脚本如下:
using UnityEngine;
using System.Collections;

public enum Direction

    ClockWise,
    Anti_ClockWise


[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class TestCubeDirection : MonoBehaviour


    public Material mat;

    public Direction direction;

    // Use this for initialization
    void Start()
    
        switch (direction)
        
            case Direction.ClockWise:
                DrawClockWiseCube();
                break;
            case Direction.Anti_ClockWise:
                DrawAnti_ClockWiseCube();
                break;
        
    

    /// <summary>
    /// 按顺时针画立方体
    /// </summary>
    void DrawClockWiseCube()
    
        gameObject.GetComponent<MeshRenderer>().material = mat;

        Mesh mesh = GetComponent<MeshFilter>().mesh;
        mesh.Clear();

        //设置顶点
        mesh.vertices = new Vector3[]
           new Vector3(0, 0, 0),
            new Vector3(1, 0, 0),
            new Vector3(1, 1, 0),
            new Vector3(0, 1, 0),
            new Vector3(0, 1, 1),
            new Vector3(1, 1, 1),
            new Vector3(1, 0, 1),
            new Vector3(0, 0, 1),
        ;

        //顺时针设置三角形的方向
        mesh.triangles = new int[]
       
            3, 0, 1,
            3,1,2,
            2,4,3,
            2,5,4,
            7,4,5,
            7,5,6,
            0,7,6,
            0,6,1,
            3,4,7,
            3,7,0,
            1,6,5,
            1,5,2

       ;

    

    /// <summary>
    /// 按逆时针画立方体
    /// </summary>
    void DrawAnti_ClockWiseCube()
    
        gameObject.GetComponent<MeshRenderer>().material = mat;

        Mesh mesh = GetComponent<MeshFilter>().mesh;
        mesh.Clear();

        //设置顶点
        mesh.vertices = new Vector3[]
           new Vector3(0, 0, 0),
            new Vector3(1, 0, 0),
            new Vector3(1, 1, 0),
            new Vector3(0, 1, 0),
            new Vector3(0, 1, 1),
            new Vector3(1, 1, 1),
            new Vector3(1, 0, 1),
            new Vector3(0, 0, 1),
        ;

        //逆时针设置
        mesh.triangles = new int[]
        
            3,1,0,
            3,2,1,
            2,3,4,
            2,4,5,
            7,5,4,
            7,6,5,
            0,6,7,
            0,1,6,
            3,7,4,
            3,0,7,
            1,5,6,
            1,2,5
        ;
    



结果如图所示:

顺时针方向的看不到看它那个方向的面,而逆时针的不会,都能看到,所以这里遗留一个问题在这里,后面还会提到。
遗留问题:顺时针,立方体不能看到朝向自己的面?


二、给立方体Cube贴图


一开始想的时候是一点思路一样,根据API上面的意思,贴图的数组大小和顶点数的大小是一致的,但是8个顶点是决定不了6个面的,想了很久想不明白后,楼主动手做了个 立方体,给它贴图:


这样一弄就一目了然了,我们把每个顶点拆成三个,每个面一个这样我们构造了24个顶点,然后8个面24个点贴图就顺理成章了。
首先,我们用Unity自带的Cube贴了图作为参考:


可以看到自带的一个面贴一张图,贴的很整齐,那下面我们看看自己动手怎么做
为了不浪费那个cube,我做了这样的操作,这样写起来方便点:


既然变成了24个顶点,更新后的顶点顺序如下,根据面数来写:
//设置顶点
        mesh.vertices = new Vector3[]
        
            //front
            new Vector3(0, 0, 0),
            new Vector3(0, 0, 1),
            new Vector3(1, 0, 1),
            new Vector3(1, 0, 0),

            //top
            new Vector3(0, 0, 1),
            new Vector3(0, 1, 1),
            new Vector3(1, 1, 1),
            new Vector3(1, 0, 1),

            //back
            new Vector3(0, 1, 1),
            new Vector3(0, 1, 0),
            new Vector3(1, 1, 0),
            new Vector3(1, 1, 1),

            //bottom
            new Vector3(0, 1, 0),
            new Vector3(0, 0, 0),
            new Vector3(1, 0, 0),
            new Vector3(1, 1, 0),

            //left
            new Vector3(0, 1, 0),
            new Vector3(0, 1, 1),
            new Vector3(0, 0, 1),
            new Vector3(0, 0, 0),

            //right
            new Vector3(1, 0, 0),
            new Vector3(1, 0, 1),
            new Vector3(1, 1, 1),
            new Vector3(1, 1, 0),
        ;

顶点顺序
顺时针的如下:
 mesh.triangles = new int[]
       
              0,1,2,
              0,2,3,
              4,5,6,
              4,6,7,
              8,9,10,
              8,10,11,
              12,13,14,
              12,14,15,
              16,17,18,
              16,18,19,
              20,21,22,
              20,22,23

       ;

逆时针的如下:
mesh.triangles = new int[]
       
              0,2,1,
              0,3,2,
              4,6,5,
              4,7,6,
              8,10,9,
              8,11,10,
              12,14,13,
              12,15,14,
              16,18,17,
              16,19,18,
              20,22,21,
              20,23,22
       ;

按照正常的贴图方式,给他们贴图:
Vector2[] uvs = new Vector2[mesh.vertices.Length];
        for (int i = 0; i < uvs.Length; i += 4)
        
            //正常贴图
            uvs[i] = new Vector2(0, 0);
            uvs[i + 1] = new Vector2(0, 1);
            uvs[i + 2] = new Vector2(1, 1);
            uvs[i + 3] = new Vector2(1, 0);

结果对比如图:



从图中可以看出,顺时针的贴图贴的是对的,但是朝向的方向看不到,逆时针的全都能看到,但是贴图方向错了。
楼主上网上查找了资料,有一篇说是跟法线有关,链接如下: http://answers.unity3d.com/questions/389434/drawing-a-cube-by-a-new-mesh.html

于是楼主给每个面都设置了法线方向:
Vector3[] normals = new Vector3[mesh.vertices.Length];
        for (int i = 0; i < normals.Length; i++)
        
            if (i < 4)
                normals[i] = Vector3.forward;
            if (i >= 4 && i < 8)
                normals[i] = Vector3.up;
            if (i >= 8 && i < 12)
                normals[i] = Vector3.back;
            if (i >= 12 && i < 16)
                normals[i] = Vector3.down;
            if (i >= 16 && i < 20)
                normals[i] = Vector3.left;
            if (i >= 20 && i < 24)
                normals[i] = Vector3.right;
        
        mesh.normals = normals;

结果如图:

除了亮度有变化,其它没啥变化,楼主想了很久想不通先放下不想了,有大神会的希望告知,万分感谢!
但是还是有其它办法的,于是楼主在逆时针的贴图上动了点变化:
 Vector2[] uvs = new Vector2[mesh.vertices.Length];
        for (int i = 0; i < uvs.Length; i += 4)
        
            //uvs[i] = new Vector2(0, 0);
            //uvs[i + 1] = new Vector2(0, 1);
            //uvs[i + 2] = new Vector2(1, 1);
            //uvs[i + 3] = new Vector2(1, 0);
            uvs[i] = new Vector2(1, 0);
            uvs[i + 1] = new Vector2(1, 1);
            uvs[i + 2] = new Vector2(0, 1);
            uvs[i + 3] = new Vector2(0, 0);
        
        mesh.uv = uvs;

结果如图:


现在看来逆时针的贴图做完改动后可以跟Unity自带的是一样的效果,所以此路不同换条路走还是可以的,当然前面那条路要是通了就更好哈!

三、给立方体Cube每个面贴不同的图片



楼主从网上找了张图片:

我们给立方体六个面贴不同的图:
这个只需要给贴图的uv做些改变,这里我们直接集合了一个方法;
Vector2[] sixTexForCube(Vector3[] verticles)
    
        Vector2[] uv = new Vector2[verticles.Length];

        float t = 1 / 3f;

        //front
        uv[0] = new Vector2(t, 0);
        uv[1] = new Vector2(t, t);
        uv[2] = new Vector2(0, t);
        uv[3] = new Vector2(0, 0);

        //top
        uv[4] = new Vector2(2 * t, 0);
        uv[5] = new Vector2(2 * t, t);
        uv[6] = new Vector2(t, t);
        uv[7] = new Vector2(t, 0);

        //back
        uv[8] = new Vector2(1, 0);
        uv[9] = new Vector2(1, t);
        uv[10] = new Vector2(2 * t, t);
        uv[11] = new Vector2(2 * t, 0);

        //Bottom
        uv[12] = new Vector2(t, t);
        uv[13] = new Vector2(t, 2 * t);
        uv[14] = new Vector2(0, 2 * t);
        uv[15] = new Vector2(0, t);

        //left
        uv[16] = new Vector2(2 * t, t);
        uv[17] = new Vector2(2 * t, 2 * t);
        uv[18] = new Vector2(t, 2 * t);
        uv[19] = new Vector2(t, t);

        //right
        uv[20] = new Vector2(1, t);
        uv[21] = new Vector2(1, 2 * t);
        uv[22] = new Vector2(2 * t, 2 * t);
        uv[23] = new Vector2(2 * t, t);

        return uv;
    

最终结果如图:


四、总结和完整代码


哈哈,虽然有一个遗留问题,但是最终的目的达到了,下面贴出这个的完整代码:
using UnityEngine;
using System.Collections;

[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class Test3D : MonoBehaviour


    public enum Direction
    
        ClockWise,
        Anti_ClockWise
    

    public Material mat;

    public Direction direction;

    // Use this for initialization
    void Start()
    
        switch (direction)
        
            case Direction.ClockWise:
                DrawCubeWithUV_CloclWise();
                break;
            case Direction.Anti_ClockWise:
                DrawCubeWithUV_Anti_CloclWise();
                break;
        
    



    void DrawCubeWithUV_CloclWise()
    
        gameObject.GetComponent<MeshRenderer>().material = mat;

        Mesh mesh = GetComponent<MeshFilter>().mesh;
        mesh.Clear();

        //设置顶点
        mesh.vertices = new Vector3[]
        
            //front
            new Vector3(0, 0, 0),
            new Vector3(0, 0, 1),
            new Vector3(1, 0, 1),
            new Vector3(1, 0, 0),

            //top
            new Vector3(0, 0, 1),
            new Vector3(0, 1, 1),
            new Vector3(1, 1, 1),
            new Vector3(1, 0, 1),

            //back
            new Vector3(0, 1, 1),
            new Vector3(0, 1, 0),
            new Vector3(1, 1, 0),
            new Vector3(1, 1, 1),

            //bottom
            new Vector3(0, 1, 0),
            new Vector3(0, 0, 0),
            new Vector3(1, 0, 0),
            new Vector3(1, 1, 0),

            //left
            new Vector3(0, 1, 0),
            new Vector3(0, 1, 1),
            new Vector3(0, 0, 1),
            new Vector3(0, 0, 0),

            //right
            new Vector3(1, 0, 0),
            new Vector3(1, 0, 1),
            new Vector3(1, 1, 1),
            new Vector3(1, 1, 0),
        ;



        //顺时针看不到正面的,贴图在里面
        mesh.triangles = new int[]
       
              0,1,2,
              0,2,3,
              4,5,6,
              4,6,7,
              8,9,10,
              8,10,11,
              12,13,14,
              12,14,15,
              16,17,18,
              16,18,19,
              20,21,22,
              20,22,23

       ;

        Vector2[] uvs = new Vector2[mesh.vertices.Length];
        for (int i = 0; i < uvs.Length; i += 4)
        
            //正常贴图
            uvs[i] = new Vector2(0, 0);
            uvs[i + 1] = new Vector2(0, 1);
            uvs[i + 2] = new Vector2(1, 1);
            uvs[i + 3] = new Vector2(1, 0);

            //转换贴图
            //uvs[i] = new Vector2(1, 0);
            //uvs[i + 1] = new Vector2(1, 1);
            //uvs[i + 2] = new Vector2(0, 1);
            //uvs[i + 3] = new Vector2(0, 0);
        
        mesh.uv = uvs;

        //Vector3[] normals = new Vector3[mesh.vertices.Length];
        //for (int i = 0; i < normals.Length; i++)
        //
        //    if (i < 4)
        //        normals[i] = Vector3.forward;
        //    if (i >= 4 && i < 8)
        //        normals[i] = Vector3.up;
        //    if (i >= 8 && i < 12)
        //        normals[i] = Vector3.back;
        //    if (i >= 12 && i < 16)
        //        normals[i] = Vector3.down;
        //    if (i >= 16 && i < 20)
        //        normals[i] = Vector3.left;
        //    if (i >= 20 && i < 24)
        //        normals[i] = Vector3.right;
        //
        //mesh.normals = normals;
    

    void DrawCubeWithUV_Anti_CloclWise()
    
        gameObject.GetComponent<MeshRenderer>().material = mat;

        Mesh mesh = GetComponent<MeshFilter>().mesh;
        mesh.Clear();

        //设置顶点
        mesh.vertices = new Vector3[]
        
            //front
            new Vector3(0, 0, 0),
            new Vector3(0, 0, 1),
            new Vector3(1, 0, 1),
            new Vector3(1, 0, 0),

            //top
            new Vector3(0, 0, 1),
            new Vector3(0, 1, 1),
            new Vector3(1, 1, 1),
            new Vector3(1, 0, 1),

            //back
            new Vector3(0, 1, 1),
            new Vector3(0, 1, 0),
            new Vector3(1, 1, 0),
            new Vector3(1, 1, 1),

            //bottom
            new Vector3(0, 1, 0),
            new Vector3(0, 0, 0),
            new Vector3(1, 0, 0),
            new Vector3(1, 1, 0),

            //left
            new Vector3(0, 1, 0),
            new Vector3(0, 1, 1),
            new Vector3(0, 0, 1),
            new Vector3(0, 0, 0),

            //right
            new Vector3(1, 0, 0),
            new Vector3(1, 0, 1),
            new Vector3(1, 1, 1),
            new Vector3(1, 1, 0),
        ;

        //逆时针看到的很好,但是贴图反了
        mesh.triangles = new int[]
       
              0,2,1,
              0,3,2,
              4,6,5,
              4,7,6,
              8,10,9,
              8,11,10,
              12,14,13,
              12,15,14,
              16,18,17,
              16,19,18,
              20,22,21,
              20,23,22
       ;
#if false
        //六个面贴同一张图片
        Vector2[] uvs = new Vector2[mesh.vertices.Length];
        for (int i = 0; i < uvs.Length; i += 4)
        
            //uvs[i] = new Vector2(0, 0);
            //uvs[i + 1] = new Vector2(0, 1);
            //uvs[i + 2] = new Vector2(1, 1);
            //uvs[i + 3] = new Vector2(1, 0);
            uvs[i] = new Vector2(1, 0);
            uvs[i + 1] = new Vector2(1, 1);
            uvs[i + 2] = new Vector2(0, 1);
            uvs[i + 3] = new Vector2(0, 0);
        
        mesh.uv = uvs;
#else
        //六个面贴不同的图片
        Vector2[] uvs = sixTexForCube(mesh.vertices);
        mesh.uv = uvs;
#endif
        //法线
        //Vector3[] normals = new Vector3[mesh.vertices.Length];
        //for (int i = 0; i < normals.Length; i++)
        //
        //    if (i < 4)
        //        normals[i] = Vector3.forward;
        //    if (i >= 4 && i < 8)
        //        normals[i] = Vector3.up;
        //    if (i >= 8 && i < 12)
        //        normals[i] = Vector3.back;
        //    if (i >= 12 && i < 16)
        //        normals[i] = Vector3.down;
        //    if (i >= 16 && i < 20)
        //        normals[i] = Vector3.left;
        //    if (i >= 20 && i < 24)
        //        normals[i] = Vector3.right;
        //
        //mesh.normals = normals;
    

    Vector2[] sixTexForCube(Vector3[] verticles)
    
        Vector2[] uv = new Vector2[verticles.Length];

        float t = 1 / 3f;

        //front
        uv[0] = new Vector2(t, 0);
        uv[1] = new Vector2(t, t);
        uv[2] = new Vector2(0, t);
        uv[3] = new Vector2(0, 0);

        //top
        uv[4] = new Vector2(2 * t, 0);
        uv[5] = new Vector2(2 * t, t);
        uv[6] = new Vector2(t, t);
        uv[7] = new Vector2(t, 0);

        //back
        uv[8] = new Vector2(1, 0);
        uv[9] = new Vector2(1, t);
        uv[10] = new Vector2(2 * t, t);
        uv[11] = new Vector2(2 * t, 0);

        //Bottom
        uv[12] = new Vector2(t, t);
        uv[13] = new Vector2(t, 2 * t);
        uv[14] = new Vector2(0, 2 * t);
        uv[15] = new Vector2(0, t);

        //left
        uv[16] = new Vector2(2 * t, t);
        uv[17] = new Vector2(2 * t, 2 * t);
        uv[18] = new Vector2(t, 2 * t);
        uv[19] = new Vector2(t, t);

        //right
        uv[20] = new Vector2(1, t);
        uv[21] = new Vector2(1, 2 * t);
        uv[22] = new Vector2(2 * t, 2 * t);
        uv[23] = new Vector2(2 * t, t);

        return uv;
    



创作挑战赛 新人创作奖励来咯,坚持创作打卡瓜分现金大奖

以上是关于Unity Mesh Mesh 立方体Cube贴图以及六个面分别贴不同的图片的主要内容,如果未能解决你的问题,请参考以下文章

Unity Mesh Mesh 平面图形的贴图

Unity Mesh Mesh给球贴图

unity---Mesh网格编程

unity---Mesh网格编程

unity---Mesh网格编程

unity---Mesh网格编程