Open rainit2006 opened 6 years ago
入门教程
入門 To actually be able to display anything with three.js, we need three things: scene, camera and renderer.
Geometry 几何形状类型汇总:
BoxGeometry 是四边形几何类,
THREE.BoxGeometry(width, height, depth, widthSegments, heightSegments, depthSegments)
PlaneGeometry 是平面类, 其实是一个长方形。
THREE.PlaneGeometry(width, height, widthSegments, heightSegments)
SphereGeometry 是球体类。
THREE.SphereGeometry(radius, segmentsWidth, segmentsHeight, phiStart, phiLength, thetaStart, thetaLength)
CircleGeometry 几何类可以创建圆形或者扇形;
THREE.CircleGeometry(radius, segments, thetaStart, thetaLength)
CylinderGeometry 表示柱体类
TetrahedronGeometry 正四面体、
OctahedronGeometry / 正八面体、
IcosahedronGeometry / 正二十面体
TorusGeometry 即圆环面, 也为甜甜圈的形状;
TorusKnotGeometry / 圆环结, 形如打了结的甜甜圈;
ExtrudeGeometry 几何类, 用于从一条路径中抽取出特征用于构建几何形状;
ConeGeometry 锥形几何类;
Three.js 还提供了很多其他几何类, 详情可以在 Three.js 文档搜索框中输入 Geometry 关键字, 查看 Geometries 下栏目.
カメラ
正投影和透视投影的区别是:透视投影有一个基本点,就是远处的物体比近处的物体小。我们看看著名的蒙娜丽莎的微笑就是典型的透视作品。 在工程建筑领域,正投影的例子很多。其特点是,远近高低比例都相同。
PerspectiveCamera( fov, aspect, near, far )
fov — Camera frustum vertical field of view.
aspect — Camera frustum aspect ratio.
near — Camera frustum near plane.
far — Camera frustum far plane.
PerspectiveCamera( 視野角 , アスペクト比(縦横比) , カメラから視体積の手前までの距離 , カメラから視体積の奥までの距離); 视野角数值越小,物体越大(离物体越近)。视角越大,中间的物体越小,这是因为,视角越大,看到的场景越大,那么中间的物体相对于整个场景来说,就越小了。
1、视角fov:这个最难理解,我的理解是,眼睛睁开的角度,即,视角的大小,如果设置为0,相当你闭上眼睛了,所以什么也看不到,如果为180,那么可以认为你的视界很广阔,但是在180度的时候,往往物体很小,因为他在你的整个可视区域中的比例变小了。
2、纵横比aspect:实际窗口的纵横比,即宽度除以高度。这个值越大,说明你宽度越大,那么你可能看的是宽银幕电影了,如果这个值小于1,那么可能你看到的是如下的图中的LED屏幕了。
3、近平面near:这个呢,表示你近处的裁面的距离。补充一下,也可以认为是眼睛距离近处的距离,假设为10米远,请不要设置为负值,Three.js就傻了,不知道怎么算了,
4、远平面far:这个呢,表示你远处的裁面,
three.jsで扱えるレンダラー(渲染器) WebGLRendererとCanvasRendererは標準で組み込まれていて、それ以外は外部ライブラリを読み込むことで利用可能となる。 WebGLに対応した環境ではWebGLRendererを利用し、対応していない(かつ、HTML5に対応している)環境ではCanvasRendererを利用するというように使いわけることができる。
WebGLRenderTarget: オフスクリーンレンダリング(バックグラウンドでのレンダリング)を可能にする。 画像処理を行いながら動的にテクスチャを生成したりできる。
CanvasRenderer: 一般的に2Dグラフィックスを描画するときに使用するCanvas2Dで3Dグラフィックスを実現する。WebGLと異なり、CPUで演算を行うため実行速度が遅くなるが、WebGLで実現できることの大半がCanvas2Dでも可能。
SVGRenderer: ベクトル画像を扱うSVGを用いた3Dグラフィックスを実現する。
SoftwareRenderer: すべての計算をGPU側でなくCPU側で行うソフトウェアレンダリングを実現する。 GPUの制限を受けない分柔軟性はあるが、実行速度が遅くなる。
CSS3DRenderer: HTMLの要素とCSS3で3Dグラフィックスを実現する。 three.jsの演算機能でCSS transformを扱うことができ、WebGLが対応していないモバイル端末でも3Dグラフィックスを簡単に実現できる。
var renderer;
canvas = document.getElementById('canvas'); // div要素の取得
renderer = new THREE.WebGLRenderer(); // レンダラーの生成
renderer.setSize(canvas.clientWidth, canvas.clientHeight); // レンダラーのサイズをdivのサイズに設定
renderer.setClearColor(0x000000, 1.0); // レンダラーの背景色を黒色(不透過)に設定
canvas.appendChild(renderer.domElement); // div領域にレンダラーを配置
如何让 Windows 下的 Chrome 支持 WebGL ? https://www.zhihu.com/question/19647275
example大全 http://techbrood.com/threejs/examples/#webgl_helpers
3D Scatter Plot Using three.js http://bl.ocks.org/phil-pedruco/9852362
Load a 3D Model Using the Three.js OBJ Loader https://www.learnthreejs.com/load-3d-model-using-three-js-obj-loader/
轨道控制器OrbitControls.js
js文件所在路径:Three.js下载文件包里的examples\examples\js\controls目录里。
也可以通过npm来安装
npm i three-orbit-controls
轨道控制器OrbitControls.js是一个相当神奇的控件,用它可以实现场景用鼠标交互,让场景动起来,控制场景的旋转、平移,缩放。
const controls = this.controls = new OrbitControls(this.camera)
controls.maxPolarAngle = 1.5
controls.minPolarAngle = 0.5
controls.rotateSpeed = 5.0
controls.zoomSpeed = 5
controls.panSpeed = 2
controls.onZoom = false
controls.noPan = false
controls.staticMoving = true
controls.dynamicDampingFactor = 0.3
controls.minDistance = 10
controls.maxDistance = 800
maxPolarAngle和minPolarAngle可以限制旋转的角度。
当相机旋转的时候更新一下
function animate() {
requestAnimationFrame( animate );
// required if controls.enableDamping or controls.autoRotate are set to true
controls.update();
renderer.render( scene, camera );
}
加载3d模型
首先,先装一个引人模型的loader
npm i three-obj-loader
把一个.obj格式的3d模型加载进来就好了
const loader = new THREE.OBJLoader()
loader.load('assets/chair.obj', obj => {
obj.traverse(child=> {
if (child instanceof Mesh) {
child.material.side = THREE.DoubleSide
this.scene.add(obj)
}
})
})
把模型加载进来后要添加到场景中(this.scene.add(obj))
进行到这一步就差不多完成了,还差最后一步,实现模型随着手指的移动而转动,原理其实很简单,改变相机的位置就可以了,这里我们用orbitControl库实现。 https://www.yanshuo.me/p/115491
材料(Materials) http://techbrood.com/threejs/docs/#参考手册/材料(Materials)/基础线条材料(LineBasicMaterial)
加入网格 使用GridHelper
var size = 10;
var step = 1;
var gridHelper = new THREE.GridHelper( size, step );
scene.add( gridHelper );
three.js の座標軸を AxisHelper で表示する
普通、数学だと z 軸が高さですが、three.js では y 軸が高さなっています。
<html>
<head>
<script type="text/javascript" src="libs/three.min.js"></script>
<script type="text/javascript" src="libs/OrbitControls.js"></script>
// カメラの移動に OrbitControls を使っています。
</head>
<body>
<div id="WebGL-area"></div>
<script type="text/javascript">
function init() {
var scene = new THREE.Scene();
// 座標軸を表示
var axes = new THREE.AxisHelper(25);
scene.add(axes);
// 物体
var sphere = new THREE.Mesh(new THREE.SphereGeometry(2), new THREE.MeshBasicMaterial({color: 0xff00ff, wireframe : true}));
sphere.position.set(5, 10, 15);
scene.add(sphere);
var camera = new THREE.PerspectiveCamera(45, 1.5, 0.1, 1000);
camera.position.set(30, 45, 30);
camera.lookAt(scene.position);
var controls = new THREE.OrbitControls(camera);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(300, 200);
document.getElementById("WebGL-area").appendChild(renderer.domElement);
render();
function render() {
controls.update();
requestAnimationFrame(render);
renderer.render(scene, camera);
}
}
window.onload = init
</script>
</body>
</html>
效果图:
动画实现
APP.animate = function() {
APP.cube.rotation.x = APP.cube.rotation.x + 0.01;
APP.cube.rotation.y = APP.cube.rotation.y + 0.01;
APP.renderer.render(APP.scene, APP.camera);
window.requestAnimationFrame( APP.animate );
}
three.js meshのグループ化 複数meshを同時に動かしたい時とか
var boxes = new THREE.Group();
// 先ほどのboxをグループに追加
boxes.add(box);
boxes.add(box2);
// sceneに追加
scene.add(boxes);
cube.material.color.setHex( 0xffffff );
Scene
var cube = new THREE.Mesh(Geometryを設定,Materialを設定);
cube.name = 'cube-1'
scene.add(cube);
THREE.Scene.getObjectName('cube-1');
更换mesh的颜色
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
var index = 0;
function animate() {
requestAnimationFrame( animate );
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
//cube.color=Three.color(0xff00ff);
if(index >= 200 ){
////在这里进行颜色变换处理
material = new THREE.MeshBasicMaterial( { color: 0x00ffff } );
cube.material = material;
}
index ++;
renderer.render( scene, camera );
}
animate();
動畫實現: 數據移動軌跡圖
// global variables
var renderer;
var scene;
var camera;
var cameraControl;
var geometry;
var material;
var plotMesh;
var dataplot;
var plot;
function init() {
// create a scene, that will hold all our elements such as objects, cameras and lights.
scene = new THREE.Scene();
// create a camera, which defines where we're looking at.
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(200, 0, 75);
// create a render, sets the background color and the size
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xffffff, 1.0);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
// add controls
cameraControl = new THREE.OrbitControls(camera);
// Scatter plot
scatterPlot = new THREE.Object3D();
scene.add(scatterPlot);
// Make grid
xzColor = 'red';
xyColor = '0x33CCFF';
yzColor = 'yellow';
var colorSet = d3.scale.linear().domain([0,5]).range(["red", "yellow"]).interpolate(d3.interpolateLab);
console.log(colorSet(0));
var gridXZ = new THREE.GridHelper(600, 10, "red", "black");
gridXZ.position.set(0, 00, 0);
scatterPlot.add(gridXZ);
/*
var gridXY = new THREE.GridHelper(600, 50);
gridXY.position.set(0, 0, 00);
gridXY.rotation.x = Math.PI / 2;
gridXY.setColors(new THREE.Color(xyColor), new THREE.Color(xyColor));
scatterPlot.add(gridXY);
var gridYZ = new THREE.GridHelper(600, 50);
gridYZ.position.set(00, 0, 0);
gridYZ.rotation.z = Math.PI / 2;
gridYZ.setColors(new THREE.Color(yzColor), new THREE.Color(yzColor));
scatterPlot.add(gridYZ);
*/
// Make Plot
geometry = new THREE.SphereGeometry(5, 50, 50);
material = new THREE.MeshNormalMaterial();
plotMesh = new THREE.Mesh(geometry, material);
plotMesh.name = 'plot';
scene.add(plotMesh);
// 位置設定
plotMesh.position.set(0,0,0);
plot = [i];
for (var i = 0; i < 100; i++) {
var vertex = new THREE.Vector3();
var max = 500;
var min = -500;
vertex.x = Math.random() * (max - min) + min;
vertex.y = Math.random() * (max - min) + min;
vertex.z = Math.random() * (max - min) + min;
geometry.vertices.push(vertex);
}
dataplot = new THREE.Mesh(geometry, material);
scatterPlot.add(dataplot);
//document.body.appendChild(renderer.domElement);
document.getElementById("container-3d").appendChild( renderer.domElement );
var index = 0;
var position = [{x: 10, y: 10, z:10}, {x: 50, y: 50, z:50}, {x: 100, y: 50, z:50}, {x: 150, y: 50, z:50}, {x: 210, y: 50, z:50}];
render();
setInterval(function(){
if( index < 5){
// Make Plot
geometry = new THREE.SphereGeometry(5, 50, 50);
material = new THREE.MeshBasicMaterial({color: colorSet(0)});
plotMesh = new THREE.Mesh(geometry, material);
plotMesh.name = 'plot'+ index;
scene.add(plotMesh);
// 位置設定
plotMesh.position.set(position[index]["x"],position[index]["y"],position[index]["z"]);
for(var n=0; n < index; n++)
{
var name = "plot"+ String(n);
var object = scene.getObjectByName(name);
console.log(object);
var col_index = index > n ? (index-n):0;
material = new THREE.MeshBasicMaterial({color: colorSet(col_index)});
object.material = material;
}
//var object = scene.getObjectByName( "plot" );
//material = new THREE.MeshBasicMaterial({color: 0xffff00});
//object.material = material;
}
index ++;
},
1000);
}
function render() {
// update the camera
cameraControl.update();
// and render the scene
renderer.render(scene, camera);
// render using requestAnimationFrame
requestAnimationFrame(render);
}
function handleResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// calls the init function when the window is done loading.
window.onload = init;
// calls the handleResize function when the window is resized
window.addEventListener('resize', handleResize, false);