從零開始學習three.js(21):一文詳解three.js中的矩陣Matrix和向量Vector

一、三維世界的數學基石

在Three.js的三維世界里,所有視覺效果的實現都建立在嚴密的數學基礎之上。其中向量(Vector)矩陣(Matrix) 是最核心的數學工具,它們就像構建數字宇宙的原子與分子,支撐著物體的移動、旋轉、縮放以及復雜的空間變換。本文一文詳解向量(Vector)矩陣(Matrix)

1.1 向量:三維空間的基本元素

向量是描述空間方向和位置的數學實體,在Three.js中主要使用以下三種向量類型:

// 三維向量(最常用)
const position = new THREE.Vector3(1, 2, 3);// 二維向量(用于UV映射)
const uvCoord = new THREE.Vector2(0.5, 0.5);// 四維向量(顏色RGBA或特殊計算)
const color = new THREE.Vector4(1, 0, 0, 0.5);

核心操作示例

// 向量加法(物體位移)
const v1 = new THREE.Vector3(1, 2, 3);
const v2 = new THREE.Vector3(4, 5, 6);
v1.add(v2); // (5,7,9)// 點積計算(光照計算)
const lightDir = new THREE.Vector3(0, 1, 0).normalize();
const normal = new THREE.Vector3(0, 0, 1);
const dotProduct = lightDir.dot(normal); // 0// 叉乘應用(計算法線)
const tangent = new THREE.Vector3(1, 0, 0);
const bitangent = new THREE.Vector3(0, 1, 0);
const normal = tangent.cross(bitangent); // (0,0,1)

1.2 矩陣:空間變換

Three.js中的矩陣主要用于描述空間變換關系,以下是關鍵矩陣類型:

矩陣類型維度應用場景
Matrix33x3UV變換、法線矩陣
Matrix44x4模型視圖投影矩陣(核心)
Matrix4數組-實例化渲染

二、矩陣運算的奧秘

2.1 基礎矩陣操作

// 創建單位矩陣(所有矩陣變換的起點)
const identityMat = new THREE.Matrix4().identity();// 矩陣相乘(變換組合)
const rotateMat = new THREE.Matrix4().makeRotationX(Math.PI/2);
const translateMat = new THREE.Matrix4().makeTranslation(0, 5, 0);
const finalMat = translateMat.multiply(rotateMat); // 注意順序!// 矩陣求逆(坐標系轉換)
const viewMatrix = camera.matrixWorldInverse;

2.2 矩陣分解技巧

const matrix = new THREE.Matrix4();
const position = new THREE.Vector3();
const quaternion = new THREE.Quaternion();
const scale = new THREE.Vector3();matrix.decompose(position, quaternion, scale);
console.log('Position:', position);
console.log('Rotation:', quaternion);
console.log('Scale:', scale);

三、矩陣變換實戰指南

3.1 變換組合原理

Three.js采用后乘的矩陣組合方式,理解執行順序至關重要:

const mesh = new THREE.Mesh(geometry, material);// 正確的變換順序:縮放 -> 旋轉 -> 平移
mesh.scale.set(2, 2, 2);
mesh.rotation.x = Math.PI/4;
mesh.position.y = 10;// 等效矩陣計算:
const scaleMat = new THREE.Matrix4().makeScale(2, 2, 2);
const rotateMat = new THREE.Matrix4().makeRotationX(Math.PI/4);
const translateMat = new THREE.Matrix4().makeTranslation(0, 10, 0);// 矩陣組合順序:T * R * S
const finalMatrix = translateMat.multiply(rotateMat).multiply(scaleMat);
mesh.matrix = finalMatrix;

3.2 矩陣堆棧管理

在復雜層級結構中,矩陣需要逐級傳遞:

function updateWorldMatrices(object, parentMatrix) {if (!parentMatrix) parentMatrix = new THREE.Matrix4();// 計算本地矩陣object.updateMatrix();// 組合世界矩陣object.matrixWorld.multiplyMatrices(parentMatrix, object.matrix);// 遞歸處理子對象for (let child of object.children) {updateWorldMatrices(child, object.matrixWorld);}
}

四、關鍵矩陣系統解析

4.1 模型視圖投影矩陣(MVP)

// 獲取三個關鍵矩陣
const modelMatrix = mesh.matrixWorld;
const viewMatrix = camera.matrixWorldInverse;
const projectionMatrix = camera.projectionMatrix;// 組合MVP矩陣
const mvpMatrix = new THREE.Matrix4().multiplyMatrices(projectionMatrix, viewMatrix).multiply(modelMatrix);

4.2 法線矩陣(Normal Matrix)

const normalMatrix = new THREE.Matrix3();
normalMatrix.getNormalMatrix(modelViewMatrix);// 在著色器中使用
material.onBeforeCompile = (shader) => {shader.uniforms.normalMatrix = { value: normalMatrix };shader.vertexShader = `uniform mat3 normalMatrix;${shader.vertexShader}`.replace('#include <beginnormal_vertex>', `objectNormal = normalMatrix * objectNormal;`);
};

五、性能優化策略

5.1 矩陣更新優化

// 禁用自動矩陣更新
mesh.matrixAutoUpdate = false;// 手動批量更新
function updateScene() {objects.forEach(obj => {obj.updateMatrix();obj.updateMatrixWorld(true); // 跳過子對象更新});
}

5.2 矩陣緩存重用

const _tempMatrix = new THREE.Matrix4();function calculateTransform(position, rotation, scale) {return _tempMatrix.compose(position, rotation, scale).clone();
}

六、常見問題診斷

6.1 變換順序錯誤

癥狀:物體縮放導致旋轉軸偏移
解決方案

// 錯誤方式:
mesh.position.set(0, 5, 0);
mesh.rotation.y = Math.PI/2;
mesh.scale.set(2, 2, 2);// 正確方式:
mesh.scale.set(2, 2, 2);
mesh.rotation.y = Math.PI/2;
mesh.position.set(0, 5, 0);

6.2 矩陣更新遺漏

癥狀:子對象未跟隨父級移動
解決方案

parent.add(child);
parent.matrixWorldNeedsUpdate = true; // 強制更新世界矩陣

七、高階應用實例

7.1 自定義矩陣動畫

function matrixAnimation(mesh, duration) {const startMatrix = mesh.matrix.clone();const endMatrix = new THREE.Matrix4().makeRotationY(Math.PI).multiply(new THREE.Matrix4().makeTranslation(5, 0, 0));new TWEEN.Tween({ t: 0 }).to({ t: 1 }, duration).onUpdate(({ t }) => {mesh.matrix = startMatrix.clone().lerp(endMatrix, t);mesh.matrixWorldNeedsUpdate = true;}).start();
}

7.2 GPU矩陣計算

// 頂點著色器中使用自定義矩陣
const material = new THREE.ShaderMaterial({uniforms: {customMatrix: { value: new THREE.Matrix4() }},vertexShader: `uniform mat4 customMatrix;void main() {gl_Position = projectionMatrix * modelViewMatrix * customMatrix * vec4(position, 1.0);}`
});

八、調試與可視化工具

8.1 矩陣可視化

function printMatrix(label, matrix) {console.log(`${label}:`);const te = matrix.elements;for (let i = 0; i < 4; i++) {console.log(te[i*4].toFixed(2), te[i*4+1].toFixed(2),te[i*4+2].toFixed(2),te[i*4+3].toFixed(2));}
}

8.2 坐標系輔助顯示

const axisHelper = new THREE.AxesHelper(5);
mesh.add(axisHelper);// 實時顯示世界坐標系
function updateAxisHelper() {axisHelper.matrixWorld.copy(mesh.matrixWorld);axisHelper.matrixWorld.decompose(axisHelper.position,axisHelper.quaternion,axisHelper.scale);
}

九、最佳實踐總結

  1. 優先使用高層API:盡量通過positionrotationscale屬性操作對象
  2. 謹慎直接修改矩陣:僅在必要時直接操作矩陣元素
  3. 注意更新順序:修改屬性后及時調用updateMatrix()
  4. 重用矩陣對象:避免頻繁創建新矩陣實例
  5. 理解空間轉換鏈局部坐標 -> 世界坐標 -> 視圖坐標 -> 裁剪坐標

通過掌握矩陣與向量的奧秘,開發者可以:
? 實現精準的物理碰撞檢測
? 創建電影級動態光影效果
? 構建工業級數字孿生系統
? 開發復雜機械運動仿真

建議結合Three.js官方文檔中的Matrix4和Vector3API參考進行實踐,并利用瀏覽器開發者工具實時觀察矩陣變化。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/81506.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/81506.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/81506.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ArcGIS Pro 3.4 二次開發 - 內容

環境&#xff1a;ArcGIS Pro SDK 3.4 .NET 8 文章目錄 內容1 工程1.1 創建一個空工程1.2 使用指定名稱創建新工程1.3 使用Pro的默認設置創建新工程1.4 使用自定義模板文件創建新工程1.5 使用 ArcGIS Pro 提供的模板創建工程1.6 打開現有工程1.7 獲取當前工程1.8 獲取當前工程的…

【Python-Day 15】深入探索 Python 字典 (下):常用方法、遍歷、推導式與嵌套實戰

Langchain系列文章目錄 01-玩轉LangChain&#xff1a;從模型調用到Prompt模板與輸出解析的完整指南 02-玩轉 LangChain Memory 模塊&#xff1a;四種記憶類型詳解及應用場景全覆蓋 03-全面掌握 LangChain&#xff1a;從核心鏈條構建到動態任務分配的實戰指南 04-玩轉 LangChai…

31、魔法生物圖鑒——React 19 Web Workers

一、守護神協議&#xff08;核心原理&#xff09; 1. 靈魂分裂術&#xff08;線程架構&#xff09; // 主組件中初始化Workerconst workerRef useRef(null);?useEffect(() > {workerRef.current new Worker(new URL(./creatureWorker.js, import.meta.url));workerRef.…

Spark SQL 之 Antlr grammar 具體分析

src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBaseLexer.g4 BACKQUOTED_IDENTIFIER: ` ( ~` | `` )* `;src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBaseParser.g4 queryPrimary:

低功耗:XILINX FPGA如何優化功耗?

優化Xilinx FPGA及其外圍電路的功耗需要從硬件設計、軟件配置和系統級優化三個層面綜合考慮。以下是具體的優化策略&#xff0c;涵蓋硬件和軟件方面&#xff1a; 一、硬件層面的功耗優化 選擇低功耗FPGA型號 選擇Xilinx低功耗系列芯片&#xff0c;如7系列中的Artix-7&#xff…

深入理解 ZAB:ZooKeeper 原子廣播協議的工作原理

目錄 ZAB 協議&#xff1a;ZooKeeper 如何做到高可用和強一致&#xff1f;&#x1f512;ZAB 協議的核心目標 &#x1f3af;ZAB 協議的關鍵概念 &#x1f4a1;ZAB 協議的運行階段 &#x1f3ac;階段一&#xff1a;Leader 選舉 (Leader Election) &#x1f5f3;?階段二&#xff…

OpenHarmony外設驅動使用 (五),Fingerprint_auth

OpenHarmony外設驅動使用 &#xff08;五&#xff09; Fingerprint_auth 概述 功能簡介 指紋認證是端側設備不可或缺的功能&#xff0c;為設備提供用戶認證能力&#xff0c;可應用于設備解鎖、支付、應用登錄等身份認證場景。用戶注冊指紋后&#xff0c;指紋認證模塊就可為設…

前端(vue)學習筆記(CLASS 6):路由進階

1、路由的封裝抽離 將之前寫在main.js文件中的路由配置與規則抽離出來&#xff0c;放置在router/index.js文件中&#xff0c;再將其導入回main.js文件中&#xff0c;即可實現路由的封裝抽離 例如 //index.js import { createMemoryHistory, createRouter } from vue-routerim…

前后端交互中的絕對路徑和相對路徑

前端 <form action"hello" method"post"> 1. 不加斜杠 &#xff08;相對路徑&#xff0c;如 action"hello"&#xff09; 解析規則&#xff1a;基于當前頁面的 URL 路徑部分 進行拼接。 假設當前頁面 URL 是 http://域名:端口/應用上下文…

在Odoo 18中創建進度條指南

在Odoo 18中創建進度條指南 一、創建進度條模板 首先在名為 progress_bar_widget.xml 的文件中定義一個名為 ProgressBarWidget 的新模板。該模板使用兩個CSS類&#xff1a;progress-bar-inner 用于樣式化進度條&#xff0c;progress_number 用于顯示進度百分比。您可以根據需…

Linux grep 命令詳解:常用選項、參數及實戰場景

一、grep 命令簡介 grep&#xff08;Global Regular Expression Print&#xff09;是 Linux 中用于文本搜索的核心工具&#xff0c;支持正則表達式&#xff0c;能快速定位文件中的目標內容。 二、常用選項&#xff08;Options&#xff09;及英文對照 | 選項 | 英文全稱 | 作用 …

【Java-EE進階】SpringBoot針對某個IP限流問題

目錄 簡介 1. 使用Guava的RateLimiter實現限流 添加Guava依賴 實現RateLimiter限流邏輯 限流管理類 控制器中應用限流邏輯 2. 使用計數器實現限流 限流管理類 控制器中應用限流邏輯 簡介 針對某個IP進行限流以防止惡意點擊是一種常見的反爬蟲和防止DoS的措施。限流策…

Linux問題排查-找到偷偷寫文件的進程

在 Linux 系統中&#xff0c;若要通過已修改的文件找到修改該文件的進程 PID&#xff0c;可以結合以下方法分析&#xff0c;具體取決于文件是否仍被進程打開或已被刪除但句柄仍存在&#xff1a; 一、文件仍被進程打開&#xff08;未刪除&#xff09; 如果文件當前正在被某個進…

More Effective C++:改善編程與設計(下)

目錄 條款19:了解臨時對象的來源 條款20:協助完成“返回值優化” 條款21:利用重載技術避免隱式類型轉換 條款22:考慮以操作符復合形式&#xff08;op&#xff09;取代其獨身形式&#xff08;op&#xff09; 條款23:考慮使用其他程序庫 條款24:了解virtual functions、mul…

VTK|類似CloudCompare的比例尺實現2-vtk實現

文章目錄 實現類頭文件實現類源文件調用邏輯關鍵問題縮放限制問題投影模式項目git鏈接實現類頭文件 以下是對你提供的 ScaleBarController.h 頭文件添加詳細注釋后的版本,幫助你更清晰地理解每個成員和方法的用途,尤其是在 VTK 中的作用: #ifndef SCALEBARCONTROLLER_H #de…

PostgreSQL 聯合索引生效條件

最近面試的時候&#xff0c;總會遇到一個問題 在 PostgreSQL 中&#xff0c;聯合索引在什么條件下會生效&#xff1f; 特此記錄~ 前置信息 數據庫版本 PostgreSQL 14.13, compiled by Visual C build 1941, 64-bit 建表語句 CREATE TABLE people (id SERIAL PRIMARY KEY,c…

SpringBoot項目里面發起http請求的幾種方法

在Spring Boot項目中發起HTTP請求的方法 在Spring Boot項目中&#xff0c;有幾種常用的方式可以發起HTTP請求&#xff0c;以下是主要的幾種方法&#xff1a; 1. 使用RestTemplate (Spring 5之前的主流方式) // 需要先注入RestTemplate Autowired private RestTemplate restT…

《Python星球日記》 第90天:微調的概念以及如何微調大模型?

名人說:路漫漫其修遠兮,吾將上下而求索。—— 屈原《離騷》 創作者:Code_流蘇(CSDN)(一個喜歡古詩詞和編程的Coder??) 目錄 一、微調原理1. 什么是大模型微調?2. 為什么需要微調?3. 微調的基本流程4. 微調策略分類二、LoRA(Low-Rank Adaptation)技術詳解1. LoRA的核…

機器學習-人與機器生數據的區分模型測試 - 模型融合與檢驗

模型融合 # 先用普通Pipeline訓練 from sklearn.pipeline import Pipeline#from sklearn2pmml.pipeline import PMMLPipeline train_pipe Pipeline([(scaler, StandardScaler()),(ensemble, VotingClassifier(estimators[(rf, RandomForestClassifier(n_estimators200, max_de…

怎樣免費開發部署自己的網站?

要免費開發自己的網站&#xff0c;您可以根據自己的技術水平和需求選擇以下兩種主要方式&#xff1a; 零基礎用戶&#xff1a;建議使用如WordPress.com、Weebly、Strikingly等平臺&#xff0c;快速搭建網站。 有一定技術基礎的用戶&#xff1a;可選擇自行開發網站&#xff0c;…