一、綜述
在計算機世界里,3D世界是由點組成,兩個點能夠組成一條直線,三個不在一條直線上的點就能夠組成一個三角形面,無數三角形面就能夠組成各種形狀的物體,如下圖:
我們通常把這種網格模型叫做Mesh模型。給物體貼上皮膚,或者專業點就叫做紋理,那么這個物體就活靈活現了。最后無數的物體就組成了我們的3D世界。
二、兩點連成直線
在Three.js中用一個向量來表示點:
var point1 = new THREE.Vecotr3(4,8,9);
另外也可以使用set方法,代碼如下:
var point1 = new THREE.Vector3(); point1.set(4,8,9);
1.畫一條彩色的線代碼
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Three框架</title> <script src="js/Three.js"></script> <style type="text/css"> div#canvas-frame { border: none; cursor: pointer; width: 100%; height: 600px; background-color: #EEEEEE; } </style> <script> var renderer; function initThree() { width = document.getElementById('canvas-frame').clientWidth; height = document.getElementById('canvas-frame').clientHeight; renderer = new THREE.WebGLRenderer({ antialias : true }); renderer.setSize(width, height); document.getElementById('canvas-frame').appendChild(renderer.domElement); renderer.setClearColor(0xFFFFFF, 1.0); } var camera; function initCamera() { camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000); camera.position.x = 0; camera.position.y = 1000; camera.position.z = 0; camera.up.x = 0; camera.up.y = 0; camera.up.z = 1; camera.lookAt({ x : 0, y : 0, z : 0 }); } var scene; function initScene() { scene = new THREE.Scene(); } var light; function initLight() { light = new THREE.DirectionalLight(0xFF0000, 1.0, 0); light.position.set(100, 100, 200); scene.add(light); } var cube; function initObject() { var geometry = new THREE.Geometry(); var material = new THREE.LineBasicMaterial( { vertexColors: true } ); var color1 = new THREE.Color( 0x444444 ), color2 = new THREE.Color( 0xFF0000 ); // 線的材質可以由2點的顏色決定 var p1 = new THREE.Vector3( -100, 0, 100 ); var p2 = new THREE.Vector3( 100, 0, -100 ); geometry.vertices.push(p1); geometry.vertices.push(p2); geometry.colors.push( color1, color2 ); var line = new THREE.Line( geometry, material, THREE.LinePieces ); scene.add(line); } function threeStart() { initThree(); initCamera(); initScene(); initLight(); initObject(); renderer.clear(); renderer.render(scene, camera); } </script> </head> <body onload="threeStart();"> <div id="canvas-frame"></div> </body> </html>
2.畫線
兩點確定一條直線,要畫一條直線,思路是:
- 定義一個幾何體geometry用來存放兩端點的坐標和顏色
- 定義線條材質
- 創建線條並加入到場景中
3.代碼解析
定義點的坐標和顏色
var color1 = new THREE.Color( 0x444444 ), color2 = new THREE.Color( 0xFF0000 ); var p1 = new THREE.Vector3( -100, 0, 100 ); var p2 = new THREE.Vector3( 100, 0, -100 );
聲明幾何體並存放點和頂點顏色
var geometry = new THREE.Geometry(); geometry.vertices.push(p1); geometry.vertices.push(p2); geometry.colors.push( color1, color2 );
幾何體里面有一個vertices變量,可以用來存放點。
geometry中colors表示頂點的顏色,必須材質中vertexColors等於THREE.VertexColors 時,顏色才有效,如果vertexColors等於THREE.NoColors時,顏色就沒有效果了。那么就會去取材質中color的值 。
定義線條材質
var material = new THREE.LineBasicMaterial( { vertexColors: true } );
使用THREE.LineBasicMaterial類型來定義線條材質,它接受一個集合作為參數,其原型如下:
LineBasicMaterial( parameters )
Parameters是一個定義材質外觀的對象,它包含多個屬性來定義材質,這些屬性是:
- Color:線條的顏色,用16進制來表示,默認的顏色是白色。
- Linewidth:線條的寬度,默認時候1個單位寬度。
- Linecap:線條兩端的外觀,默認是圓角端點,當線條較粗的時候才看得出效果,如果線條很細,那么你幾乎看不出效果了。
- Linejoin:兩個線條的連接點處的外觀,默認是“round”,表示圓角。
- VertexColors:定義線條材質是否使用頂點顏色,這是一個boolean值。意思是,線條各部分的顏色會根據頂點的顏色來進行插值。
- Fog:定義材質的顏色是否受全局霧效的影響。
創建線條並加入場景
var line = new THREE.Line( geometry, material, THREE.LinePieces ); scene.add(line);
第一個參數是幾何體geometry,里面包含了2個頂點和頂點的顏色。第二個參數是線條的材質,或者是線條的屬性,表示線條以哪種方式取色。第三個參數是一組點的連接方式。
然后,將這條線加入到場景中,代碼如下:
scene.add(line);
這樣,場景中就會出現剛才的那條線段了。
4.線條深入理解
點由THREE.Vector3表示,Threejs中沒有提供單獨畫點的函數,它必須被放到一個THREE.Geometry形狀中,這個結構中包含一個數組vertices,這個vertices就是存放無數的點(THREE.Vector3)的數組。
三、網格面
1.右手坐標系
Threejs使用的是右手坐標系。x軸正方向向右,y軸正方向向上,z軸由屏幕從里向外。
2.畫坐標平面
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Three框架</title> <script src="js/Three.js"></script> <style type="text/css"> div#canvas-frame { border: none; cursor: pointer; width: 100%; height: 600px; background-color: #EEEEEE; } </style> <script> var renderer; function initThree() { width = document.getElementById('canvas-frame').clientWidth; height = document.getElementById('canvas-frame').clientHeight; renderer = new THREE.WebGLRenderer({ antialias : true }); renderer.setSize(width, height); document.getElementById('canvas-frame').appendChild(renderer.domElement); renderer.setClearColor(0xFFFFFF, 1.0); } var camera; function initCamera() { camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000); camera.position.x = 0; camera.position.y = 1000; camera.position.z = 0; camera.up.x = 0; camera.up.y = 0; camera.up.z = 1; camera.lookAt({ x : 0, y : 0, z : 0 }); } var scene; function initScene() { scene = new THREE.Scene(); } var light; function initLight() { light = new THREE.DirectionalLight(0xFF0000, 1.0, 0); light.position.set(100, 100, 200); scene.add(light); } var cube; function initObject() { var geometry = new THREE.Geometry(); geometry.vertices.push( new THREE.Vector3( - 500, 0, 0 ) ); geometry.vertices.push( new THREE.Vector3( 500, 0, 0 ) ); for ( var i = 0; i <= 20; i ++ ) { var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) ); line.position.z = ( i * 50 ) - 500; scene.add( line ); var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) ); line.position.x = ( i * 50 ) - 500; line.rotation.y = 90 * Math.PI / 180; scene.add( line ); } } function threeStart() { initThree(); initCamera(); initScene(); initLight(); initObject(); renderer.clear(); renderer.render(scene, camera); } </script> </head> <body onload="threeStart();"> <div id="canvas-frame"></div> </body> </html>
3.代碼解析
定義幾何體並加入兩個點。
var geometry = new THREE.Geometry(); geometry.vertices.push( new THREE.Vector3( - 500, 0, 0 ) ); geometry.vertices.push( new THREE.Vector3( 500, 0, 0 ) );
這兩個點決定了x軸上的一條線段,將這條線段復制20次,分別平行移動到z軸的不同位置,就能夠形成一組平行的線段。
同理,將p1p2這條線先圍繞y軸旋轉90度,然后再復制20份,平行於z軸移動到不同的位置,也能形成一組平行線。
經過上面的步驟,就能夠得到坐標網格了。代碼如下:
for ( var i = 0; i <-= 20; i ++ ) { var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) ); line.position.z = ( i * 50 ) - 500; scene.add( line );
var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) ); line.position.x = ( i * 50 ) - 500; line.rotation.y = 90 * Math.PI / 180; // 旋轉90度 scene.add( line ); }
4.補充
相機的position,是相機的位置。如果把人頭比作相機,那么就是人頭的中心的位置。
up是頭頂的方向。
lookat是眼睛,看的方向,或者說是眼睛的聚焦點。
最后要說明的是 up 和lookat這兩個方向必須垂直,無論怎么設置,他們必須互相垂直。不然相機看到的結果無法預知。
另外,相機沒有朝向的說法,只有lookat,就是它看到的那一個聚焦點,就像眼睛看到的聚焦點一樣。