幾何體本質:
立方體幾何體BoxGeometry
本質上就是一系列的頂點構成,只是Threejs的APIBoxGeometry
把頂點的生成細節封裝了,用戶可以直接使用。
比如一個立方體網格模型,有6個面,每個面至少兩個三角形拼成一個矩形平面,每個三角形三個頂點構成,對於球體網格模型而言,同樣是通過三角形拼出來一個球面,三角形數量越多,網格模型表面越接近於球形。
法向量:
什么是法向量?三維平面的法線是垂直於該平面的三維向量。一個平面有無數個法向量。
沒有法向量數據,點光源、平行光等帶有方向性的光源不會起作用(梁濤注:可以使用環境光),三角形平面整個渲染效果相對暗淡,而且兩個三角形分界位置沒有棱角感。設置前后對比如下:
法向量計算方法:(可略過)
1、BA向量的xyz值=A點坐標的xyz分別-B點坐標的xyz
2、n法向量垂直於BA向量,所以乘積為0
3、n法向量*BA向量=n的xyz分別*BA向量的xyz=0
4、平面任一頂點的法向量=平面的法向量
5、平面存在無數的法向量,取任一值即可
使用three.js自定義立方體:
效果圖:
完整代碼:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script src="js/three.min.js"></script> <script src="js/OrbitControls.js"></script> <script> //創建場景 var scene = new THREE.Scene(); /** * 相機設置 */ var width = window.innerWidth-16; //窗口寬度 var height = window.innerHeight-20; //窗口高度 var k = width / height; //窗口寬高比 var s=200; var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000); //創建相機對象 var camera = new THREE.PerspectiveCamera(75, k, 1, 1000); camera.position.set(100, 200, 100); //設置相機位置 /** * 創建渲染器對象 */ var renderer = new THREE.WebGLRenderer(); renderer.setSize(width, height);//設置渲染區域尺寸 renderer.setClearColor(0xb9d3ff, 1); //設置背景顏色 document.body.appendChild(renderer.domElement); //body元素中插入canvas對象 //點光源 var point = new THREE.PointLight(0xffffff); point.position.set(100, 100, 100); //點光源位置 scene.add(point); //點光源添加到場景中 //聲明一個空幾何體對象 var geometry = new THREE.BufferGeometry(); //類型數組創建頂點位置position數據 var vertices = new Float32Array([ //第一個面 0, 0, 0, 50, 0, 0, 0, 50, 0, 50, 0, 0, 0, 50, 0, 50, 50, 0, //第二個面 0, 0, 0, 0, 50, 0, 0, 50, 50, 0, 50, 50, 0, 0, 0, 0, 0, 50, //第三個面 50, 0, 0, 50, 50, 0, 50, 50, 50, 50, 0, 0, 50, 0, 50, 50, 50, 50, //第四個面 0, 0, 0, 0, 0, 50, 50, 0, 0, 50, 0, 0, 50, 0, 50, 0, 0, 50, //第五個面 0, 50, 0, 0, 50, 50, 50, 50, 0, 50, 50, 0, 50, 50, 50, 0, 50, 50, //第六個面 0, 0, 50, 50, 0,50, 0, 50, 50, 50, 0, 50, 0, 50, 50, 50, 50, 50, ]); // 創建屬性緩沖區對象 var attribue = new THREE.BufferAttribute(vertices, 3); //3個為一組 // 設置幾何體attributes屬性的位置position屬性 geometry.attributes.position = attribue //設置法向量 var normals = new Float32Array([ //第一個面頂點的法向量 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, //第二個面頂點的法向量 -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, //第三個面頂點的法向量 1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0, //第四個面頂點的法向量 0,-1,0, 0,-1,0, 0,-1,0, 0,-1,0, 0,-1,0, 0,-1,0, //第五個面頂點的法向量 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, //第四個面頂點的法向量 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, ]); // 設置幾何體attributes屬性的位置normal屬性 geometry.attributes.normal = new THREE.BufferAttribute(normals, 3); //3個為一組,表示一個頂點的法向量數據 // 三角面(網格)渲染模式 var material = new THREE.MeshLambertMaterial({ color: 0x0000ff, //三角面顏色 side: THREE.DoubleSide //兩面可見 }); //材質對象 var mesh = new THREE.Mesh(geometry, material); //網格模型對象Mesh scene.add(mesh); // 點渲染模式 var material = new THREE.PointsMaterial({ color: 0xff0000, size: 5.0 //點對象像素尺寸 }); //材質對象 var points = new THREE.Points(geometry, material); //點模型對象 scene.add(points); //點對象添加到場景中 // 輔助坐標系 參數250表示坐標系大小,可以根據場景大小去設置 var axisHelper = new THREE.AxisHelper(250); scene.add(axisHelper); //添加幀渲染 function render() { renderer.render(scene, camera); //執行渲染操作 requestAnimationFrame(render); //請求再次執行渲染函數render } render(); var controls = new THREE.OrbitControls(camera, renderer.domElement); //創建鼠標控制對象 //尺寸響應式 window.addEventListener('resize', () => { //初始化攝像機 camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); //初始化渲染器 renderer.setSize(window.innerWidth, window.innerHeight); }) </script> </body> </html>
頂點索引復用頂點數據
通過頂點索引組織網格模型三角形的繪制,因為矩形的兩個三角形有兩個頂點位置重復,所以頂點位置數據、頂點法向量數據可以復用。立方體只需要定義8個頂點。
//聲明一個空幾何體對象 var geometry = new THREE.BufferGeometry(); //類型數組創建頂點位置position數據 var vertices = new Float32Array([ //第一個面 0, 0, 0, 50, 0, 0, 50, 50, 0, 0, 50, 0, 0, 0, 50, 50, 0, 50, 50, 50, 50, 0, 50, 50, ]); // 創建屬性緩沖區對象 var attribue = new THREE.BufferAttribute(vertices, 3); //3個為一組 // 設置幾何體attributes屬性的位置position屬性 geometry.attributes.position = attribue //設置法向量 var normals = new Float32Array([ //第一個頂點的法向量 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, ]); // 設置幾何體attributes屬性的位置normal屬性 geometry.attributes.normal = new THREE.BufferAttribute(normals, 3); //3個為一組,表示一個頂點的法向量數據 // Uint16Array類型數組創建頂點索引 var indexes = new Uint16Array([ // 0對應第1個頂點位置數據、第1個頂點法向量數據 // 1對應第2個頂點位置數據、第2個頂點法向量數據 // 索引值3個為一組,表示一個三角形的3個頂點 0,1,2, 0,2,3, 2,3,6, 3,6,7, 1,2,5, 2,5,6, 0,3,4, 3,4,7, 1,4,5, 0,1,4, 4,5,7, 5,6,7 ]) // 索引數據賦值給幾何體的index屬性 geometry.index = new THREE.BufferAttribute(indexes, 1); //1個為一組
創建頂點索引數組的時候,可以根據頂點的數量選擇類型數組Uint8Array
、Uint16Array(
數據無符號16位整型)
、Uint32Array
。對於頂點索引而言選擇整型類型數組,對於非索引的頂點數據,需要使用浮點類型數組Float32Array
等。
Face3
對象定義Geometry
的三角形面
幾何體Geometry的三角面屬性geometry.faces
和緩沖類型幾何體BufferGeometry頂點索引屬性BufferGeometry.index
類似都是頂點位置數據的索引值,用來組織網格模型三角形的繪制。
threejs提供了Face3
對象構建三角形,通過Face3
構建一個三角形,不要設置頂點位置坐標數據,只需要通過數組索引值從geometry.vertices
數組中獲得頂點位置坐標數據。
//聲明一個幾何體對象Geometry var geometry = new THREE.Geometry(); //類型數組創建頂點位置position數據 var p1 = new THREE.Vector3(0, 0, 0); //頂點1坐標 var p2 = new THREE.Vector3(50, 0, 0); //頂點2坐標 var p3 = new THREE.Vector3(50, 50, 0); //頂點3坐標 var p4 = new THREE.Vector3(0, 50, 0); //頂點4坐標 var p5 = new THREE.Vector3(0, 0, 50); //頂點5坐標 var p6 = new THREE.Vector3(50, 0, 50); //頂點6坐標 var p7 = new THREE.Vector3(50, 50, 50); //頂點7坐標 var p8 = new THREE.Vector3(0, 50, 50); //頂點8坐標 //頂點坐標添加到geometry對象 geometry.vertices.push(p1, p2, p3,p4,p5,p6,p7,p8); // Face3構造函數創建一個三角面 var face1 = new THREE.Face3(0,1,2); var face2 = new THREE.Face3(0,2,3); var face3 = new THREE.Face3(2,3,6); var face4 = new THREE.Face3(3,6,7); var face5 = new THREE.Face3(1,2,5); var face6 = new THREE.Face3(2,5,6); var face7 = new THREE.Face3(0,3,4); var face8 = new THREE.Face3(3,4,7); var face9 = new THREE.Face3(1,4,5); var face10 = new THREE.Face3(0,1,4); var face11 = new THREE.Face3(4,5,7); var face12 = new THREE.Face3(5,6,7); // 設置三角面法向量 face3.normal=new THREE.Vector3(0, 0, 1); // 設置三角面face1三個頂點的顏色 face1.color = new THREE.Color(0xff00ff); //三角面face1、face2添加到幾何體中 geometry.faces.push(face1,face2,face3,face4,face5,face6,face7,face8,face9,face10,face11,face12); //縮放 geometry.scale(0.5, 1.5, 1.5);
總結:
BufferGeometry總結
Geometry總結
幾何體縮放、平移、旋轉屬性