1. 程式人生 > >Unity3D之與根據動態的兩個軌跡點繪製面詳解

Unity3D之與根據動態的兩個軌跡點繪製面詳解

大家應該知道3D世界中任何的面都是由三角形繪製完成的,因為任何無規則的集合圖形都可以由三角形來組成。比如四邊形,無論是正四邊形還是無規則四邊形都可以由兩個三角形拼接而成。結合本文的標題大家仔細想想,如果需要繪製一個動態無規則面其實只需要得到動態的兩個軌跡點即可,那麼結合下面的圖片大家仔細在想想。

Unity3D研究院之與根據動態的兩個軌跡點繪製面詳解(二十) - 雨鬆MOMO程式研究院 - 1

(點選圖片,檢視大圖)

        暫時我們先忽略Z軸(這樣在平面中看得更清楚),假設Z軸座標都為0。假設遊戲中有兩個軌跡點在動態的增加與改變,最後將這兩個點改變的軌跡拼接起來就是它們生成的面。如上圖所示,第一個點的軌跡是“ 3,4,5,6,7” 第二個點的軌跡是“2,1,10,9,8” 。這兩個點的長度是可變的,前提是他們兩個的數量必需完全一樣。接著,如下圖所示,我們將這些點兩兩相連起來,目前一共形成了8個三角形面(可根據兩個動態點的數量而確定整個網格面三角形面的數量)。最後我們將這8個三角形填充上同樣的顏色,就可以實現一個完整的立體網格面。

Unity3D研究院之與根據動態的兩個軌跡點繪製面詳解(二十) - 雨鬆MOMO程式研究院 - 2

(點選圖片,檢視大圖)

         原理很簡單,就是這樣的我相信大家看到這裡大家都能明白,接著我們就學習如何使用程式碼來實現它。首先建立Unity工程,接著建立一個空的遊戲物件,然後給該遊戲物件繫結Mesh Filter元件 與 Mesh Renderer元件。

Mesh Filter元件:表示網格面,這個網格面是由我們使用程式碼將所有三角形拼接起來生成的面。

Mesh Renderer元件:表示表示網格的渲染,可設定一個渲染的材質,它包括貼圖與顏色。

       如下圖所示,我說說裡面比較重要的屬性。Mesh Renderer中,Materials下拉列表中可設定網格模型的材質,此時我們設定了一個紅色的材質。 Mesh Filter:目前為None,也不用再編輯器中為它賦值,因為這個網格模型我們會在程式碼中生成並且賦值。在下面就是方剛我們設定紅色的材質資源,Shader中設定了貼圖的屬性,目前是GUI/ TextShader。它表示這個材質的渲染級別在GUI上,就是優先順序是最一層的。舉個例子無論在這個網格模型的前面繪製多少模型,它永遠都會在最前面顯示。就這個例子而言它的存在並不是必需的,其實Shader的選項還有很多,可透明、不可透明、鏡面、反射等等,後期我會向大家詳細道來。

Unity3D研究院之與根據動態的兩個軌跡點繪製面詳解(二十) - 雨鬆MOMO程式研究院 - 3

 OK,現在資原始檔都已經準備完畢,下面我們學習如何來繪製一個三角形,從簡單的開始。。把下面的程式碼繫結在攝像機物件當中。

using UnityEngine;
using System.Collections.Generic;
using System;
 
public class Test : MonoBehaviour {
 
	void Start ()
	{
		//得到MeshFilter物件,目前是空的。
		MeshFilter meshFilter = (MeshFilter)GameObject.Find("face").GetComponent(typeof(MeshFilter));
		//得到對應的網格物件
		Mesh mesh = meshFilter.mesh;
 
		//三角形頂點的座標陣列
		Vector3[] vertices = new Vector3[3];
		//三角形頂點ID陣列
		int[] triangles   = new int[3];
 
		//三角形三個定點座標,為了顯示清楚忽略Z軸
		vertices[0] = new Vector3(0,0,0);
		vertices[1] = new Vector3(0,1,0);
		vertices[2] = new Vector3(1,0,0);
 
		//三角形繪製頂點的陣列
		triangles[0] =0;
		triangles[1] =1;
		triangles[2] =2;
 
		//註釋1
		mesh.vertices = vertices;
 
		mesh.triangles = triangles;
 
	}
 
}

程式碼中有兩個非常重要的概念,就是三角形頂點陣列與座標陣列。先說說座標陣列,假設需要繪製一個四邊形,此時三角形座標陣列的長度應當是4,它儲存著四邊形四個頂點的座標。然後是頂點陣列,四邊形是由兩個三角形組成,然而一個三角形是由3個頂點組成,兩個三角形就應當是6個頂點組成,無論多少個三角形它們的結構都應當是以此類推。

註解1:這裡是將模型的頂點陣列與座標陣列賦值給網格模型,還記得剛剛在建立Mesh Filter時,當時沒有在編輯器中給網格模型賦值,實際上程式碼走到這裡就會重新為網格模型MeshFilter賦值,接著我們在程式碼中繪製的三角形就會顯示在螢幕當中。

如圖所示,三角形已經繪製在螢幕當中。 圖中陣列 0 1 2 表示該三角形的三個頂點的ID。這個ID對應程式碼中對應vertices陣列索引頂點的座標。

Unity3D研究院之與根據動態的兩個軌跡點繪製面詳解(二十) - 雨鬆MOMO程式研究院 - 4

 下面我們修改一下程式碼,讓螢幕中一共繪製4個三角形。

using UnityEngine;
using System.Collections.Generic;
using System;
 
public class Test : MonoBehaviour {
 
    //網格模型頂點數量
	private int VERTICES_COUNT = 6;
 
	void Start ()
	{
		//得到MeshFilter物件,目前是空的。
		MeshFilter meshFilter = (MeshFilter)GameObject.Find("face").GetComponent(typeof(MeshFilter));
		//得到對應的網格物件
		Mesh mesh = meshFilter.mesh;
 
		//三角形頂點的座標陣列
		Vector3[] vertices = new Vector3[VERTICES_COUNT];
 
		//得到三角形的數量
		int triangles_count = VERTICES_COUNT - 2;
 
		//三角形頂點ID陣列
		int[] triangles   = new int[triangles_count *3];
 
		//三角形三個定點座標,為了顯示清楚忽略Z軸
		vertices[0] = new Vector3(0,0,0);
		vertices[1] = new Vector3(0,1,0);
		vertices[2] = new Vector3(1,0,0);
		vertices[3] = new Vector3(1,1,0);
		vertices[4] = new Vector3(2,0,0);
		vertices[5] = new Vector3(2,1,0);
 
		//三角形繪製頂點的陣列
		triangles[0] =0;
		triangles[1] =1;
		triangles[2] =2;
		triangles[3] =3;
		triangles[4] =2;
		triangles[5] =1;
 
		triangles[6] =2;
		triangles[7] =3;
		triangles[8] =4;
 
		triangles[9] =5;
		triangles[10] =4;
		triangles[11] =3;
 
     	//繪製三角形
		mesh.vertices = vertices;
 
		mesh.triangles = triangles;
 
	}
 
}

已知模型的頂點數量,頂點數量減去2就是三角形的數量,三角形的數量在乘以3就是三角形頂點的數量。根據這個公式計算得知,上述程式碼中共繪製4個三角形,頂點座標陣列應當是6,頂點ID陣列應當是12。多個三角形在頂點ID陣列中排列方式比較特殊,大家需要仔細記錄一下不然無法繪製出正確的三角形。如下圖所示,由於我這邊沒有合適的3D座標點,就用正三角形拼接出一個正四邊形,這個四邊形是由6個頂點4個小三角形組成 ,看到這裡思路清晰的朋友應當明瞭無規則四邊形的繪製原理和它完全一樣。只需要傳入適當的3D座標點即可。

Unity3D研究院之與根據動態的兩個軌跡點繪製面詳解(二十) - 雨鬆MOMO程式研究院 - 5

          根據上面的邏輯,我們修改一下演算法。假設三角形的頂點座標為任意數量,我們需要更根據頂點座標數量來計算對應頂點ID的陣列內容。在for迴圈中start =0 與end =3的含義是繪製從頂點座標陣列中索引為0的頂點開始繪製到陣列索引為3的頂點,也就說是這裡從0到3繪製了3個三角形。

using UnityEngine;
using System.Collections.Generic;
using System;
public class Test : MonoBehaviour {
    //網格模型頂點數量
	private int VERTICES_COUNT = 6;
	void Start ()
	{
		//得到MeshFilter物件,目前是空的。
		MeshFilter meshFilter = (MeshFilter)GameObject.Find("face").GetComponent(typeof(MeshFilter));
		//得到對應的網格物件
		Mesh mesh = meshFilter.mesh;
		//三角形頂點的座標陣列
		Vector3[] vertices = new Vector3[VERTICES_COUNT];
		//得到三角形的數量
		int triangles_count = VERTICES_COUNT - 2;
		//三角形頂點ID陣列
		int[] triangles   = new int[triangles_count *3];
		//三角形三個定點座標,為了顯示清楚忽略Z軸
		vertices[0] = new Vector3(0,0,0);
		vertices[1] = new Vector3(0,1,0);
		vertices[2] = new Vector3(1,0,0);
		vertices[3] = new Vector3(1,1,0);
		vertices[4] = new Vector3(2,0,0);
		vertices[5] = new Vector3(2,1,0);
     	//繪製三角形
		mesh.vertices = vertices;
		//起始三角形頂點
		int start = 0;
		//結束三角形的頂點
		int end = 3;
		for(int i = start; i <end; i++)
		{
			for(int j = 0; j < 3; j++)
			{
				if( i%2 ==0)
				{
					triangles[3*i + j] = i +j;
				}else
				{
					triangles[3*i + j] = i + 2-j;
				}
 
			}
		}
		mesh.triangles = triangles;
	}
}

如下圖所示,根據上面的邏輯演算法,共繪製了3個三角形,並且頂點座標ID是由 0 到3 。 說到這裡請大家仔細想想本文的標題內容,其實兩個動態軌跡的點就是在維護triangles頂點座標陣列。triangles[0]、triangles[2]、triangles[4]……表示一個軌跡點的值,triangles[1]、triangles[3]、triangles[5]……就表示另一個軌跡點的值,最終將它們通過上面的演算法將三角形面連線起來那麼就是動態的兩個點軌跡繪製面了。

Unity3D研究院之與根據動態的兩個軌跡點繪製面詳解(二十) - 雨鬆MOMO程式研究院 - 6


相關推薦

Unity3D根據動態軌跡繪製

大家應該知道3D世界中任何的面都是由三角形繪製完成的,因為任何無規則的集合圖形都可以由三角形來組成。比如四邊形,無論是正四邊形還是無規則四邊形都可以由兩個三角形拼接而成。結合本文的標題大家仔細想想,如果需要繪製一個動態無規則面其實只需要得到動態的兩個軌跡點即可,那麼結合

棧實現佇列,用棧實現佇列方法(含實現程式碼)

棧怎樣才能實現和佇列一樣從棧的底層抽出元素呢?一般會用兩個棧來實現佇列。 首先,我們將兩個棧分別定義為 stack1 與 stack2。 實現方案 1 我們讓入隊操作在 stack1 中執行,而出隊操作在 stack2 中執行。執行方式如下。 入隊:直接向 stack1 中入棧。 出隊:將 stac

如何使用指標形參交換整數的值(

函式內部通過解引用操作改變指標所指的內容 程式碼塊 #include <iostream> using namespace std; int swap(int *a,int *b); int main() { int *p,*q;

深入N皇后問題的最高效演算法的

N皇后問題是一個經典的問題,在一個N*N的棋盤上放置N個皇后,每行一個並使其不能互相攻擊(同一行、同一列、同一斜線上的皇后都會自動攻擊)。一、 求解N皇后問題是演算法中回溯法應用的一個經典案例回溯演算法也叫試探法,它是一種系統地搜尋問題的解的方法。回溯演算法的基本思想是:從

深入N皇后問題的最高效演算法的[裝載]

[原地址:http://www.jb51.net/article/37318.htm] N皇后問題是一個經典的問題,在一個N*N的棋盤上放置N個皇后,每行一個並使其不能互相攻擊(同一行、同一列、同一斜線上的皇后都會自動攻擊)。 一、 求解N皇后問題是演算

mac安全隱私只有選項,少了一個任何來源

span 軟件 style 出現 pos 全選 nbsp font 終端 mac安裝軟件時如彈出程序已損壞,請移到廢紙簍的提示。 解決方法:在終端裏輸入: sudo spctl --master-disable 然後回車,然後輸入密碼,即可在安全選項中看到

pythonpygal:擲不同的骰子並統計大小出現次數

range 截圖 pan lis label 一個 出現 pen des 代碼示例: 1 # 擲兩個不同的骰子並統計大小出現次數 2 import pygal 3 from die_class import Die 4 5 die = Die(6) # 實例

求過圓心直線圓的交點

主要是注意所使用的資料型別。 之前用的是float,出現了一些意外,而且花費了我不少時間來反覆驗證、推導, 做了很多的無用功,而且,反覆推導得出來的計算步驟並沒有什麼不牢靠的地方。 然後計算得到的結果卻是讓人如此之不省心,梗的我悶得慌。 今天上午發來了一貼,多位朋友各抒己見, 總

joda.time如何獲取到時間的差值(正確的使用Period類)

前言 此前Java處理時間日期所使用的 Date 和 Calendar 被詬病不已,Calendar 的主要問題物件可變,而像時間和日期這樣的類應該是不可變的,另外其概念模型也有不明確的地方,月份計算從0開始等等。 JodaTime開源時間/日期庫是很好的替代,另外Java8中也推出了新的java.tim

使用Pangolon在同一副圖中,畫出軌跡,比較誤差

轉載:https://www.cnblogs.com/feifanrensheng/p/8628900.html 使用 code/ground-truth.txt 和 code/estimate.txt 兩條軌跡。請你根據上面公式,實現 RMSE 的計算程式碼,給出最後的 RMSE 結果。作為驗

Shell程式設計if簡單判斷數字大小

#指令碼編輯   #!/bin/bash #定義變數 num1=$1 num2=$2   #判斷是否輸入兩個引數,若是,將兩個引數傳遞給下一個指令動作,若非兩個引數,則列印輸出內容輸出並且退出exit指令碼不執行下一個指令 if [ $# -ne

iOS開發技巧:iOS判斷陣列中資料是否相同

IOS開發之判斷兩個陣列中資料是否相同例項詳解 前言: 工作中遇到的問題,這裡記錄下,也許能幫助到大家 例項程式碼: ? 1

CUDA學習(三)使用GPU進行陣列相加

 傳入兩個陣列,在GPU中將兩個陣列對應索引位置相加 #include "cuda_runtime.h" #include "device_launch_parameters.h" #include <iomanip> #include <iostream> #in

一次掌握 React React Native 框架

此係列文章將整合我的 React 視訊教程與 React Native 書籍中的精華部分,給大家介紹 React 與 React Native 結合學習的方法。 1. 軟體開發語言與框架的學習本質 我們在開始系列文章的技術點內容前,花一點時間探討一下軟體開發語言以及框架的學習本質,相對於整個技術點的講解,花這

《程式設計珠璣》程式碼路14:不會演算法也能把效率提升4倍的小套路

現在我們假設要在沒排序的陣列中找一個數: 菜狗也能寫出如下的演算法1: 找到了我就返回位置,否則我就返回-1。 int search1(){ for (int i = 0; i < MAXN; ++i){ if (nums[i] == VALUE){ return i;

Echarts圖表座標軸動態展示時間之間的時間

Echarts圖表座標軸動態展示兩個時間點之間的時間 初始折線圖樣式 以下是配置項設定: option = { xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', '

PAT Basic1054(unsolved:測試沒過,其實只有一步遙)

1054 求平均值 (20)(20 分)本題的基本要求非常簡單:給定N個實數,計算它們的平均值。但複雜的是有些輸入資料可能是非法的。一個“合法”的輸入是[-1000,1000]區間內的實數,並且最多精確到小數點後2位。當你計算平均值的時候,不能把那些非法的資料算在內。輸入格式

fragmentactivity及fragment之間的跳轉實現

在近期的練手專案中,我們使用到了Android Fragment技術。在應用的互動中,我可能需要實現: 從當前的fragment跳轉到另一個fragment從當前的fragment跳轉到一個activity中從當前的activity跳轉到一個fragment中 網上提供的

LeetCode刷題三:判斷二叉樹是否相同

題目為: Given two binary trees, write a function to check if they are equal or not. Two binary trees are considered equal if they are str

關於C#中的StreamReaderFileStream這

成員函式1. Peek() Returns the next available character but does not consume it. 2. Read() Reads the next character from the input stream and advances the chara