pos機如何選擇sn,向量數(shù)學(xué)在游戲中如何使用

 新聞資訊  |   2023-04-23 13:38  |  投稿人:pos機之家

網(wǎng)上有很多關(guān)于pos機如何選擇sn,向量數(shù)學(xué)在游戲中如何使用的知識,也有很多人為大家解答關(guān)于pos機如何選擇sn的問題,今天pos機之家(www.afbey.com)為大家整理了關(guān)于這方面的知識,讓我們一起來看下吧!

本文目錄一覽:

1、pos機如何選擇sn

pos機如何選擇sn

對于一個初學(xué)者來說,三維空間的幾何似乎有點讓人望而生畏。在紙上可以畫出來的二維空間幾何就已經(jīng)足夠難以理解了,但是現(xiàn)在我們竟然要使用和掌握三維空間的幾何?

好消息是在圖形學(xué)中直接使用三角形是非常罕見的并且有很多方法可以用來避免這么做。我們有其他更好理解和使用的工具來代替。你可能在下圖中已經(jīng)認(rèn)出我們的老朋友-向量(vector)。

這篇文章將向你介紹三維空間的向量,并將用幾個實際使用方面的例子來帶你熟悉三維空間的向量。雖然這些例子的內(nèi)容是側(cè)重三維空間的,但是里面說明的大部分內(nèi)容和原理也同樣適用于二維空間。

這篇文章會假設(shè)讀者具有代碼和幾何方面的知識,以及具有編程方面的經(jīng)驗和對面向?qū)ο缶幊?OOP)的基本了解。

游戲中的向量數(shù)學(xué)

概念

在數(shù)學(xué)中,一個向量是指一個既有方向(direction)又有大小(magnitue)的結(jié)構(gòu)。在游戲開發(fā)中它經(jīng)常用來描述位置的變化,并且可以與其他向量相加或者相減來得到新的位置變化(一個向量代表一個位置的變化,兩個這樣的向量相加得到的是這兩段位置變化的總效果)。通常情況下,你會發(fā)現(xiàn)向量是數(shù)學(xué)庫或者物理庫的一部分。

它們通常包含一個或多個組件,比如x、y和z。向量可以是一維向量(只包含x分量)、二維向量(包含x、y分量)、三維向量(包含x、y、z分量)甚至是四維向量(一般是x、y、z、w分量)。四維向量可以用來描述其他一些東西,比如一個帶額外alpha值的顏色。

對于初學(xué)者來說最困難的事情之一就是他們在剛接觸向量的時候如何去理解看上去就是空間的一個點的東西為什么可以用來描述一個方向。

讓我們用二維向量(3,3)來舉例說明這個事情。要理解為什么向量能夠代表一個方向你只需要看下面這張圖。我們都知道需要兩個點才能形成一條線。所以第二個點在哪里呢?缺失的那個點就是位于(0,0)的原點(origin)。我們畫一條從原點(0,0)到(3,3)的線段,我們就得到下圖這么一個效果:

正如你在上圖中看到的那樣,原點作為第二個點引入以后就與第一個點一起賦予了我們的向量一個方向。但是你也會看到,第一個點(3,3)可以被移動(或者說位移)來接近或者遠(yuǎn)離原點。

第一個點到原點的距離就被稱為大小,可以用二次方程a^2 + b^2 = c^2計算得到。在我們舉得例子中,就是3^2 + 3^2 =c^2, c = sqrt(18) ~= 4.24。如果我們把向量的每個分量除以4.24那么我們就把向量放縮成了大小正好為1(也就是到原點的距離為1)的向量。在接下來的例子中我們將看到為什么這個被稱為向量歸一化的過程非常有用,向量的歸一化保留了向量的方向,但是提供了通過對數(shù)字(也就是標(biāo)量)值進(jìn)行乘法來放縮大小的能力。

在接下來的例子中,我將假設(shè)你的數(shù)學(xué)庫用Vector2 代指二維向量,用Vector3代指三維向量。它們在不同的庫和編程語言中有各種不同的名字,舉個例子來說,vector、vector3、 Vector3f、 vec3、 point、 point3f等等都是向量的名字。你的數(shù)學(xué)庫中關(guān)于向量部分肯定有很多文檔和例子。

注意:向量類型在編程語言的世界里面通常有兩種含義,既可以用來指傳統(tǒng)的數(shù)學(xué)/物理場景中的向量,也可以用來表示自行控制的n維單位。這里僅僅是做一個小提醒。

像其他變量一樣,你代碼中的向量到底代表著什么含義完全取決于你的控制:它可以是一個位置、方向或者速度。下面是游戲中常見的一些向量用法

位置 - 向量代表著真實位置與你的世界坐標(biāo)原點(0, 0, 0)的一個偏移量。

方向 - 向量看起來非常像是一個箭頭指著某個方向。它確實是可以這么用。舉個例子來說,如果你有一個指向南的向量,那么你可以把這個向量賦予你的所有單位作為它們的新方向,那么它們都將面向南。

方向向量的一個特例是長度為1的向量。它也被稱為歸一化的向量或者簡稱為標(biāo)準(zhǔn)向量。

一個速度(velocity )向量可以描述一個運動。在這種情況下,它描述的是特定時間內(nèi)的位置的變化。

記住最基本的內(nèi)容-向量加法和減法

向量加法是用來累加兩個向量所描述的不同,并寫入最后的向量中。

比如說,一個物體移動了A向量這么大的位移,然后又移動了B向量這么大的位移,那么結(jié)果就仿佛是它一共移動了C向量這么大的位移(其中C = A + B)。

對于向量減法來說,就相當(dāng)于把第二個向量反轉(zhuǎn),然后把反轉(zhuǎn)的向量加到第一個向量身上。

注意:坐標(biāo)系解向量加減法:在直角坐標(biāo)系里面,定義原點為向量的起點.兩個向量和與差的坐標(biāo)分別等于這兩個向量相應(yīng)坐標(biāo)的和與差若向量的表示為(x,y)形式,A(X1,Y1) B(X2,Y2),則A+B=(X1+X2,Y1+Y2),A-B=(X1-X2,Y1-Y2)

簡單地講:向量的加減就是向量對應(yīng)分量的加減。類似于物理的正交分解。

例子: 物體之間的距離

如果在這個例子中,向量代表的分別是物體A和B的位置,那么 B – A將是代表著A和B物體位置差的向量。 B – A所得到的結(jié)果將表示A位置移動到B位置所需的方向和距離。

舉個例子來說,要得到人到樹的距離向量你必須用樹的位置減去人的位置,如下圖所示:

我用了偽代碼(pseudo-code )來保持代碼的簡潔方便閱讀。在括號內(nèi)的三個數(shù)字(x,y,z)代表著一個向量。:

注意:偽代碼是一種算法描述語言。使用偽碼的目的是使被描述的算法可以容易地以任何一種編程語言(Pascal,C,Java等)實現(xiàn)。因此,偽代碼必須結(jié)構(gòu)清晰、代碼簡單、可讀性好,并且類似自然語言。介于自然語言與編程語言之間。以編程語言的書寫形式指明算法職能。使用偽代碼, 不用拘泥于具體實現(xiàn)。相比程序語言(例如Java,C++,C, Dephi 等等)它更類似自然語言:

tree_position = (10, 10, 0)

my_position = (3, 3, 0)

# distance anddirection you would need to move

# to getexactly where the tree is

vector_to_tree = tree_position - my_position

例子: 速度

除了位置向量以外,對象可能還有一個向量用來表示速度。

舉個例子來說,大炮炮彈的速度向量描述的是它下一秒將要移動的距離。

當(dāng)?shù)谝淮伪话l(fā)射的時候,大炮炮彈可能具有如下這些屬性:

position = (0, 10, 10) # position: 10units in Y and Z direction

velocity = (500, 0, 0) # initialmovement is 500 units in X direction over the next second

每秒鐘要基于速度向量來更新一次炮彈的位置:

position += velocity # add velocityto position and update position

概念: 仿真

等等!我們不希望每一秒才更新一次物體。事實上,我們希望盡可能的頻繁更新物體的信息。

但是我們不能指望兩次更新之間的時間總是固定的。所以我們使用了delta時間,這是上一次更新到這一次更新的時間差。

因為delta時間代表的是逝去時間的一個時間差。所以我們可以用它來得到這次更新到上一次更新之間的這段時間內(nèi)物體的移動速度所導(dǎo)致的位置差。

position += velocity * delta

這是一個非?;镜姆抡?。為了實現(xiàn)一個仿真,我們在自己的世界里面建模了我們的對象該具有怎樣的行為(比如說大炮炮彈永遠(yuǎn)具有不變的速度)。然后我們加載最初的游戲狀態(tài)(大炮炮彈開始的時候具有初始位置和速度)。

最后一塊拼圖是要把所有的東西融合在一起,這就是update循環(huán),它會定期執(zhí)行,我們用delta時間(也就是時間間隔)來記錄上一次更新到這次更新的時間間隔。在每次update調(diào)用的時候,它會根據(jù)我們預(yù)先定義好的規(guī)則(比如說用炮彈的速度來更新炮彈的位置)來對每個仿真物體進(jìn)行更新。

例子:重力、空氣阻力和風(fēng)

我們的炮彈移動是很無聊的:它永遠(yuǎn)是向一個方向移動并且移動的速度永遠(yuǎn)是不變的。我們需要它對周圍的世界做出反應(yīng)。舉個例子來說,我們希望重力能讓炮彈下落,希望空氣阻力會讓炮彈的速度變慢,至于風(fēng)呢,僅僅是加進(jìn)來為了好玩。

在一個游戲中重力實際上意味著什么呢?嗯,它會產(chǎn)生一個副作用,在物體向下的方向增加物體的速度。因為在我們的例子中Y軸是向上的,所以我們的重力向量將是下面這樣的:

# increasevelocity of every object -2 down per second

gravity_vector = (0, -2, 0)

所以,在每次進(jìn)行update調(diào)用之前,我們可以修改速度變量,如下面代碼所示:

velocity += gravity_vector * delta # applygravity effect

position += velocity * delta # updateposition

讓我們假設(shè)空氣很厚,所以空氣會每半秒就降低一次炮彈的速度。

velocity += gravity_vector * delta # applygravity effect

velocity *= 0.5 * delta # apply 0.5slowdown per second

position += velocity * delta # updateposition

速度會受到空氣阻力的影響因為炮彈總是在空氣中行進(jìn)。空氣會阻擋它的前進(jìn)進(jìn)而減少它的動能。所以我們需要調(diào)整下炮彈在空氣中前進(jìn)的速度。

但是,還有一個恒定的力會改變炮彈的運動,就像風(fēng)一樣。

# modifykinetic energy / velocity

# add all forces

final_change_per_second = velocity + wind_force_per_second

# updateposition

position += final_change_per_second * delta

這個例子的著眼點在于說明用簡單的向量數(shù)學(xué)構(gòu)建如此復(fù)雜的一個行為是多么的容易。

概念: 方向

通常情況下,你不會需要從A到B的距離,而是需要從A指向B的方向。向量A到向量B的距離當(dāng)然可以用來表示方向,但是如果你需要從A向B移動“很小一點點”,但是要精確的按照你希望的速度該怎樣做呢?

在這種情況下向量長度應(yīng)該無關(guān)緊要的,如果我們把方向向量的長度縮減為1,就可以用于這個目的以及其他一些情況。我們把這個縮減稱為歸一化(normalization ),得到的向量稱為標(biāo)準(zhǔn)向量(normalvector)。

所以,一個標(biāo)準(zhǔn)向量它的長度應(yīng)該總是1,否則它就不是一個標(biāo)準(zhǔn)向量。。

一個標(biāo)準(zhǔn)向量代表的是一個角度,而沒有實際位置移動相關(guān)的其他任何信息。如果我們用一個標(biāo)量數(shù)字乘以一個標(biāo)準(zhǔn)向量,我們就得到了一個方向向量,同時它的長度就是標(biāo)量數(shù)字的大小。

在你的數(shù)學(xué)庫里面應(yīng)該有一個normalize函數(shù),來從任意的向量中得到一個標(biāo)準(zhǔn)向量。

所以如果要朝B精確的移動3個單位長度,代碼如下:

final_change = (B - A).normalize * 3

概念:平面

一個標(biāo)準(zhǔn)向量也可以用來描述一個平面所朝向的方向。你可以把平面想象成從一個特定點P出發(fā)的無限大的片,對這個片的旋轉(zhuǎn)可以通過法向量N來精確描述出來。

要旋轉(zhuǎn)這個片/平面,你應(yīng)該改變它的法向量。

注意:法向量是空間解析幾何的一個概念,垂直于平面的直線所表示的向量為該平面的法向量。由于空間內(nèi)有無數(shù)個直線垂直于已知平面,因此一個平面都存在無數(shù)個法向量(包括兩個單位法向量)。如果一個非零向量n與平面a垂直,則稱向量n為平面a的法向量。垂直于平面的直線所表示的向量為該平面的法向量。每一個平面存在無數(shù)個法向量。

概念: 點積(Dot Product)

點積是對兩個向量進(jìn)行操作然后返回一個數(shù)字。你可以把返回的這個數(shù)字看作是兩個向量比較的一個方法。

注意:在數(shù)學(xué)中,點積(dot product; scalar product,也稱為數(shù)量積)是接受在實數(shù)R上的兩個向量并返回一個實數(shù)值標(biāo)量的二元運算。它是歐幾里得空間的標(biāo)準(zhǔn)內(nèi)積。

通常寫為:

result = A dot B

兩個法向量之間的這種比較是特別有用的,因為這個數(shù)字會代表著他們在旋轉(zhuǎn)上的不同。

如果點積返回的結(jié)果為1,說明這兩個法向量指向同一個方向。

如果點積返回的結(jié)果為0,說明這兩個法向量互相垂直。

如果點積返回的結(jié)果為-1,說明這兩個法向量指向完全相反的方向。

下面這張圖說明的是點積返回的結(jié)果與兩個向量之間夾角的關(guān)系:

請注意上圖中從1到0以及從0到-1的變化不是線性的,而是遵循余弦曲線進(jìn)行變化的。所以,要從點積的結(jié)果中得到一個角度,你需要對返回的結(jié)果調(diào)用反余弦,如下面代碼所示:

angle = acos(A dot B)

例子: 光照

試想一下我們正在寫一個光照著色器并且我們需要計算一個特定表面點的像素明亮度。我們有如下這些信息:

一個法向量用來表示這個點上的表面的方向

光源的位置

這個表面點的位置

我們可以得到計算特定點到光源的距離向量:

distance_vec = light_pos - point_pos

以及把這個特定點上的光照方向變?yōu)橐粋€標(biāo)準(zhǔn)向量:

light_direction = distance_vec.normalize

然后基于我們已有的關(guān)于角度和點積(dot product)之間關(guān)系的知識,我們可以使用表面法向量和光照方向之間的點積來計算這個點的明亮度。在最簡單的情況下,它就完全等于點積得到的結(jié)果!

brightness = surface_normaldot light_direction

不管你是否相信,這就是一個簡單的光照著色器的基本框架。OpenGL中的實際片段著色器代碼就是這樣的(如果你沒有著色器的相關(guān)知識也不用擔(dān)心,這只是一個用來說明點積實際應(yīng)用的例子,我們不會在著色器方面展開太多):

注意:Shader(著色器)是用來實現(xiàn)圖像渲染的用來替代固定渲染管線的可編輯程序。Shader分為Vertex Shader(頂點著色器)和Pixel Shader(像素著色器兩種((注:兩種著色器在不同的實現(xiàn)中略有不同)。其中Vertex Shader主要負(fù)責(zé)頂點的幾何關(guān)系等的運算,Pixel Shader主要負(fù)責(zé)片源顏色等的計算。

著色器替代了傳統(tǒng)的固定渲染管線,可以實現(xiàn)3D圖形學(xué)計算中的相關(guān)計算,由于其可編輯性,可以實現(xiàn)各種各樣的圖像效果而不用受顯卡的固定渲染管線限制。這極大的提高了圖像的畫質(zhì)。

varying vec3surface_normal;

varying vec3vertex_to_light_vector;

void main(void)

{

vec4diffuse_color = vec3(1.0, 1.0, 1.0); // the color of surface - white

float diffuse_term = dot(surface_normal, normalize(vertex_to_light_vector));

gl_FragColor = diffuse_color * diffuse_term;

}

注意dot函數(shù)和normalize函數(shù)的使用用法是與前一個例子唯一有區(qū)別的地方。

例子:點到一個平面的距離

如果要得到某個點到一個平面的最短距離,首先計算出這個點到平面上任意一點的距離向量,不要對這個向量進(jìn)行歸一化,然后將其與平面的法向量相乘,得到的就是這個點到這個平面的最短距離。

distance_to_a_plane = (point - plane_point) dotplane_normal;

例子:這個點是否在這個平面上?

利用上一個例子的內(nèi)容,計算這個點到這個平面的最短距離,如果等于0,那么這個點就在這個平面上。

例子:一個向量是否與一個平面平行?

如果這個向量與平面的法向量垂直的話,那么這個向量就是與這個平面平行的。

我們已經(jīng)知道,如果兩個向量的點積等于0的時候這兩個向量是垂直的。

所以當(dāng)向量與平面法向量的點積等于0的時候,那么這個向量就是與這個平面平行的。

例子:線段是否與一個平面相交

讓我們假設(shè)下,線段從P1點開始到P2點結(jié)束。在平面上的一個特定點是SP而平面的法向量是SN。

如果我們假想一個平面穿過線段的第一個點P1,那么要解決這個問題就可以轉(zhuǎn)換為計算哪個點(P2還是SP)既更接近P1又與SN更加平行。這個值可以通過點積計算得到,如下所示:

dot1 = SN dot (SP - P1)

dot2 = SN dot (P2 - P1)

你可以計算它與平面相交的”程度“,也就是將這兩個值相比較(相除)。

u = (SN dot (SP - P1)) / (SN dot (P2 - P1))

如果 u == 0,那么線段是與平面平行的。

如果 u <= 1 并且 u > 0, 那么線段與平面相交。

如果u > 1,那么線段與平面不相交。

可以將線段的向量與u相乘得到精確的相交點:

intersectionpoint = (P2 - P1) * u

概念: 向量積(Cross Product)

向量積也是對兩個向量的一個操作。結(jié)果是一個新的向量,它與前兩個向量垂直,并且它長度是前兩個向量長度的均值。

注意:向量積,數(shù)學(xué)中又稱外積、叉積,物理中稱矢積、叉乘,是一種在向量空間中向量的二元運算。與點積不同,它的運算結(jié)果是一個向量而不是一個標(biāo)量。并且兩個向量的叉積與這兩個向量的和垂直。

兩個向量a和b的叉積寫作a×b(有時也被寫成a∧b,避免和字母x混淆)。

向量積可以被定義為:|向量a×向量b|=|a||b|sinθ在這里θ表示兩向量之間的夾角(共起點的前提下)(0° ≤ θ ≤ 180°),它位于這兩個矢量所定義的平面上。

需要注意的是對于向量積操作來說,參數(shù)的順序是有影響的,如果調(diào)換了參數(shù)的順序,生成的結(jié)果向量長度不變,但是方向?qū)耆喾础?/p>

例子: 碰撞

假設(shè)物體以某個角度往墻那里移動。但是墻是無摩擦的,所以物體應(yīng)該沿著墻的表面移動而不是停下來。在這種情況下,如何計算物體的新位置?

首先,我們用一個向量來表示如果沒有墻的情況下物體應(yīng)該移動的距離。我們將稱它為“變化向量“。然后,我們將假設(shè)物體觸碰到了墻。并且我們還需要墻表面的法向量。

我們將使用向量積來得到一個新的向量,它與”變化向量“和平面法向量相垂直:

temp_vector = change crossplane_normal

然后,最后的方向是與新的向量以及之前的平面法向量相垂直的:

new_direction = temp_vectorcross plane_normal

所以,就如下面代碼這樣得到最后的結(jié)果:

new_direction = (change crossplane_normal) cross plane_normal

現(xiàn)在該怎么辦?

通過這篇文章,我希望能彌補向量數(shù)學(xué)的理論和在游戲開發(fā)中實際應(yīng)用之間的鴻溝。但是,這也意味著我在講解的過程中跳過了大量的東西。

但是我希望在閱讀完這篇文章以后,你對向量數(shù)學(xué)的整體框架更加清楚一點。文中對向量數(shù)學(xué)的遍歷可以視為游戲開發(fā)中使用向量數(shù)學(xué)的一個概述。

以上就是關(guān)于pos機如何選擇sn,向量數(shù)學(xué)在游戲中如何使用的知識,后面我們會繼續(xù)為大家整理關(guān)于pos機如何選擇sn的知識,希望能夠幫助到大家!

轉(zhuǎn)發(fā)請帶上網(wǎng)址:http://www.afbey.com/news/31567.html

你可能會喜歡:

版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn),該文觀點僅代表作者本人。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請發(fā)送郵件至 babsan@163.com 舉報,一經(jīng)查實,本站將立刻刪除。