Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Three.js #9

Open
rainit2006 opened this issue Jan 31, 2018 · 12 comments
Open

Three.js #9

rainit2006 opened this issue Jan 31, 2018 · 12 comments

Comments

@rainit2006
Copy link
Owner

No description provided.

@rainit2006
Copy link
Owner Author


@rainit2006
Copy link
Owner Author

rainit2006 commented Jan 31, 2018

入门教程


入門
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 锥形几何类;
image
image
Three.js 还提供了很多其他几何类, 详情可以在 Three.js 文档搜索框中输入 Geometry 关键字, 查看 Geometries 下栏目.

  • 光与影
    three.js 中常用的四种光源模型为环境光、平行光、点光源、聚光灯;
    在Three.js中,能形成阴影的光源只有THREE.DirectionalLight与THREE.SpotLight;而相对地,能表现阴影效果的材质只有THREE.LambertMaterial与THREE.PhongMaterial。因而在设置光源和材质的时候,一定要注意这一点;

カメラ

  • Three.jsには4種類カメラがあります。透視投影と正投影です。
  1. 透視投影(PerspectiveCamera)…通常生活における物の見え方と同じ.
  2. 正投影(OrthographicCamera)…物体の見た目の大きさが視点からの距離によらず、変わらない(どこから見ても物体のサイズは同じ).
  3. CubeCamera : 会创建六个PerspectiveCamera,并将这些相机渲染到WebGLRenderTargetCube渲染器中。
  4. StereoCamera: 会创建两个PerspectiveCamera,可用于图像立体显示,呈现视觉立体效果,当带上立体眼镜时,会产生相应的立体效果。

正投影和透视投影的区别是:透视投影有一个基本点,就是远处的物体比近处的物体小。我们看看著名的蒙娜丽莎的微笑就是典型的透视作品。
在工程建筑领域,正投影的例子很多。其特点是,远近高低比例都相同。

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:这个呢,表示你远处的裁面,
image

image
image
image

http://gupuru.hatenablog.jp/entry/2013/11/20/183100

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

@rainit2006
Copy link
Owner Author

rainit2006 commented Jan 31, 2018

@rainit2006
Copy link
Owner Author

rainit2006 commented Feb 1, 2018

轨道控制器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 );
}

@rainit2006
Copy link
Owner Author

加载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

@rainit2006
Copy link
Owner Author

材料(Materials)
http://techbrood.com/threejs/docs/#参考手册/材料(Materials)/基础线条材料(LineBasicMaterial)

  • 基础线条材料(LineBasicMaterial)
  • 虚线材料(LineDashedMaterial)
  • 材料(Material)
  • 基础网孔材料(MeshBasicMaterial)
  • 深度网孔材料(MeshDepthMaterial)
  • 多种材料(MultiMaterial)
  • 兰伯特网孔材料(MeshLambertMaterial)
  • 法向量网孔材料(MeshNormalMaterial)
  • Phong网孔材料(MeshPhongMaterial)
  • 标准网孔材料(MeshStandardMaterial)
  • 点材料(PointsMaterial)
  • 原始着色器材料(RawShaderMaterial)
  • 着色器材料(ShaderMaterial)
  • 精灵材料(SpriteMaterial)

@rainit2006
Copy link
Owner Author

rainit2006 commented Feb 1, 2018

加入网格
使用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>

效果图:
image

@rainit2006
Copy link
Owner Author

动画实现

  1. 利用window.requestAnimationFrame方法
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 );
    }

@rainit2006
Copy link
Owner Author

rainit2006 commented Feb 4, 2018

three.js meshのグループ化
複数meshを同時に動かしたい時とか

var boxes = new THREE.Group();

    // 先ほどのboxをグループに追加
    boxes.add(box);
    boxes.add(box2);

    // sceneに追加
    scene.add(boxes);

  • Changing color of cube in three.js
    cube.material.color.setHex( 0xffffff );

@rainit2006
Copy link
Owner Author

Scene

  • 名前を指定して、シーンから特定のオブジェクトを取得
var cube = new THREE.Mesh(Geometryを設定,Materialを設定);
cube.name = 'cube-1'
scene.add(cube);

THREE.Scene.getObjectName('cube-1');

@rainit2006
Copy link
Owner Author

更换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();

@rainit2006
Copy link
Owner Author

動畫實現: 數據移動軌跡圖

					// 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);



Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant