首先我要承認(rèn)下我不是很清楚如何講解這個讓它看起來更容易理解,但是,不管怎么樣,我想盡力嘗試下。首先,我想介紹下什么叫做“單位圓”。你如果還記得高中數(shù)學(xué)中一個圓又一個半徑。半徑指的是從圓心到圓的圓邊的距離。單位圓指的是它的半徑是 1.0。
如鏈接里有一個單位圓:
打開上面的鏈接之后,你可以拖動頁面內(nèi)圓環(huán)上面的小圓,接著 X 和 Y 的值也會隨之發(fā)生變化。這個左邊值表示的是圓環(huán)上的點。在圓上的最高點處,Y 為 1 和 X 為 0。在最右的位置時 X 為 1 和 Y 為 0。
如果你還記得基礎(chǔ)的三年級數(shù)學(xué),把某個數(shù)乘以 1 以后結(jié)果仍然是該數(shù)。那么 123*1 = 123。相當(dāng)基礎(chǔ)對吧?那么半徑為 1.0 的單位圓也是一種形式的 1。它是一種旋轉(zhuǎn)的 1。因此你可以將這個單位圓與某物相乘,它執(zhí)行的操作和乘以 1 類似,除了一些奇異的事情發(fā)生改變這種方式。
我們將從單位圓上得到任何點的 X 和 Y 值,接著將他們乘以上一節(jié)示例中的幾何圖形。
如下是更新渲染器:
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;
uniform vec2 u_resolution;
uniform vec2 u_translation;
uniform vec2 u_rotation;
void main() {
// Rotate the position
vec2 rotatedPosition = vec2(
a_position.x * u_rotation.y + a_position.y * u_rotation.x,
a_position.y * u_rotation.y - a_position.x * u_rotation.x);
// Add in the translation.
vec2 position = rotatedPosition + u_translation;
接著修改 JavaScript 代碼,這樣我們就可以傳遞上面的兩個參數(shù):
...
var rotationLocation = gl.getUniformLocation(program, "u_rotation");
...
var rotation = [0, 1];
..
// Draw the scene.
function drawScene() {
// Clear the canvas.
gl.clear(gl.COLOR_BUFFER_BIT);
// Set the translation.
gl.uniform2fv(translationLocation, translation);
// Set the rotation.
gl.uniform2fv(rotationLocation, rotation);
// Draw the rectangle.
gl.drawArrays(gl.TRIANGLES, 0, 18);
}
如下是代碼運行的結(jié)果。拖動單位圓上的小環(huán)使圖形進行旋轉(zhuǎn)或者拖動滑動條使圖形進行移動。
為什么上面的代碼能夠起作用?首先,讓我們看下數(shù)學(xué)公式:
rotatedX = a_position.x * u_rotation.y + a_position.y * u_rotation.x;
rotatedY = a_position.y * u_rotation.y - a_position.x * u_rotation.x;
假設(shè)你有一個矩形,并且你想旋轉(zhuǎn)它。在你把它旋轉(zhuǎn)到右上角 (3.0,9.0) 這個位置之前。我們先在單位圓中選擇一個從 12 點鐘的位置順時針偏移 30 度的點。
在圓上那個位置的點的坐標(biāo)為 0.50 和 0.87:
3.0 * 0.87 + 9.0 * 0.50 = 7.1
9.0 * 0.87 - 3.0 * 0.50 = 6.3
那剛剛好是我們需要的位置:
旋轉(zhuǎn) 60 度和上面的操作一樣:
圓上面的位置的坐標(biāo)是 0.87 和 0.50:
3.0 * 0.50 + 9.0 * 0.87 = 9.3
9.0 * 0.50 - 3.0 * 0.87 = 1.9
你可以發(fā)現(xiàn)當(dāng)我們順時針向右旋轉(zhuǎn)那個點時,X 的值變得更大而 Y 的值在變小。如果接著旋轉(zhuǎn)超過 90 度,X 的值將再次變小而 Y 的值將變得更大。這個形式就能夠達到旋轉(zhuǎn)的目的。
圓環(huán)上的那些點還有另外一個名稱。他們被稱作為 sine 和 cosine。因此,對任意給定的角度,我們就只需查詢它所對應(yīng)的 sine 和 cosine 值:
function printSineAndCosineForAnyAngle(angleInDegrees) {
var angleInRadians = angleInDegrees * Math.PI / 180;
var s = Math.sin(angleInRadians);
var c = Math.cos(angleInRadians);
console.log("s = " + s + " c = " + c);
}
如果你把上面的代碼復(fù)制粘貼到 JavaScript 控制臺中,接著輸入 printSineAndCosineForAnyAngle(30)
,接著你會看到輸出 s = 0.49 c = 0.87
(注意:這個數(shù)字是近似值。)
如果你把上面的代碼整合在一起的話,你就可以將你的幾何體按照你想要的任何角度進行旋轉(zhuǎn)。僅僅只需要將你需要旋轉(zhuǎn)的角度值傳給 sine 和 cosine 就可以了。
...
var angleInRadians = angleInDegrees * Math.PI / 180;
rotation[0] = Math.sin(angleInRadians);
rotation[1] = Math.cos(angleInRadians);
如下是設(shè)置一個角度旋轉(zhuǎn)的版本。拖動滑動條旋轉(zhuǎn)或者移動。
更多建議: