昔洛 的个人博客

Bug不空,誓不成佛

目录
(二)WebGL Threejs 学习 ----- 点、线、面
/        

(二)WebGL Threejs 学习 ----- 点、线、面

学习内容

  • 点、线、面
  • 点操作
  • 画一条线
  • 右手坐标系
  • 画一个面

点、线、面

3D 世界的组成

在计算机世界里,3D 世界是由点组成,两个点能够组成一条直线,三个不在一条直线上的点能够组成一个三角形面,无数三角形面就能够组成各种形状的物体,如下图:

20130810194940829.gif
通常把这种网格模型叫做 Mesh 模型,也可称为网格体。给物体贴上皮肤,或者专业点就叫做纹理,那么这个物体活现了。最后无数的物体就组成了我们的 3D 世界。

点操作

在 Threejs 中定义一个点

在三维空间中的某一个点可以用一个坐标点来表示。一个坐标点由 x,y,z 三个分量构成。在 three.js 中,点可以在右手坐标系中表示:
空间几何中,点可以用一个向量来表示,在 Three.js 中也是用一个向量来表示的,代码如下:

THREE.Vector3 = function(x,y,z) {
	this.x = x || 0;
	this.y = y || 0;
	this.z = z || 0;
}

    在这段代码中:前面我们已经知道了 THREE 是 Three.js 引擎的一个全局变量。只要你想用它,就可以在任何地方用它。
    那么 THREE.Vector3 呢?就是表示 Vector3 是定义在 THREE 下面的一个类。以后要用 Vector3,就必须要加 THREE 前缀。当然 Three.js 的设计者,也可以不加 THREE 这个前缀,但是他们预见到,Three.js 引擎中会有很多类型,最好给这些类型加一个前缀,以免与开发者的代码产生冲突。
    THREE.Vector3 被赋值为一个函数。这个函数有 3 个参数,分别代表 x 坐标,y 坐标和 z 坐标的分量。函数体内的代码将他们分别赋值给成员变量 x,y,z。如果没有的话应该使用默认值 0。

操作一个点

    在 3D 世界中点可以用 THREE.Vector3D 来表示,假设有一个点 x=4,y=8,z=9。你可以这样定义它:

var point1 = new THREE.Vector3(4,8,9);

也可以使用 set 方法:

var point1 = new THREE.Vector3();
point1.set(4,8,9);

画一条线的步骤

  • 1、声明一个几何体
    var geometry = new THREE.Geometry();
    

    几何体里面有一个 vertices 变量,可以用来存放点。

  • 2、定义一种线条的材质,使用 THREE.LineBasicMaterial 类型来定义,它接受一个集合作为参数,其原型如下:
    LineBasicMaterial( parameters )
    
    • Parameters 是一个定义材质外观的对象,它包含多个属性来定义材质,这些属性是:
      • Color:线条的颜色,用 16 进制来表示,默认的颜色是白色。
      • LineWidth:线条的宽度,默认时候 1 个单位宽度。
      • Linecap:线条两端的外观,默认是圆角端点,当线条较粗的时候才看得出效果,如果线条很细,那几乎看不出效果了。
      • Linejoin:两个线条的连接点处的外观,默认是“round”,表示圆角。
      • VertexColors:定义线条材质是否使用定点颜色,这是一个 boolean 值,意思是,线条各部分的颜色会根据顶点的颜色来进行插值。
      • Fog:定义材质的颜色是否受全局雾效的影响。
      var material = new THREE.LineBasicMaterial({ vertexColors: THREE.VertexColors });
      
  • 3、定义两种颜色,分别表示线条两个端点的颜色,如下所示
    var color1 = new THREE.Color( 0x444444 );
    var color2 = new THREE.Color( 0xFF0000 );
    
  • 4、定义2个顶点的位置,并放到 geometry 中,代码如下:
    var p1 = new THREE.Vector3( -100, 0, 100);
    var p2 = new THREE.Vector3( 100, 0, -100);
    geometry.vertices.push(p1);
    geometry.vertices.push(p2);
    
  • 5、为步骤 4 中定义的 2 个顶点,设置不同的颜色,代码如下:
    geometry.colors.push( color1, color2 );
    

    geometry 中 colors 表示顶点的颜色,必须材质中 vertexColors 等于 THREE.VertexColors 时,颜色才有效,如果 vertexColors 等于 THREE.NoColors 时,颜色就没有效果了。那么就会去取材质中 color 的值。

  • 6、定义一条线
    var line = new THREE.Line( geometry, material, THREE.LinePieces );
    

    第一个参数是几何体 geometry,里面包含了 2 个顶点的顶点的颜色。第二个参数是线条的材质,或者就是线条的属性,表示线条以哪种方式取色。第三个参数是一组点的连接方式。接下来添加到场景中:
    scene.add(line);

补充

  • 在 Threejs 中,一条线由点,材质和颜色组成。
  • 点由 THREE.Vector3 表示,Threejs 中没有提供单独画点的函数,它必须被放到一个 THREE.Geometry 形状中,这个结构中包含一个数组 vertices,这个 vertices 就是存放无数的点 ( THREE.Vector3 )的数组,这个表示可以用下图所示:20130515135032174.png
    为了绘制一条直线,首先需要定义两个点:
    var p1 = new THREE.Vector3( -100, 0, 100);
    var p2 = new THREE.Vector3( 100, 0, -100);
    

    声明一个 THREE.Geometry 并把点加入进去:

    var geometry = new THREE.Geometry();
    geometry.vertices.push(p1);
    geometry.vertices.push(p2);
    

    geometry.vertices能够使用 push 方法,因为其本身就是一个数组,这样 geometry 中就有了 2 个点了。
    然后我们需要给线加一种材质,可以使用专为线准备的材质,THREE.LineBasicMaterial。
    最终通过 THREE.Line 绘制了一条线
    var line = new THREE.Line( geometry, material, THREE.LinePieces );

右手坐标系

Threejs 使用的是右手坐标系,这源于 opengl 默认情况下,也是右手坐标系。下面是右手坐标系的图例2013051513493411.jpg

图中右边那个手对应的坐标系,就是右手坐标系。在 Threejs 中,,坐标系和右边的坐标完全一样。x 轴正方向向右,y 轴正方向向上,z 轴由屏幕从里向外。值得一提的是,计算机的屏幕 y 轴正方向为下,所以一定要清楚的区分两个坐标系的关系。

画一个网格面

思路:画一个网格的坐标,应该找到线的点。把网格虚拟成正方形,在正方形边界上找到几个等分点,用这些点两两连接,就能够画出整个网格来。

  • 定义 2 个点
    在 x 轴上定义两个点 p1(-500, 0, 0),p2(500, 0, 0);
geometry.vertices.push(new THREE.Vector3( -500, 0, 0));
geometry.vertices.push(new THREE.Vector3(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 );
}
希望所有的 Bug 都会报错~
评论
歌名 - 歌手
0:00