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

来源:互联网 发布:js将 json转换对象数组 编辑:程序博客网 时间:2024/05/16 15:00

在前面的篇章中已经有了怎么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;    }}


0 0