最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Three.js中矩陣和向量的使用教程

 更新時(shí)間:2019年03月19日 11:38:25   作者:斷橋百曉生  
這篇文章主要給大家介紹了關(guān)于Three.js中矩陣和向量使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Three.js具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

前言

提起矩陣,很容易讓人想起我們曾經(jīng)學(xué)不會的線性代數(shù)和離散數(shù)學(xué),但是作為圖形開發(fā)中的核心部分,它代表著每一次的運(yùn)動和變換,就像魚不能脫離水一樣,矩陣并不是一個(gè)可以避之不談的話題。

好消息是,Three.js幫助我們把許多矩陣運(yùn)算封裝成了一些頂層的方法,并提供了一個(gè)優(yōu)秀的數(shù)學(xué)庫,我們不太需要知道HowToCalc,只需要知道HowToUse,就可以得到絕大部分我們想要的東西。

這篇文章將要介紹的就是,如何在不了解內(nèi)部結(jié)構(gòu)的情況下在Three.js中使用矩陣和向量。

從一個(gè)例子開始

在講解一些枯燥的概念前先舉一個(gè)小例子,來簡要說明一下為什么我們要使用矩陣方法。

這是我們最終要完成的效果。

首先,我們要?jiǎng)?chuàng)建三個(gè)幾何體:

var box_geometry = new THREE.BoxGeometry();
var sphere_geometry = new THREE.SphereGeometry(0.5, 32, 32);
var cylinder_geometry = new THREE.CylinderGeometry(0.1, 0.1, 0.5);

var material = new THREE.MeshLambertMaterial({color: new THREE.Color(0.9, 0.55, 0.4)})

這三個(gè)幾何體分別是盒子、球和圓柱體。

然后去創(chuàng)建三個(gè)網(wǎng)格,并將它們置入場景。

var box = new THREE.Mesh(box_geometry, material);
var sphere = new THREE.Mesh(sphere_geometry, material);
sphere.position.y += 1;
var cylinder = new THREE.Mesh(cylinder_geometry, material);
cylinder.position.y += 1.75;
scene.add(box);
scene.add(sphere);
scene.add(cylinder);

這段代碼將生成如下場景:

雖然不那么美觀,但作為示例已經(jīng)足夠了,現(xiàn)在我希望這堆物體尺寸減半。通常我會把物體的scale屬性減半,像這樣:

box.scale.multiplyScalar(0.5); 
sphere.scale.multiplyScalar(0.5);
cylinder.scale.multiplyScalar(0.5);

和想象中的有些偏差。我的本意是讓這一組物體進(jìn)行一個(gè)整體的縮放,并不想讓它們彼此偏離,為了修正這件事,我需要根據(jù)其他對象的縮放重新計(jì)算每個(gè)對象的位置。但這并不是一件很難解決的問題,three.js提供了一種優(yōu)雅的方式,來處理這個(gè)問題。我們可以定義一個(gè)空對象,然后將三個(gè)對象放在其中,然后將比例應(yīng)用于父對象。

var pile = new THREE.Object3D();
pile.scale.multiplyScalar(0.5);
pile.add(box);
pile.add(sphere);
pile.add(cylinder);
scene.add(pile);

接下來我們做一點(diǎn)更有趣的事。

我將在這個(gè)物體組合里添加旋轉(zhuǎn),讓我們嘗試圍繞球體表面旋轉(zhuǎn)的那個(gè)圓柱體,就像他將要滑落一樣。

它變成了這樣,很明顯,這不是我想要的東西。我們在這里有兩個(gè)做法可供選擇:第一,通過數(shù)學(xué)計(jì)算算出圓柱相對于球體的正確位置;第二,創(chuàng)建另一個(gè)Object3D,將圓柱和球放進(jìn)去并旋轉(zhuǎn)。這聽上去挺復(fù)雜的,而且也很不酷。

所以,我們可以嘗試自己去計(jì)算矩陣。

首先,我需要將屬性maxtrixAutoUpdate設(shè)置為false,然后我就不能再通過position,scale和rotation去修改矩陣。

box.matrixAutoUpdate = false;
sphere.matrixAutoUpdate = false;
cylinder.matrixAutoUpdate = false;

現(xiàn)在,我將用applyMatrix方法來解決這個(gè)問題。具體做法是:為每個(gè)對象創(chuàng)建一個(gè)Matrix4,然后我們將矩陣與該矩陣相乘以應(yīng)用后續(xù)操作。

var sphere_matrix = new THREE.Matrix4().makeTranslation(0.0, 1.0, 0.0); 
sphere.applyMatrix(sphere_matrix);
var cylinder_matrix = sphere_matrix.clone(); cylinder_matrix.multiply(new THREE.Matrix4().makeTranslation(0.0, 0.75, 0.0)); 
cylinder.applyMatrix(cylinder_matrix);

這幾步下來,可以讓我們解鎖很多知識,來看看這里發(fā)生了什么。

首先,我們把盒子單獨(dú)留下,因?yàn)樗恍枰獎(jiǎng)印?br />

接著,我創(chuàng)建了一個(gè)平移矩陣并把它應(yīng)用到了球?qū)ο笊稀?br />

最后,在圓柱體上,我clone了球的矩陣信息,并在此基礎(chǔ)上又創(chuàng)建了一個(gè)新的平移矩陣,圓柱體將移動1.75。

理解了上面幾步,你就會知道最后一步該做什么了。

只需要一行代碼,作用在球上:

sphere_matrix.multiply(new THREE.Matrix4().makeRotationZ(-Math.PI * 0.25));

達(dá)成了想要的效果,很酷。

示例中用到的方法

在上面的示例中,我將球和圓柱體分別沿y軸移動了一定的距離,并使用了makeTranslation這個(gè)方法。這個(gè)方法的作用是創(chuàng)建了一個(gè)平移矩陣。緊接著,我又使用到了applyMatrix的方法。這個(gè)方法的作用是把平移矩陣作用在球和圓柱體上。

那么什么是平移矩陣?它又是如何完成一次平移呢?

Three.js中最常見的一種4x4的矩陣,被稱為變換矩陣,它所表示的變換類型包括平移、旋轉(zhuǎn)和縮放。

用一個(gè)簡單的數(shù)學(xué)題來說明變換矩陣:

有一個(gè)起始點(diǎn),用向量來表示即為Vector3(20,20,0);現(xiàn)在,我要把它移動到另一個(gè)位置,Vector3(30,60,0)。

接下來,我設(shè)置一個(gè)平移矩陣,來表示向量依照什么方式去移動。

t = |1 0 0 10|
 |0 1 0 40|
 |0 0 1 0 |
 |0 0 0 1 |

最后,用起始的向量去乘以變換矩陣的向量。

|20| |1 0 0 10| |30|
|20| x |0 1 0 40| = |60|
|0 | |0 0 1 0 | |0 |
|1 | |0 0 0 1 | |1 |

變換公式如下:

transformedVector = vector * transformationMatrix

最終的變換向量 = 原始向量 * 變換矩陣

用我們上面例子中的方法來還原這個(gè)公式,即:

var vector = new THREE.Vector3(20, 20, 0);
var matrix = new THREE.Matrix4();
matrix.makeTranslation(10, 40, 0);
vector.applyMatrix4(matrix);

除了平移,Three的API中還提供了rotation和scale,scale變化很簡單,它將使用makeScale(x, y, z)這個(gè)方法來表示縮放。

而旋轉(zhuǎn)則相對復(fù)雜許多,Three.js提供以下旋轉(zhuǎn)方法:

matrix.makeRotationX(angle);
matrix.makeRotationY(angle);
matrix.makeRotationZ(angle);
matrix.makeRotationAxis(axis, angle);
matrix.makeRotationFromEuler(euler);
matrix.makeRotationFromQuaternion(quaternion);

前三個(gè)方法分別代表的是繞X、Y、Z三個(gè)軸旋轉(zhuǎn),無需贅述。

第四個(gè)方法是前三個(gè)方法的整合版,第一個(gè)參數(shù)表示的是代表xyz的THREE.Vector3,第二個(gè)參數(shù)是旋轉(zhuǎn)的弧度。下面兩行代碼是等價(jià)的:

matrix.makeRotationX(Math.PI);
matrix.makeRotationAxis(new THREE.Vector3(1, 0, 0), Math.PI);

第五個(gè)方法表示圍繞x、y和z軸的旋轉(zhuǎn),這是表示旋轉(zhuǎn)最常用的方式;第六個(gè)方法是一種基于軸和角度表示旋轉(zhuǎn)的替代方法。

最后,Three.js api提供了一種方法來創(chuàng)建表示平移,旋轉(zhuǎn)和縮放的組合的矩陣 -- matrix.compose:

var translation = new THREE.Vector3();
var rotation = new THREE.Quaternion();
var scale = new THREE.Vector3();
var matrix = new THREE.Matrix4();
matrix.compose(translation, rotation, scale);

矩陣相乘

矩陣乘法的意義在于疊加。

上圖表示了三個(gè)變化:旋轉(zhuǎn)、縮放和移動。

通過按次序相乘,三個(gè)變化矩陣可以得出一個(gè)最終的變化矩陣:

combinedMatrix = rotationMatrix * scaleMatrix * translationMatrix;

Three.js里提供了兩種矩陣相乘的方法:

  • matrix.multiply(otherMatrix)
  • matrix.multiplyMatrices(matrixA, matrixB)

第一種方法表示將矩陣乘以另一個(gè)矩陣;而第二種方法代表的是將矩陣設(shè)置為matrixA * matrixB的結(jié)果。

我們在示例中也使用到了第一個(gè)方法:將圓柱體的矩陣乘以新的平移矩陣,和將球的矩陣乘以一個(gè)旋轉(zhuǎn)矩陣。

需要注意的是,乘法交換律不適用于矩陣乘法,矩陣乘法是具有次序的,先旋轉(zhuǎn)再移動和先移動再旋轉(zhuǎn)的結(jié)果是完全不同的。

矩陣的逆

在數(shù)字的運(yùn)算里,除法相當(dāng)于是乘法的“撤銷”操作:

4 x 5 = 20
20 / 5 = 4

但是在矩陣計(jì)算里,這個(gè)守則同樣是不適用的。我們不能用向量去除一個(gè)矩陣,我們只能用向量去乘以一個(gè)矩陣的逆矩陣,來完成“撤銷”的操作。

變化后的向量 = 原始向量 * 變化矩陣;
逆矩陣 = 變化矩陣.inverse();
原始向量 = 變化后的向量 * 逆矩陣;

逆矩陣表示的是相反的變換。

Three.js里提供了一種計(jì)算逆矩陣的方法:

var matrix = new THREE.Matrix4();
var inverseMatrix = new THREE.Matrix4();
matrix.getInverse(inverseMatrix);

除此之外,逆矩陣還應(yīng)用在3D場景中處理相機(jī)對象的時(shí)候。

最后

矩陣在3D世界里是一種十分強(qiáng)大的工具,它能夠?qū)⑷我庾儞Q都表示為一種相似的結(jié)構(gòu),并采用相同的計(jì)算過程。而實(shí)際上,矩陣的世界遠(yuǎn)遠(yuǎn)比這里介紹的內(nèi)容更多,希望通過這些簡要的介紹,可以讓我們進(jìn)入到一個(gè)更深的領(lǐng)域,并游刃有余的利用他處理圖形開發(fā)中更復(fù)雜的場景。

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對腳本之家的支持。

相關(guān)文章

  • js實(shí)現(xiàn)二級導(dǎo)航功能

    js實(shí)現(xiàn)二級導(dǎo)航功能

    本文主要介紹了js實(shí)現(xiàn)二級導(dǎo)航功能的實(shí)例,具有很好的參考價(jià)值。下面跟著小編一起來看下吧
    2017-03-03
  • js設(shè)計(jì)模式之結(jié)構(gòu)型享元模式詳解

    js設(shè)計(jì)模式之結(jié)構(gòu)型享元模式詳解

    這篇文章主要為大家詳細(xì)介紹了js設(shè)計(jì)模式之結(jié)構(gòu)型享元模式的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • 如何開發(fā)出更好的JavaScript模塊

    如何開發(fā)出更好的JavaScript模塊

    給大家分享一下如何才能開發(fā)出更好的JavaScript模塊和功能,有興趣的朋友參考學(xué)習(xí)下吧。
    2017-12-12
  • p5.js臨摹旋轉(zhuǎn)愛心

    p5.js臨摹旋轉(zhuǎn)愛心

    這篇文章主要為大家詳細(xì)介紹了p5.js臨摹旋轉(zhuǎn)愛心,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • JavaScript十大取整方法實(shí)例教程

    JavaScript十大取整方法實(shí)例教程

    這篇文章主要給大家介紹了關(guān)于JavaScript的十大取整方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 基于JavaScript實(shí)現(xiàn)的順序查找算法示例

    基于JavaScript實(shí)現(xiàn)的順序查找算法示例

    這篇文章主要介紹了基于JavaScript實(shí)現(xiàn)的順序查找算法,結(jié)合實(shí)例形式分析了javascript順序查找的原理、實(shí)現(xiàn)技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2017-04-04
  • 詳談js中window.location.search的用法和作用

    詳談js中window.location.search的用法和作用

    下面小編就為大家?guī)硪黄斦刯s中window.location.search的用法和作用。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-02-02
  • IONIC自定義subheader的最佳解決方案

    IONIC自定義subheader的最佳解決方案

    本文重點(diǎn)給大家介紹IONIC自定義subheader的最佳解決方案,本文實(shí)例講解,介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2016-09-09
  • JavaScript定時(shí)器setTimeout()和setInterval()詳解

    JavaScript定時(shí)器setTimeout()和setInterval()詳解

    這篇文章主要為大家詳細(xì)介紹了JavaScript定時(shí)器setTimeout()和setInterval()的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • 兼容IE和FF的js腳本代碼小結(jié)(比較常用)

    兼容IE和FF的js腳本代碼小結(jié)(比較常用)

    做BS開發(fā)就難免會用到j(luò)avascript,而每個(gè)瀏覽器對javascript的支持有不同。這就需要我們程序員去兼容他們下面是兼容IE和FF的js腳本做法和分解(部分選自網(wǎng)上,經(jīng)本人整理),希望對大家有幫助。
    2010-12-12

最新評論

西吉县| 达州市| 钦州市| 伊吾县| 南阳市| 绥宁县| 梨树县| 佛坪县| 翁源县| 阳新县| 新疆| 怀安县| 长泰县| 闻喜县| 隆化县| 永济市| 绵竹市| 沁阳市| 读书| 邹城市| 鄂托克前旗| 双桥区| 汉沽区| 丹凤县| 进贤县| 马山县| 阿巴嘎旗| 阿城市| 缙云县| 林州市| 虹口区| 博白县| 吉林省| 济南市| 绥德县| 大城县| 天水市| 新田县| 吴堡县| 临汾市| 四川省|