# 【Three.js】三、three.js之几何体与网格

### 三、【Three.js】three.js之几何体与网格

three.js中的几何体基本上可以看成三维空间中的点集和将这些点连起来的面。如立方体是由八个顶点及其连接这些顶点的六个面组成。

# 一、定义一个几何体

	// 定义点
let verties = [
new THREE.Vector3(1,4,1),
new THREE.Vector3(1,4,-1),
new THREE.Vector3(1,0,1),
new THREE.Vector3(1,0,-1),
new THREE.Vector3(-1,4,-1),
new THREE.Vector3(-1,4,1),
new THREE.Vector3(-1,0,-1),
new THREE.Vector3(-1,0,1)
];
// 连接顶点，定义面
let faces = [
new THREE.Face3(0,2,1),
new THREE.Face3(2,3,1),
new THREE.Face3(4,6,5),
new THREE.Face3(6,7,5),
new THREE.Face3(4,5,1),
new THREE.Face3(5,0,1),
new THREE.Face3(7,6,2),
new THREE.Face3(6,3,2),
new THREE.Face3(5,7,0),
new THREE.Face3(7,2,0),
new THREE.Face3(1,3,4),
new THREE.Face3(3,6,4)
];
let geometry = new THREE.Geometry();
geometry.vertices = verties;
geometry.faces = faces;
geometry.computeFaceNormals();
// 创建材质
let materials = [
new THREE.MeshBasicMaterial({color: 0x000000, wireframe: true}),
new THREE.MeshLambertMaterial({opacity: 0.6, color: 0x44ff44, transparent: true})
];
// 根据几何体与材质形成要显示的对象
let mesh = createMultiMaterialObject(geometry, materials);


import '../../stylus/index.styl'
import * as THREE from 'three';
import * as dat from 'dat.gui';
import {initStats,initTrackballControls, createMultiMaterialObject} from '../../util/util';

function init() {
let stats = initStats();
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
renderer.setClearColor(0x000000);

let axes = new THREE.AxesHelper(30);

let planeGeometry = new THREE.PlaneGeometry(60, 40,1,1);
let planeMaterial = new THREE.MeshLambertMaterial({
color: 0xffffff
});
let plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -0.5 * Math.PI;

let ambientLight = new THREE.AmbientLight(0x494949);

let verties = [
new THREE.Vector3(1,4,1),
new THREE.Vector3(1,4,-1),
new THREE.Vector3(1,0,1),
new THREE.Vector3(1,0,-1),
new THREE.Vector3(-1,4,-1),
new THREE.Vector3(-1,4,1),
new THREE.Vector3(-1,0,-1),
new THREE.Vector3(-1,0,1)
];
let faces = [
new THREE.Face3(0,2,1),
new THREE.Face3(2,3,1),
new THREE.Face3(4,6,5),
new THREE.Face3(6,7,5),
new THREE.Face3(4,5,1),
new THREE.Face3(5,0,1),
new THREE.Face3(7,6,2),
new THREE.Face3(6,3,2),
new THREE.Face3(5,7,0),
new THREE.Face3(7,2,0),
new THREE.Face3(1,3,4),
new THREE.Face3(3,6,4)
];
let geometry = new THREE.Geometry();
geometry.vertices = verties;
geometry.faces = faces;
geometry.computeFaceNormals();
let materials = [
new THREE.MeshBasicMaterial({color: 0x000000, wireframe: true}),
new THREE.MeshLambertMaterial({opacity: 0.6, color: 0x44ff44, transparent: true})
];
let mesh = createMultiMaterialObject(geometry, materials);

let spotLight = new THREE.SpotLight(0xffffff,1,150,120);
// 阴影贴图设置,值越大，阴影越清晰，占用资源也越大
spotLight.position.set(-40, 30, 30);
spotLight.lookAt(mesh);

camera.position.x = -20;
camera.position.y = 25;
camera.position.z = 20;
camera.lookAt(new THREE.Vector3(5, 0, 0));
document.body.appendChild(renderer.domElement);
let trackballControls = initTrackballControls(camera, renderer);
let controlPoints = [];
function render () {
stats.update();
trackballControls.update();
let verties = [];
controlPoints.forEach(point => {
verties.push(new THREE.Vector3(point.x, point.y, point.z));
});
mesh.children.forEach(function (e) {
e.geometry.vertices = verties;
e.geometry.verticesNeedUpdate = true;
e.geometry.computeFaceNormals();
delete e.geometry.__directGeometry
});
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
return new function(){
this.x = x;
this.y = y;
this.z = z;
}
}

let gui = new dat.GUI();
this.clone = function(){
let clonedGeometry = mesh.children[0].geometry.clone();
let materials = [
new THREE.MeshLambertMaterial({opacity: 0.8, color: 0xff44ff, transparent: true}),
new THREE.MeshBasicMaterial({color: 0x000000, wireframe: true})
];

let mesh2 = createMultiMaterialObject(clonedGeometry, materials);
mesh2.children.forEach(function (e) {
});

mesh2.translateX(5);
mesh2.translateZ(5);
mesh2.name = "clone";
scene.remove(scene.getChildByName("clone"));
}
}, 'clone');
for(let i = 0; i < 8; i++) {
let folder = gui.addFolder(顶点\${i+1});
}
}



# 二、网格对象

position 该属性决定该对象相对于父对象的位置，通常父对象是THREE.Scene对象或者是THREE.Object3D对象
rotation 通过该属性设置绕每个轴的旋转角度
scale 通过该属性设置在x/y/z轴方向的缩放
translateX(amount) 沿x轴平移amount距离
translateY(amount) 沿y轴平移amount距离
translateZ(amount) 沿z轴平移amount距离
visible 设置是否可见，false不会被渲染到场景

## 2.1 属性OR方法示例

import '../../stylus/index.styl'
import * as THREE from 'three';
import * as dat from 'dat.gui';
import {initTrackballControls, initStats} from '../../util/util'

function init(){
let stats = initStats();
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 100);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);

let axes = new THREE.AxesHelper(30);

let planeGeometry = new THREE.PlaneGeometry(60, 40,1,1);
let planeMaterial = new THREE.MeshLambertMaterial({
color: 0xffffff
});
let plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -0.5*Math.PI;
plane.position.x = 0;
plane.position.y = 0;
plane.position.z = 0;

let cubeGeometry = new THREE.BoxGeometry(5,10,5);
let cubeMaterial = new THREE.MeshLambertMaterial({
color: 0x3896fe,
opacity: .6
});
let cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.position.x = 2.5;
cube.position.y = 5;
cube.position.z = 2.5;

let spotLight = new THREE.SpotLight(0xffffff,1,150,120);
spotLight.position.set(-40, 40, 30);

let ambientLight = new THREE.AmbientLight(0x494949);

camera.position.x = -30;
camera.position.y = 20;
camera.position.z = 30;
camera.lookAt(scene.position);
document.body.appendChild(renderer.domElement);
// 添加控制变量
let controls = new function(){
this.positionX = 2.5;
this.positionY = 5;
this.positionZ = 2.5;
this.rotationX = 0;
this.rotationY = 0;
this.rotationZ = 0;
this.scaleX = 1;
this.scaleY = 1;
this.scaleZ = 1;
this.translateX = 0;
this.translateY = 0;
this.translateZ = 0;
this.visible = true;
this.translate = function() {
cube.translateX(controls.translateX);
cube.translateY(controls.translateY);
cube.translateZ(controls.translateZ);
// 平移之后位置发生变化，重新给位置赋值
controls.positionX = cube.position.x;
controls.positionY = cube.position.y;
controls.positionZ = cube.position.z;
};
}
let gui = new dat.GUI();
let posX = guiPosition.add(controls, 'positionX', -10, 10).listen();
let posY = guiPosition.add(controls, 'positionY', 5, 10).listen();
let posZ = guiPosition.add(controls, 'positionZ', -10, 10).listen();
posX.onChange(value => cube.position.x = value);
posY.onChange(value => cube.position.y = value);
posZ.onChange(value => cube.position.z = value);
let trackballControls = initTrackballControls(camera, renderer);
function render(){
stats.update();
trackballControls.update();
cube.rotation.x = controls.rotationX;
cube.rotation.y = controls.rotationY;
cube.rotation.z = controls.rotationZ;
cube.scale.set(controls.scaleX, controls.scaleY, controls.scaleZ);
cube.visible = controls.visible;
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();

}