1. 程式人生 > >Unity Mesh(七) Mesh給球貼圖

Unity Mesh(七) Mesh給球貼圖

之前在

   中已經說明了如何畫球,現在我們在這個球的基礎上貼圖。

          這裡我們有個極座標和直角座標的轉換,具體我也不是很明白,反正就是拿來用吧,據某位大神講解,極座標(球座標)由球半徑,水平角和垂直角決定,我們完全可以理解為三維座標轉換成uv座標的方程,也就是三維座標對映到uv座標上,f(u,v)=[x,y,z]這樣的一個對映關係,對映關係取決於函式具體怎麼定義的或者這個球是怎麼畫的,不同的模型有不同的方法,典型的克萊因瓶一個uv完整的模型,它有自己的函式。

好了,樓主還是參考的Jasper Flick的方法,這個大神一直很崇拜。

f(u,v)=[x,y,z]

u=asin(y) / π + ½

.

v=atan2(x, z) / -2π

unity自帶的球貼圖會在兩個極點出現扭曲Twisting的現象:


包括我們之前建立的球也沒有考慮到這一個點,原因是計算極點的座標時,極點只有一個座標,但是極點每個四分之一圓實際上是我們極點四個三角形公用了一個uv座標,這樣就會造成扭曲現象,解決方法是我們把極點的點拆分成四個相同的點,一個面一個。

這樣的話,我們之前畫球的點稍稍有改動,上下兩個極點分別加三個點。

這樣這個問題就解決了!

下面我們直接上圖:


這個最後的完整程式碼如下:

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class DrawOctahedronSphere : MonoBehaviour
{
    public Material mat;

    public int subdivisions;
    public int radius;

    private static Vector3[] directions = {
        Vector3.left,
        Vector3.back,
        Vector3.right,
        Vector3.forward
    };

    void Start()
    {
        DrawSphere(subdivisions, radius);
    }

    public void DrawSphere(int subdivisions = 0, float radius = 1)
    {
        if (subdivisions > 4)
        {
            subdivisions = 4;
        }

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

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

        int resolution = 1 << subdivisions;
        Vector3[] vertices = new Vector3[(resolution + 1) * (resolution + 1) * 4 - 3 * (resolution * 2 - 1)];
        int[] triangles = new int[(1 << (subdivisions * 2 + 3)) * 3];
        CreateOctahedron(vertices, triangles, resolution);

        if (radius != 1f)
        {
            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i] *= radius;
            }
        }

        Vector3[] normals = new Vector3[vertices.Length];
        Normalize(vertices, normals);

        Vector2[] uv = new Vector2[vertices.Length];
        CreateUV(vertices, uv);

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

    private static void CreateOctahedron(Vector3[] vertices, int[] triangles, int resolution)
    {
        int v = 0, vBottom = 0, t = 0;

        for (int i = 0; i < 4; i++)
        {
            vertices[v++] = Vector3.down;
        }

        for (int i = 1; i <= resolution; i++)
        {
            float progress = (float)i / resolution;
            Vector3 from, to;
            vertices[v++] = to = Vector3.Lerp(Vector3.down, Vector3.forward, progress);
            for (int d = 0; d < 4; d++)
            {
                from = to;
                to = Vector3.Lerp(Vector3.down, directions[d], progress);
                t = CreateLowerStrip(i, v, vBottom, t, triangles);
                v = CreateVertexLine(from, to, i, v, vertices);
                vBottom += i > 1 ? (i - 1) : 1;
            }
            vBottom = v - 1 - i * 4;
        }

        for (int i = resolution - 1; i >= 1; i--)
        {
            float progress = (float)i / resolution;
            Vector3 from, to;
            vertices[v++] = to = Vector3.Lerp(Vector3.up, Vector3.forward, progress);
            for (int d = 0; d < 4; d++)
            {
                from = to;
                to = Vector3.Lerp(Vector3.up, directions[d], progress);
                t = CreateUpperStrip(i, v, vBottom, t, triangles);
                v = CreateVertexLine(from, to, i, v, vertices);
                vBottom += i + 1;
            }
            vBottom = v - 1 - i * 4;
        }

        for (int i = 0; i < 4; i++)
        {
            triangles[t++] = vBottom;
            triangles[t++] = v;
            triangles[t++] = ++vBottom;
            vertices[v++] = Vector3.up;
        }
    }

    private static int CreateVertexLine(Vector3 from, Vector3 to, int steps, int v, Vector3[] vertices)
    {
        for (int i = 1; i <= steps; i++)
        {
            vertices[v++] = Vector3.Lerp(from, to, (float)i / steps);
        }
        return v;
    }

    private static int CreateLowerStrip(int steps, int vTop, int vBottom, int t, int[] triangles)
    {
        for (int i = 1; i < steps; i++)
        {
            triangles[t++] = vBottom;
            triangles[t++] = vTop - 1;
            triangles[t++] = vTop;

            triangles[t++] = vBottom++;
            triangles[t++] = vTop++;
            triangles[t++] = vBottom;
        }
        triangles[t++] = vBottom;
        triangles[t++] = vTop - 1;
        triangles[t++] = vTop;
        return t;
    }

    private static int CreateUpperStrip(int steps, int vTop, int vBottom, int t, int[] triangles)
    {
        triangles[t++] = vBottom;
        triangles[t++] = vTop - 1;
        triangles[t++] = ++vBottom;
        for (int i = 1; i <= steps; i++)
        {
            triangles[t++] = vTop - 1;
            triangles[t++] = vTop;
            triangles[t++] = vBottom;

            triangles[t++] = vBottom;
            triangles[t++] = vTop++;
            triangles[t++] = ++vBottom;
        }
        return t;
    }


    private static void Normalize(Vector3[] vertices, Vector3[] normals)
    {
        for (int i = 0; i < vertices.Length; i++)
        {
            normals[i] = vertices[i] = vertices[i].normalized;
        }
    }

    private static void CreateUV(Vector3[] vertices, Vector2[] uv)
    {
        float previousX = 1f;
        for (int i = 0; i < vertices.Length; i++)
        {
            Vector3 v = vertices[i];
            if (v.x == previousX)
            {
                uv[i - 1].x = 1f;
            }
            previousX = v.x;
            Vector2 textureCoordinates;
            textureCoordinates.x = Mathf.Atan2(v.x, v.z) / (-2f * Mathf.PI);
            if (textureCoordinates.x < 0f)
            {
                textureCoordinates.x += 1f;
            }
            textureCoordinates.y = Mathf.Asin(v.y) / Mathf.PI + 0.5f;
            uv[i] = textureCoordinates;
        }
        uv[vertices.Length - 4].x = uv[0].x = 0.125f;
        uv[vertices.Length - 3].x = uv[1].x = 0.375f;
        uv[vertices.Length - 2].x = uv[2].x = 0.625f;
        uv[vertices.Length - 1].x = uv[3].x = 0.875f;
    }
}


相關推薦

Unity Mesh() Mesh

之前在    中已經說明了如何畫球,現在我們在這個球的基礎上貼圖。           這裡我們有個極座標和直角座標的轉換,具體我也不是很明白,反正就是拿來用吧,據某位大神講解,極座標(球座標)由球半徑,水平角和垂直角決定,我們完全可以理解為三維座標轉換成uv座標的

unity按鈕新增圖片

1.在Assets\Resources目錄新建的兩個資料夾subjectbtn、subjectbtn_highlight,subjectbtn用於存放各個科目按鈕的預設狀態圖片,subjectbtn_highlight用於存放各個科目按鈕的滑鼠滑過或點選時的狀態

unity標準Shader之十種型別

                                                           十種貼圖型別 介紹:標準 Shader 貼圖 標準 Shader 使用的是 PBR 渲染,基於現實物理效果的渲染表現形式。 一個模型能不能使用標準 Shad

MFC對話方塊視窗使用GDI+按鈕

        最近要做一個有透明效果的按鈕出來,先是大致學了PS教程,製作一個PNG格式的背景透明的按鈕,如圖1所示。然後使用GDI+進行貼圖,最後要達到圖2所示效果。開發環境是VS2010,MFC。 圖1 PS製作的PNG格式按鈕 圖2 效果圖     1、背景填充

Unity技巧】調整畫質()質量

寫在前面 當我們在Unity中,使用圖片進行2D顯示時,會發現顯示出來的畫面有明顯的模糊或者鋸齒,但是美術給的原圖卻十分清晰。 要改善這一狀況實際上很簡單。 造成這樣的原因,是Unity在匯入圖片

Unity 獲得某個物體的主

獲得物體的貼圖 gameObject.getComponent<MeshRenderer>().material.mainTexture; 預設的圖片型別是Texture2D Text

[Unity3d]如何製作unity能使用的RGBA材質

最近在研究ui材質問題時,想借用《魔獸世界》裡的Ui材質貼圖,可惜幾經週轉在網上實在找不到我想要的貼圖,大家是不是也有過這樣的經歷,索性我就嘗試自己用PS做了一個,大牛請忽視題主PS的技能~~ 首先我們先了解一下unity類透明的材質的格式資訊。 可以看

【個人Unity筆記】烘焙光照後保留法線和光探頭

使用的5.34f1版本的unity 有時候為了節省開銷,烘焙光照貼圖是一種很好的辦法,在手機上開發經常會使用到,配合光探頭還可以讓靜態光和非靜態物體產生互動。 首先,把要烘焙的物體全部勾選為靜態(Static)。 然後,把需要烘焙的光的Baking由預

Unity實用小方法】判斷是否為透明

private bool JudgeTransparentPic(TextureFormat format) { //所有貼圖格式帶alpha通道的格式,帶alpha通

Unity Mesh(五) Mesh 立方體Cube以及六個面分別不同的圖片

using UnityEngine; using System.Collections; [RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))] public class Test3D : MonoBehaviour { publi

Unity Mesh(四) Mesh 平面圖形的

前面都講了怎麼畫,沒有寫怎麼貼圖,上一篇提到了法線,今天這篇會說說平面圖形的貼圖。 為了更好的觀察,我們使用這張圖片來進行貼圖(可以右擊儲存): 一、三角形貼圖 三角形的貼圖是最簡單的,因為我們畫的三角形就簡單,直接根據點來選取: 首先說下貼圖的座標系:如下圖

動態載入烘培與Terrain轉mesh

前言 unity載入烘培貼圖是需要載入場景才可以使用,但如果專案只使用一個場景或者有許多關卡地形時,明顯通過載入場景來達到更換烘培貼圖的這種做法是不妥當的。而terrain地形在有些安卓機上的支援並不是很好,所以有必要把地形轉為網格。慶幸的是,網上也有這方面的

Unity Mesh(三) Mesh

關於畫球一開始真是一點思路都沒有,樓主也查了好多資料,比較有代表性的是兩篇帖子。 一篇是Jasper Flick的帖子,一個很厲害的人: 這一篇的思路是根據柏拉圖體,正八面體分割成的球。 第二篇是OpenGL或者XNA回答的思路,是根據柏拉圖體正二十面體畫的

FairyGUI UIPanel看不到顯示UI的Mesh的問題

初學FairyGUI,看例子,FairyGUI在Editor中顯示UI的時候是先選擇Package名,在選擇Component名,然後在場景裡面就可以顯示包裡面的元件,這時就有一個問題,底層到底做了什麼使得UIPanel能夠顯示Mesh和貼圖? 看了Fairy

初識Unity 3D——認識材質

1、Unity中習慣將材質(Material)成為材質球,因為在U3D引擎中材質的預覽方式為一個球體。 2、材質球的組成又分為貼圖(Texture)和著色器(Shader)。 3、貼圖就是普通的圖片。 4、著色器是一種可以精確的控制材質球的工具。 通過貼

Unity Shaders】學習筆記之法線()

 一、簡介   法線貼圖是凸凹貼圖(Bump mapping)的一種常見應用,簡單說就是在不增加模型多邊形數量的前提下,通過渲染暗部和亮部的不同顏色深度,來為原來的貼圖和模型增加視覺細節和真實效果

Unity Shader 法線的實現

計算 變換 float minus include 的確 dal 反射 mode 這裏有一個細節,關於法線貼圖是有兩個不同的空間的,如下:   切線空間:法線貼圖顏色為偏藍色   模型空間:法線貼圖顏色為五顏六色 因此根據不同的空間變換位置方便一致計算。 1 // 法

03 傳遞著色器

tac cti arc port -- angle span com shader WebGL很容易把圖片傳遞給著色器程序當作貼圖。下面是一些需要註意的地方: 1、貼圖圖片長寬像素必須是2的冪,例如16、32、64、128、256,否則貼圖無法顯示。

unity

inf 因此 基礎上 tro 控制 ron lmap 導入 金屬 貼圖的英語 Map 其實包含了另一層含義就是“映射”。其功能就是把紋理通過 UV 坐標映射到3D 物體表面。貼圖包含了除了紋理以外其他很多信息,比方說 UV 坐標、貼圖輸入輸出控制等等。材質是一個數據集,主要

Unity使用腳本進行批量動態加載

它的 有關 技術 post 應該 而且 下一步 AI 屬性。 先描述一下我正在做的這個項目,是跑酷類音遊。 那麽跑酷類音遊在繪制跑道上的時候,就要考慮不同的磚塊顯示問題。假設我有了一個節奏列表,那麽我們怎麽將不同的貼圖貼到不同的磚塊上去呢? 我花了好幾個小時才搞清楚裏面的門