three.js 入门详解(一)

image

1. 概述

1.1 什么是WebGL?

WebGL是在浏览器中实现三维效果的一套规范
  • 想要使用WebGL原生的API来写3D效果的话,很吃力。three.js是WebGL的一个开源框架,它省去了不少麻烦的细节。

1.2 初识three.js

什么是threejs,很简单,你将它理解成 three+js就能够了。 three表示3D的意思js表示javascript的意思。那么合起来, three.js就是使用 javascript 来写 3D程序的意思。
  • Javascript是运行在网页端的脚本语言,那么毫无疑问Three.js也是运行在浏览器上的。

1.3 前期准备

1.3.1 下载地址

1.3.2 目录结构

image

  • Build目录: 包含两个文件,three.js 和three.min.js 。这是three.js最终被引用的文件。一个已经压缩,一个没有压缩的js文件。
  • Docs目录: 这里是three.js的帮助文档,里面是各个函数的api,惋惜并无详细的解释。试图用这些文档来学会three.js是不可能的。
  • Editor目录: 一个相似3D-max的简单编辑程序,它能建立一些三维物体。
  • Examples目录: 一些颇有趣的例子demo,惋惜没有文档介绍。对图像学理解不深刻的同窗,学习成本很是高。
  • Src目录: 源代码目录,里面是全部源代码。
  • Test目录: 一些测试代码,基本没用。
  • Utils目录: 存放一些脚本,python文件的工具目录。例如将3D-Max格式的模型转换为three.js特有的json模型。
  • .gitignore文件: git工具的过滤规则文件,没有用。
  • CONTRIBUTING.md文件: 一个怎么报bug,怎么得到帮助的说明文档。
  • LICENSE文件: 版权信息。
  • README.md文件: 介绍three.js的一个文件,里面还包含了各个版本的更新内容列表。

1.3.3 配置开发环境

  • 浏览器: 推荐使用高版本的浏览器,谷歌、火狐、360等,对于前端开发者来讲,chrome是不二的选择
  • js 开发工具: VS-code、Webstorm 均可以,为了方便下面的学习,这里使用Webstorm
  • Three.js 调试: 利用谷歌浏览器的调试窗口,使用断点调试的方法

2. 开始使用Three.js

使用Three.js以前,首先在 <head>部分,须要引入外部文件 Three.js
<head>
    <script type="text/javascript" src="three.js"></script>
</head>
WebGL 的渲染是须要HTML5 中的 Canvas元素的,你能够手动在HTML的 <body>部分中使用canvas标签,或者让Three.js帮你生成。这两种选择,通常没有多大差异。咱们先手动定义一个canvas标签:
<body onload="init();">
    <canvas id="canvasId" width="800" height="600"></canvas>
</body>
在js里面定义一个函数,将全部执行的代码放在函数里,在html加载完成后,执行该函数
function init{
    // 全部须要执行的代码
}

一个典型的Three.js程序,至少应该包括四个部分:渲染器(renderer)场景(scene)相机(camera)以及场景中建立的物体javascript

2.1 渲染器(renderer)

渲染器决定了 渲染的结果应该画在 页面的什么元素上面,而且 以怎样的方式来绘制

渲染器将会和canvas元素进行绑定,若是以前<html>标签中,定义了id为canvasId的canvas标签,那么renderer能够这样写:html

var renderer = new THREE.WebGLRenderer({
    canvas : document.getElementById('canvasId');
});
若是想要 Three.js生成Canvas元素的时候,在html中就不须要在定义一个canvas标签了,直接在javascript代码中写道:
var renderer = new THREE.WebGLRenderer();
renderer.setSize = (800,600);
document.body.appendChild(renderer.domElement);
  • 上面的代码setSize是为canvas元素设置宽高,document.body.appendChild(renderer.domElement)是将渲染器对应的Canvas元素添加到body中。
咱们可使用下面的代码(用于清除画面的颜色)将背景色设置为黑色:
renderer.setClearColor(0x000000);

2.2 场景(scene)

在Three.js中 添加物体都是添加到 场景中的,所以它至关于一个大容器。通常说,场景里没有很复杂的操做,只要new一个对象就能够了,而后将物体添加到场景中便可。
var scene = new THREE.Scene();

2.3 照相机(camera)

在介绍照相机以前,咱们先来介绍一下坐标系。
  • three.js中使用的是右手坐标系,X轴水平向右,y轴垂直向上,Z轴的方向就是屏幕由里往外的方向

image

这里咱们定义一个 透视相机(相机也须要添加到场景中):
var camera = new THREE.PerspectiveCamera(45, 4 / 3, 1, 1000);
// 设置相机的位置
camera.position.set(0,0,5);
// 将相机添加到场景中
scene.add(camera);

2.4 建立一个物体

这里咱们先介绍一个长方体,建立一个x、y、z方向长度分别为一、二、3的长方体,并设置为红色。
var geometry = new THREE.CubeGeometry(1,2,3);
var material = new THREE.MeshBasicMaterial({
    color: 0xff0000;
});
var cube = new THREE.Mesh(geometry,material);
scene.add(cube);
  • new THREE.CubeGeometry(); 表示调用一个几何体前端

    • Cube : 立方体 Geometry : 几何;
    • CubeGeometry是一个正方体或者长方体,到底是什么,由它的3个参数所决定
CubeGeometry(width, height, depth, segmentsWidth, segmentsHeight, segmentsDepth, materials, sides)
width:立方体x轴的长度

height:立方体y轴的长度

depth:立方体z轴的深度,也就是长度

想想你们就明白,以上3个参数就可以肯定一个立方体。

剩下的几个参数就要费解和复杂一些了,不事后面咱们会本身来写一个立方体,到时候,你会更明白这些参数的意义,这里你能够将这些参数省略。
  • new THREE.MeshBasicMaterial(); 表示的是物体的材质java

    • 你能够在里面设置物体的颜色
var material = new THREE.MeshBasicMaterial({
    color: 0xff0000;
});
  • 必定不要忘了,将物体添加到场景

2.5 渲染

在定义了场景中的物体,设置好的照相机以后,渲染器就知道如何渲染出二维的结果了。这时候,咱们只须要调用渲染器的渲染函数,就能使其渲染一次了。
renderer.render(scene, camera);

2.6 完整代码

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>长方体</title>
    <script src="three.js"></script>
</head>

<body onload="init();">
    <script>
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            // canvas元素设置宽高
            renderer.setSize = (800, 600);
            // 渲染器对应的Canvas元素添加到<body>中。
            document.body.appendChild(renderer.domElement);
            // 清除画面的颜色
            renderer.setClearColor(0x000000);

            // 场景
            var scene = new THREE.Scene();

            // 相机
            // 定义一个透视相机
            var camera = new THREE.PerspectiveCamera(45, 4 / 3, 1, 1000);
            // 设定相机的位置
            camera.position.set(0, 0, 5);
            // 将相机添加到场景中
            scene.add(camera);

            // 物体
            var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3), new THREE.MeshBasicMaterial({
                color: 0xff0000
            }));
            scene.add(cube);

            // 渲染
            renderer.render(scene, camera);
        }
    </script>
</body>
</html>
  • 效果图

image
canvas元素的默认宽高为300/150python

3. Three.js功能概览

下面介绍下Three.js官网文档中的一些重要的对象,在你须要寻求帮助时,就可以知道关键词是什么。
  • Cameras(照相机,控制投影方式)git

    • Camera
    • OrthographicCamera
    • PerspectiveCamera
  • Core(核心对象)程序员

    • BufferGeometry
    • Clock(用来记录时间)
    • EventDispatcher
    • Face3
    • Face4
    • Geometry
    • Object3D
    • Projector
    • Raycaster(计算鼠标拾取物体时颇有用的对象)
  • Lights(光照)github

    • Light
    • AmbientLight
    • AreaLight
    • DirectionalLight
    • HemisphereLight
    • PointLight
    • SpotLight
  • Loaders(加载器,用来加载特定文件)web

    • Loader
    • BinaryLoader
    • GeometryLoader
    • ImageLoader
    • JSONLoader
    • LoadingMonitor
    • SceneLoader
    • TextureLoader
  • Materials(材质,控制物体的颜色、纹理等)算法

    • Material
    • LineBasicMaterial
    • LineDashedMaterial
    • MeshBasicMaterial
    • MeshDepthMaterial
    • MeshFaceMaterial
    • MeshLambertMaterial
    • MeshNormalMaterial
    • MeshPhongMaterial
    • ParticleBasicMaterial
    • ParticleCanvasMaterial
    • ParticleDOMMaterial
    • ShaderMaterial
    • SpriteMaterial
  • Math(和数学相关的对象)

    • Box2
    • Box3
    • Color
    • Frustum
    • Math
    • Matrix3
    • Matrix4
    • Plane
    • Quaternion
    • Ray
    • Sphere
    • Spline
    • Triangle
    • Vector2
    • Vector3
    • Vector4
  • Objects(物体)

    • Bone
    • Line
    • LOD
    • Mesh(网格,最经常使用的物体)
    • MorphAnimMesh
    • Particle
    • ParticleSystem
    • Ribbon
    • SkinnedMesh
    • Sprite
  • Renderers(渲染器,能够渲染到不一样对象上)

    • CanvasRenderer
    • WebGLRenderer(使用WebGL渲染,这是本书中最经常使用的方式)
    • WebGLRenderTarget
    • WebGLRenderTargetCube
    • WebGLShaders(着色器,在最后一章做介绍)
  • Renderers / Renderables

    • RenderableFace3
    • RenderableFace4
    • RenderableLine
    • RenderableObject
    • RenderableParticle
    • RenderableVertex
  • Scenes(场景)

    • Fog
    • FogExp2
    • Scene
  • Textures(纹理)

    • CompressedTexture
    • DataTexture
    • Texture
  • Extras

    • FontUtils
    • GeometryUtils
    • ImageUtils
    • SceneUtils
  • Extras / Animation

    • Animation
    • AnimationHandler
    • AnimationMorphTarget
    • KeyFrameAnimation
  • Extras / Cameras

    • CombinedCamera
    • CubeCamera
  • Extras / Core

    • Curve
    • CurvePath
    • Gyroscope
    • Path
    • Shape
  • Extras / Geometries(几何形状)

    • CircleGeometry
    • ConvexGeometry
    • CubeGeometry
    • CylinderGeometry
    • ExtrudeGeometry
    • IcosahedronGeometry
    • LatheGeometry
    • OctahedronGeometry
    • ParametricGeometry
    • PlaneGeometry
    • PolyhedronGeometry
    • ShapeGeometry
    • SphereGeometry
    • TetrahedronGeometry
    • TextGeometry
    • TorusGeometry
    • TorusKnotGeometry
    • TubeGeometry
  • Extras / Helpers

    • ArrowHelper
    • AxisHelper
    • CameraHelper
    • DirectionalLightHelper
    • HemisphereLightHelper
    • PointLightHelper
    • SpotLightHelper
  • Extras / Objects

    • ImmediateRenderObject
    • LensFlare
    • MorphBlendMesh
  • Extras / Renderers / Plugins

    • DepthPassPlugin
    • LensFlarePlugin
    • ShadowMapPlugin
    • SpritePlugin
  • Extras / Shaders

    • ShaderFlares
    • ShaderSprite

咱们看到,Three.js功能是十分丰富的,一时间想所有掌握有些困难。在接下来的章节中,咱们将会先详细介绍照相机、几何形状、材质、物体等入门级知识;而后介绍使用动画、模型导入、加入光照等功能;最后,对于学有余力的读者,咱们将介绍着色器,用于更高级的图形渲染。

4. 照相机

本章将介绍照相机的概念,以及如何使用Three.js设置相应的参数。

4.1 什么是照相机?

在图形学中,照相机可没有生活中的照相机那么简单
  • 咱们使用的Three.js建立的场景是三维的,而一般状况下显示器是二维的,那么三维的场景怎么在二维的显示器上显示呢?照相机就是一个抽象,它定义了三维空间到二维屏幕投影的方式,用“照相机”这样一个类比,可使咱们直观地理解这一投影方式。
  • 而针对投影方式的不一样,照相机又分为正交投影照相机透视投影照相机。咱们须要为本身的程序选择合适的照相机。这二者分别是什么,以及二者有何差别,咱们将在下节中做介绍。

4.2 正交投影和透视投影

举个简单的例子来讲明正交投影与透视投影照相机的区别。使用 透视投影照相机得到的结果是 相似人眼在真实世界中看到的有“近大远小”的效果(以下图中的(a));而使用 正交投影照相机得到的结果就像咱们在数学几何学课上老师教咱们画的效果,对于 三维空间内平行的线,投影到 二维空间中也必定是平行的(以下图中的(b))。

image

通常说来,对于制图、建模软一般使正交投影,这样不会由于投影而改变物体比例;而对于其余大多数应用,一般使用 透视投影,由于这更接近人眼的观察效果。固然,照相机的选择并无对错之分,你能够更具应用的特性,选择一个效果更佳的照相机。

4.3 正交投影照相机

4.3.1 参数介绍

正交投影照相机( Orthographic Camera)
THREE.OrthographicCamera(left, right, top, bottom, near, far)
这六个参数分别表明正交投影照相机拍摄到的空间的六个面的位置,这六个面围成一个长方体,咱们称其 视景体(Frustum)。只有在视景体内部(下图中的灰色部分)的物体才可能显示在屏幕上,而视景体外的物体会在显示以前被裁减掉。

image

为了保持照相机的横竖比例,须要保证 (right - left)与(top - bottom)的比例与 Canvas宽度与高度的比例(800/600)一致。
// [2-(-2)] / [1.5-(-1.5)] = canvas.width/canvas.height
var camera = new THREE.OrthographicCamera(-2, 2, 1.5, -1.5, 1, 10) // left right top bottom near far

near与far都是指到照相机位置在深度平面的位置,而照相机不该该拍摄到其后方的物体,所以这两个值应该均为正值。为了保证场景中的物体不会由于太近或太远而被照相机忽略,通常near的值设置得较小far的值设置得较大,具体值视场景中物体的位置等决定。

4.3.2 示例代码

下面咱们经过一个具体的例子来了解正交投影照相机的设置

基本设置

  • 设置照相机:
var camera = new THREE.OrthographicCamera(-2, 2, 1.5, -1.5, 1, 10);
camera.poaition.set(0,0,5);
scene.add(camera);
  • 在原点处建立一个边长为1的正方体,为了和透视效果作对比,这里咱们使用wireframe而不是实心的材质,以便看到正方体后方的边:
var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1), 
    new THREE.MeshBasicMaterial({
        color: 0xff0000,
        wireframe: true
    })
);
scene.add(cube);
  • 效果图:

image

  • 咱们看到正交投影的结果是一个正方形,后面的边与前面彻底重合了,这也就是正交投影与透视投影的区别所在。

长宽比例

这里,咱们的Canvas宽度是800px,高度是600px,照相机水平方向距离4,垂直方向距离3,所以长宽比例保持不变。为了试验长宽比例变化时的效果,咱们将照相机水平方向的距离减少为2(right-left = 2):
var camera = new THREE.OrthographicCamera(-1, 1, 1.5, -1.5, 1, 10);
  • 效果图(此时水平方向的距离就被拉长了):

image

照相机位置

接下来,咱们来看看照相机位置对渲染结果的影响。在以前的例子中,咱们将照相机设置在(0, 0, 5)位置,而因为照相机默认是 面向z轴负方向放置的,因此能看到在原点处的正方体。如今,若是咱们将照相机 向右移动1个单位:
var camera = new THREE.OrthographicCamera(-2, 2, 1.5, -1.5, 1, 10);
// 向右移动一个单位的位置
camera.position.set(1, 0, 5);
  • 效果图(物体看上去向左移动了)

image

  • 其实照相机就比如人的眼睛,当咱们身体往右移动的时候,看到的物体就好像向左移了。
正交投影摄像机在设置时,是否须要保证 left 和 right 互为相反数呢?
  • 下面,咱们将本来的参数(-2, 2, 1.5, -1.5, 1, 10)改成(-1, 1, 1.5, -1.5, 1, 10),即,将视景体设置得更靠右:
var camera = new THREE.OrthographicCamera(-1, 3, 1.5, -1.5, 1, 10);
camera.position.set(0, 0, 5);
  • 效果图(与以前相机向右的效果是同样的)

image

换个角度

到目前为止,咱们使用照相机,都是 沿着Z轴负方向观察的,所以看到的都是一个正方形,如今咱们尝试一下 仰望这个正方体,改变照相机的位置:
// x轴:4;  y轴:-3;  z轴:5
camera.position.set(4, -3, 5);
照相机默认是沿着z轴的负方向观察的,所以观察不到正方体,只看到一片黑。咱们能够经过 lookAt函数指定它 看着原点方向

image

camera.lookAt(new THREE.Vector3(0, 0, 0));
  • 效果图:

image

  • 注意:lookAt函数接收的是一个THREE.Vector3的实例千万不能写成camera.lookAt(0,0,0)

4.4 透视投影照相机

4.4.1 参数介绍

透视投影照相机( Perspective Camera)
THREE.PerspectiveCamera(fov, aspect, near, far)
让咱们经过一张透视照相机投影的图来了解这些参数。

image

  • 透视图中,灰色的部分是视景体,是可能被渲染的物体所在的区域。fov是视景体竖直方向上张角(是角度制而非弧度制),如侧视图所示。
  • aspect等于width / height,是照相机水平方向和竖直方向长度的比值,一般设为Canvas的横纵比例
  • near和far分别是照相机到视景体 最近、最远的距离,均为正值,且far应大于near

4.4.2 示例代码

下面咱们经过一个例子来学习透视投影照相机

基本设置

  • 设置透视投影照相机,这里Canvas长800px,宽600px,因此aspect设为800 / 600
var camera = new THREE.PerspectiveCamera(45, 800 / 600, 1, 10);
camera.position.set(0, 0, 5);
scene.add(camera);
  • 设置一个在原点处的边长为1的正方体:
var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1),
        new THREE.MeshBasicMaterial({
            color: 0xff0000,
            wireframe: true
        })
);
scene.add(cube);
  • 效果图:

image

  • 对比正交透视照相机下正方形的效果,透视投影能够看到所有的12条边,并且有近大远小的效果,这也就是与正交投影的区别。

竖直张角

  • 接下来,咱们来看下fov的改变对渲染效果的影响。咱们将原来的45改成60
var camera = new THREE.PerspectiveCamera(60, 800 / 600, 1, 10);
camera.position.set(0, 0, 5);
scene.add(camera);
  • 效果图:

image

  • 为何正方体显得更小了呢?咱们从下面的侧视图来看,虽然正方体的实际大小并未改变,可是将照相机的竖直张角设置得更大时,视景体变大了,于是正方体相对于整个视景体的大小就变小了,看起来正方形就显得变小了。

image

  • 注意,改变fov不会起画面横竖比例的变化,而改变aspect改变横竖比例。

5. 点、线、面

5.1 3D世界的组成

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

image

  • 咱们一般把这种网络模型叫作Mesh模型。给物体贴上皮肤,或者专业点就叫作纹理,那么这个物体就活灵活现了。最后无数的物体就组成了咱们的3D世界。

5.2 在Three.js中定义一个点

在三维空间中的某一个点能够用一个坐标点来表示。一个坐标点由 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。看看上面的代码,中间使用了一个“||”(或)运算符,就是当x=null或者undefine时,this.x的值应该取0

5.3 点的操做

在3D世界中 能够用 THREE.Vector3D来表示。
  • 如今来看看怎么定义个点,假设有一个点x=4,y=8,z=9。你能够这样定义它:
var point1 = new THREE.Vecotr3(4,8,9);
  • 另外你也可使用set方法,代码以下:
var point1 = new THREE.Vector3();

point1.set(4,8,9);

5.4 绘制一条线段

两个不重合的点可以决定一条直线。在three.js中,也能够经过定义两个点,来画一条直线。
  • 一、首先,声明一个几何体geometry
  • 几何体里面有个vertices变量,能够用来存放点
var geometry = new THREE.Geometry();
// 几何体里面有个vertices变量,能够用来存放点
  • 二、定义一种线条的材质,使用THREE.LineBasicMaterial类型来定义,它接受一个集合做为参数,其原型以下:
THREE.LineBasicMaterial(parameters);
  • parameters 是定义材质外观的对象,它包含多个属性来定义材质,这些属性是:

    • Color 线条的颜色,用16进制表示,默认都是白色
    • Linewidth 线条的宽度,默认是1个单位宽度
    • Linecap 线条两端的外观,默认是圆角端点,当线条较粗的时候才能看到效果
    • Linejoin 两个线条的链接点处的外观,默认是“round”,表示圆角。
    • VertexColors 定义线条材质是否使用顶点颜色,这是一个boolean值。意思是,线条各部分的颜色会根据顶点的颜色来进行插值。
    • Fog 定义材质的颜色是否受全局雾效的影响。
  • 咱们这里使用了顶点颜色 vertexColors: THREE.VertexColors,就是线条的颜色会根据顶点来计算。
var material = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors } );
  • 注意: 关于线宽的坑,WebGLRender渲染方式是不之持绘制线宽的,要想支持,须要将渲染方式设置为CanvasRenderer
  • 三、接下来,定义两种颜色,分别表示线条两个端点的颜色,
var color1 = new THREE.Color( 0x444444 ),
    color2 = new THREE.Color( 0xFF0000 );
  • 四、定义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);
  • 五、为4中定义的2个顶点,设置不一样的颜色,代码以下所示:
geometry.colors.push( color1, color2 );
  • geometry中colors表示顶点的颜色,必须材质中vertexColors等于THREE.VertexColors时,颜色才有效,若是vertexColors等于THREE.NoColors时,颜色就没有效果了。那么就会去取材质中color的值,这个很重要。
  • 六、定义一条线。
  • 定义线条,使用THREE.Line类,代码以下所示:
var line = new THREE.Line( geometry, material, THREE.LinePieces );
  • 第一个参数是几何体geometry,里面包含了2个顶点和顶点的颜色
  • 第二个参数是线条的材质,或者是线条的属性,表示线条以哪一种方式取色。
  • 第三个参数是一组点的链接方式。
  • 七、而后,将这条线加入到场景中,代码以下:
scene.add(line);
  • 八、总体代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>

<head>
    <script type="text/javascript" src="three.js"></script>

    <script type="text/javascript">
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            // 设定渲染器尺寸
            renderer.setSize(800, 600);
            // 添加到dom
            document.body.appendChild(renderer.domElement);
            // 重绘时颜色
            renderer.setClearColor(0xffffff);

            // 场景
            var scene = new THREE.Scene();

            // 相机
            var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
            // 设定相机位置
            camera.position.set(0, -25, 0);
            // 相机看向
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);

            // 定义一个物体
            // new 一个模型
            var geometry = new THREE.Geometry();
            // 定义模型的类型是线段  而且设置其材质
            var material = new THREE.LineBasicMaterial({
                // 使用顶点颜色
                vertexColors: true
            });
            // 定义两个颜色
            var color1 = new THREE.Color(0x444444),
                color2 = new THREE.Color(0xff0000);

            // 新建两个点
            var p1 = new THREE.Vector3(-1, 0, 1);
            var p2 = new THREE.Vector3(1, 0, -1);

            // 将新建的两个点添加到几何体中
            geometry.vertices.push(p1);
            geometry.vertices.push(p2);

            // 将两个颜色添加到几何体中
            geometry.colors.push(color1, color2);

            // new 一条线
            var line = new THREE.Line(geometry, material, THREE.LinePieces);
            scene.add(line);

            // 渲染
            renderer.render(scene, camera);

        }
    </script>
</head>

<body onload="init()">

</body>

</html>
  • 效果图:

image

5.5 线条的深度理解

在Threejs中,一条线由点,材质和颜色组成。
  • 点由THREE.Vector3表示,Threejs中没有提供单独画点的函数,它必须被放到一个THREE.Geometry形状中,这个结构中包含一个数组vertices,这个vertices就是存放无数的点(THREE.Vector3)的数组
  • 一、为了绘制一条直线,首先咱们须要定义两个点
var p1 = new THREE.Vector3( -1, 0, 1 );
var p2 = new THREE.Vector3( 1, 0, -1 );
  • 二、声明一个THREE.Geometry,并把点加进去
var geometry = new THREE.Geometry();
geometry.vertices.push(p1);
geometry.vertices.push(p2);
  • geometry.vertices的可以使用push方法,是由于geometry.vertices是一个数组。这样geometry中就有了2个点了。
  • 三、而后咱们须要给线加一种材质,THREE.LineBasicMaterial
var material = new THREE.LineBasicMaterial();
  • 四、最终咱们经过THREE.Line绘制了一条线:
var line = new THREE.Line( geometry, material, THREE.LinePieces );

5.6 绘制网格线

咱们要画一个网格的坐标,那么咱们就应该找到线的点。把网格虚拟成正方形,在正方形边界上找到几个等分点,用这些点两两链接,就可以画出整个网格来。
  • 一、定义两个点
// 在x轴上定义两个点p1(-500,0,0),p2(500,0,0)。
geometry.vertices.push( new THREE.Vector3( - 500, 0, 0 ));
geometry.vertices.push( 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 );

}
  • 三、完整代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>

<head>
    <script type="text/javascript" src="three.js"></script>

    <script type="text/javascript">
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            // 设定渲染器尺寸
            renderer.setSize(800, 600);
            // 添加到dom
            document.body.appendChild(renderer.domElement);
            // 重绘时颜色
            renderer.setClearColor(0x000000);

            // 场景
            var scene = new THREE.Scene();

            // 相机
            var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
            // 设定相机位置
            camera.position.set(0, -25, 0);
            // 相机看向
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);

            // 定义一个几何体
            var geometry = new THREE.Geometry();
            geometry.vertices.push(new THREE.Vector3(-2, 0, 0));
            geometry.vertices.push(new THREE.Vector3(2, 0, 0));
            // for循环出来六条线段
            for (var i = 0; i <= 5; i++) {
                // 定义竖着的线段
                var line = new THREE.Line(geometry, new THREE.LineBasicMaterial({
                    color: 0xffffff,
                }));
                // 每条线段之间的间隔为0.8,-2是为了达到田字格的效果
                line.position.z = (i * 0.8) - 2;
                scene.add(line);

                // 定义横着的线段
                var line = new THREE.Line(geometry, new THREE.LineBasicMaterial({
                    color: 0xffffff,
                    opacity: 0.2
                }));
                line.position.x = (i * 0.8) - 2;
                line.rotation.y = 90 * Math.PI / 180;
                scene.add(line);

                // 渲染
                renderer.render(scene, camera);

            }
        }
    </script>
</head>

<body onload="init()">

</body>

</html>
  • 效果图:

image

6. 几何形状

在建立物体时,须要传入两个参数,一个是 几何形状(Geometry),另外一个是 材质(Material),这一章将着重介绍几何形状的建立,第6章介绍材质,第7章介绍如何使用二者建立网格。
  • 几何形状(Geometry)最主要的功能是储存了一个物体的顶点信息。WebGL须要程序员指定每一个顶点的位置,而在Three.js中,能够经过指定一些特征来建立几何形状,例如使用半径建立一个球体,从而省去程序员一个个指定顶点的工做量。
  • 本章节将分别介绍立方体、平面、球体、圆柱体、四面体、八面体等几何形状,以及以三维文字做为几何形状的方法。本节还会介绍经过手动定义 顶点位置面片信息组成几何形状。

6.1 基本几何形状

6.1.1 立方体

虽然这形状的名字叫作立方体( CubeGeometry),但实际上是长方体,也就是长宽高能够设置不一样的值:
new THREE.CubeGeometry(width, height, depth, widthSegments, heightSegments, depthSegments)
  • 这里,widthx方向上的长度;heighty方向上的长度;depthz方向上的长度;后三个参数分别是在三个方向上的分段数,如widthSegments为3的话,表明x方向上水平分为三份。通常状况下不须要分段的话,能够不设置后三个参数,后三个参数的缺省值为1。其余几何形状中的分段也是相似的,下面不作说明。

长宽高

  • 建立立方体直观简单,如:new THREE.CubeGeometry(1, 2, 3);能够建立一个x方向长度为1,y方向长度为2,z方向长度为3的立方体。
// 调用渲染器
var renderer = new THREE.WebGLRenderer();
renderer.setSize(800, 600);
document.body.appendChild(renderer.domElement);
renderer.setClearColor(0x000000);

// 调用场景
var scene = new THREE.Scene();

// 调用相机
var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
camera.position.set(25, 25, 25);
camera.lookAt(new THREE.Vector3(0, 0, 0));
scene.add(camera);

// 新建一个几何体(长方体)
var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3), new THREE.MeshBasicMaterial({
    color: 0xffff00,
    wireframe: true
}));

scene.add(cube);
  • 为了更好地表现参数效果,咱们在场景中用长度为3红、绿、蓝线段分别表示x、y、z三个轴(这里不须要深究,后面会详细介绍):
// 封装一个坐标系函数
function drawAxes(scene) {
    // x-axis
    var xGeo = new THREE.Geometry();
    xGeo.vertices.push(new THREE.Vector3(0, 0, 0));
    xGeo.vertices.push(new THREE.Vector3(3, 0, 0));
    var xMat = new THREE.LineBasicMaterial({
        color: 0xff0000
    });
    var xAxis = new THREE.Line(xGeo, xMat);
    scene.add(xAxis);

    // y-axis
    var yGeo = new THREE.Geometry();
    yGeo.vertices.push(new THREE.Vector3(0, 0, 0));
    yGeo.vertices.push(new THREE.Vector3(0, 3, 0));
    var yMat = new THREE.LineBasicMaterial({
        color: 0x00ff00
    });
    var yAxis = new THREE.Line(yGeo, yMat);
    scene.add(yAxis);

    // z-axis
    var zGeo = new THREE.Geometry();
    zGeo.vertices.push(new THREE.Vector3(0, 0, 0));
    zGeo.vertices.push(new THREE.Vector3(0, 0, 3));
    var zMat = new THREE.LineBasicMaterial({
        color: 0x00ccff
    });
    var zAxis = new THREE.Line(zGeo, zMat);
    scene.add(zAxis);
}

// 在init 函数里调用这个函数 便可在屏幕上显示一个坐标系了
drawAxes(scene);
  • 在设置材质,并添加到场景以后具体的效果是:

image

  • 物体的默认位置原点,对于立方体而言,是其几何中心在原点的位置。

分段

  • 根据THREE.CubeGeometry(width, height, depth, widthSegments, heightSegments, depthSegments),的后三个参数,为这个长方体分段:
// x轴分两段  y轴分两段 z轴分三段
new THREE.CubeGeometry(1, 2, 3, 2, 2, 3)
  • 效果图:

image

  • 注意这个分段是对六个面进行分段,而不是对立方体的体素分段,所以在立方体的中间是不分段的,只有六个侧面被分段。

6.1.2 平面

这里的平面( PlaneGeometry)实际上是一个长方形,而并不是是数学意义上无限大的平面:
new THREE.PlaneGeometry(width, height, widthSegments, heightSegments)
  • 其中,widthx方向上的长度;heighty方向上的长度;后两个参数一样表示分段
  • new THREE.PlaneGeometry(2, 4);建立的平面在x轴和y轴所在平面内:
var plane = new THREE.Mesh(
    new THREE.PlaneGeometry(2, 4), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(plane);
  • 效果图:

image

  • 若是须要建立的平面在x轴和z轴所在的平面内,能够经过物体的旋转来实现,具体的作法将在下面章节介绍到。

6.1.3 球体

球体( SphereGeometry)的构造函数是:
new THREE.SphereGeometry(radius, segmentsWidth, segmentsHeight, phiStart, phiLength, thetaStart, thetaLength)
  • 其中,radius半径segmentsWidth表示经度上的切片数segmentsHeight表示纬度上的切片数phiStart表示经度开始的弧度phiLength表示经度跨过的弧度thetaStart表示纬度开始的弧度thetaLength表示纬度跨过的弧度

分段

  • 首先,咱们来理解下segmentsWidthsegmentsHeight。使用var sphere = new THREE.SphereGeometry(2, 8, 6)能够建立一个半径为2经度划分红8份,纬度划分红6份的球体
var sphere = new THREE.Mesh(
    new THREE.SphereGeometry(2, 8, 6), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(sphere);
  • 效果图:

image

  • new THREE.SphereGeometry(2, 8, 16)的效果如图:

image

  • new THREE.SphereGeometry(3, 18, 12)的效果如图:

image

  • segmentsWidth至关于经度被切成了几瓣,而segmentsHeight至关于纬度被切成了几层。由于在图形底层的实现中,并没有曲线的概念,曲线都是由多个折线近似构成的。对于球体而言,当这两个值较大的时候,造成的多面体就能够近似看作是球体了。

经度弧度

  • new THREE.SphereGeometry(2, 8, 6, Math.PI / 2, Math.PI / 3)表示起始经度为Math.PI / 6,经度跨度为Math.PI / 3
var sphere = new THREE.Mesh(
    new THREE.SphereGeometry(2, 8, 6, Math.PI / 2, Math.PI / 3), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(sphere);
  • 效果图:

image

  • 值得注意的是,这里的SegmentsWidth8意味着对于经度从Math.PI / 2跨过Math.PI / 3区域内划分为8块,而不是整个球体的经度划分红8块后再判断在此经度范围内的部分。

纬度弧度

  • 理解了经度以后,纬度能够同理理解。new THREE.SphereGeometry(2, 8, 6, 0, Math.PI * 2, Math.PI / 6, Math.PI / 3)意味着纬度从Math.PI / 6跨过Math.PI / 3
var sphere = new THREE.Mesh(
    // 经度起始弧度为0度,经度跨度为 180*2
    new THREE.SphereGeometry(2, 8, 6, 0, Math.PI * 2, Math.PI / 6, Math.PI / 3), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(sphere);
  • 效果图:

image

  • 咱们再来看一个经度纬度都改变了起始位置和跨度的例子:new THREE.SphereGeometry(2, 8, 6, Math.PI / 2, Math.PI, Math.PI / 6, Math.PI / 2)
var sphere = new THREE.Mesh(
    new THREE.SphereGeometry(2, 8, 6, Math.PI / 2, Math.PI, Math.PI / 6, Math.PI / 2), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(sphere);
  • 效果图:

image

6.1.4 圆形

圆形( CircleGeometry)能够建立 圆形或者扇形,其构造函数是:
new THREE.CircleGeometry(radius, segments, thetaStart, thetaLength)
  • 这里的参数跟绘制圆是同样的,咱们再来熟悉一下。radius是半径;segments表示切片数;thetaStart表示纬度开始的弧度thetaLength表示纬度跨过的弧度
  • 看个例子: new THREE.CircleGeometry(3, 18, Math.PI / 3, Math.PI / 3 * 4)能够建立一个在x轴和y轴所在平面的三分之二圆的扇形:
var circle = new THREE.Mesh(
    new THREE.CircleGeometry(2, 18, Math.PI / 3, Math.PI / 3 * 4), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(circle);
  • 效果图:

image

6.1.5 圆柱体

圆柱体( CylinderGeometry)的构造函数是:
new THREE.CylinderGeometry(radiusTop, radiusBottom, height, radiusSegments, heightSegments, openEnded)
  • 其中,radiusTopradiusBottom分别是顶面和底面的半径,由此可知,当这两个参数设置为不一样的值时,实际上建立的是一个圆台;height是圆柱体的高度radiusSegmentsheightSegments可类比球体中的分段,一个表示底面、顶面的分段,另外一个表示环面的分段;openEnded是一个布尔值,表示是否没有顶面和底面,缺省值为false,表示有顶面和底面。

标准圆柱体

  • new THREE.CylinderGeometry(1.5, 1.5, 3, 18, 3)建立一个顶面与底面半径都为2,高度为4的圆柱体:
var cylinder = new THREE.Mesh(
    new THREE.CylinderGeometry(1.5, 1.5, 3, 18, 3), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(cylinder);
  • 效果图:

image

圆台

  • 顶面、底面半径不一致的时候,便是一个圆台。将底面半径设为2建立一个圆台:new THREE.CylinderGeometry(1.5, 2, 3, 18, 3)
var cylinder = new THREE.Mesh(
    new THREE.CylinderGeometry(1.5, 2, 3, 18, 3), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(cylinder);
  • 效果图:

image

无底面、顶面

  • openEndedtrue的时候,将无底面、顶面。new THREE.CylinderGeometry(1.5, 1.5, 3, 18, 3, true)将建立一个没有顶面与底面的圆柱:
var cylinder = new THREE.Mesh(
    new THREE.CylinderGeometry(1.5, 1.5, 3, 18, 3, true), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(cylinder);
  • 效果图:

image

6.1.6 正四面体、正八面体、正二十面体

正四面体( TetrahedronGeometry)、正八面体( OctahedronGeometry)、正二十面体( IcosahedronGeometry)的构造函数较为相似,分别为:
// 正四面体
new THREE.TetrahedronGeometry(radius, detail)
// 正八面体
new THREE.OctahedronGeometry(radius, detail)
// 正二十面体
new THREE.IcosahedronGeometry(radius, detail)
  • 其中,radius是半径;detail是细节层次(Level of Detail)的层数,对于大面片数模型,能够控制在视角靠近物体时,显示面片数多的精细模型,而在离物体较远时,显示面片数较少的粗略模型。这里咱们不对detail多做展开,通常能够对这个值缺省。

正四面体

  • new THREE.TetrahedronGeometry(2.5)建立一个半径2.5的正四面体:
var tetrahedron = new THREE.Mesh(
    new THREE.TetrahedronGeometry(2.5), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(tetrahedron);
  • 效果图:

image

正八面体

  • new THREE.OctahedronGeometry(2.5)建立一个半径为2.5的正八面体:
var octahedron = new THREE.Mesh(
    new THREE.OctahedronGeometry(2.5), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(octahedron);
  • 效果图:

image

正二十面体

  • new THREE.IcosahedronGeometry(2.5)建立一个半径为2.5的正二十面体:
var icosahedron = new THREE.Mesh(
    new THREE.IcosahedronGeometry(2.5), 
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(icosahedron);
  • 效果图:

image

6.1.7 圆环面

圆环面( TorusGeometry)就是甜甜圈的形状,其构造函数是:
new THREE.TorusGeometry(radius, tube, radialSegments, tubularSegments, arc)

image

  • 其中,radius是圆环半径;tube是管道半径;radialSegmentstubularSegments分别是两个分段数,详见上图;arc是圆环面的弧度,缺省值为Math.PI * 2

粗糙圆环面

  • new THREE.TorusGeometry(2, 0.7, 4, 8)建立一个粗糙的圆环面:
var torus = new THREE.Mesh(
    new THREE.TorusGeometry(2, 0.7, 4, 8),
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(torus);
  • 效果图:

image

精细圆环面

  • new THREE.TorusGeometry(2, 0.7, 12, 18)建立一个较为精细的圆环面:
var torus = new THREE.Mesh(
    new THREE.TorusGeometry(2, 0.7, 12, 18),
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(torus);
  • 效果图:

image

部分圆环面

  • new THREE.TorusGeometry(2, 0.7, 4, 8, Math.PI / 3 * 2)建立部分圆环面:
var torus = new THREE.Mesh(
    new THREE.TorusGeometry(2, 0.7, 4, 8, Math.PI / 3 * 2),
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(torus);
  • 效果图:

image

6.1.8 圆环结

若是说圆环面是甜甜圈,那么圆环结( TorusKnotGeometry)就是打告终的甜甜圈,其构造参数为:
new THREE.TorusKnotGeometry(radius, tube, radialSegments, tubularSegments, p, q, heightScale)
  • 前四个参数在圆环面中已经有所介绍,pq是控制其样式的参数,通常能够缺省,若是须要详细了解,请学习圆环结的相关知识heightScale是在z轴方向上的缩放。
  • new THREE.TorusKnotGeometry(2, 0.5, 32, 8) 默认样式的圆环结:
var torus = new THREE.Mesh(
    new THREE.TorusKnotGeometry(1.6, 0.4, 32, 8),
    new THREE.MeshBasicMaterial({
        color: 0xffff00,
        wireframe: true
    })
);
scene.add(torus);
  • 效果图:

image

6.2 文字形状

文字形状( TextGeometry)能够用来建立三维的文字形状。

6.2.1 下载使用

使用文字前,须要下载和引用额外的字体库。字体库在 three.js Github master/examples/fonts目录下,下载里面的 json文件,放在你的目录下,而后加载。

image

  • 这里,咱们就以helvetiker字体为例。咱们在刚刚的字体库目录下,下载helvetiker_regular.typeface.json文件放在你的目录下,而后用如下方法加载:
// 调用一个字体加载函数
var loader = new THREE.FontLoader();
loader.load('helvetiker_regular.typeface.json', function(font) {
    var mesh = new THREE.Mesh(
        new THREE.TextGeometry('Hello', {
            font: font,
            size: 1,
            height: 1
        }), 
        new THREE.MeshBasicMaterial({
            color: 0xffff00,
            wireframe: true
        })
    );
    scene.add(mesh);
    // 写在loader函数里面 不然不显示
    renderer.render(scene,camera);
});
  • 注意:

    • 以前用的73dev版本的three.js,执行代码的时候发现报错,多是尚未添加这个功能,因此建议去下载最新版本的three.js
    • json配置文件,须要在本地服务器打开,推荐使用webstorm编辑器,由于它打开html文件时,就是以本地服务器的方式打开的。或者在cmd命令行中输入live-server,但须要配置,具体方法请点这里

6.2.2 参数介绍

建立文字形状的流程和以前介绍的基本几何形状是相似的,其构造函数是:
new THREE.TextGeometry(text, parameters)
  • 其中,text是要显示的文字字符串,parameters是如下参数组成的对象:

    • size:字号大小,通常为大写字母的高度
    • height:文字的厚度
    • curveSegments:弧线分段数,使得文字的曲线更加光滑
    • font:字体,默认是'helvetiker',需对应引用的字体文件
    • weight:值为'normal''bold',表示是否加粗
    • style:值为'normal''italics',表示是否斜体
    • bevelEnabled:布尔值,是否使用倒角,意为在边缘处斜切
    • bevelThickness:倒角厚度
    • bevelSize:倒角宽度

6.2.3 示例代码

建立一个三维文字 new THREE.TextGeometry("hello", {size: 1, height: 1})
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>hello</title>
    <script type="text/javascript" src="js/three.js"></script>
</head>

<body onload="init()">
    <script>
        function init() {
            // 调用一个渲染器
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(800, 600);
            document.body.appendChild(renderer.domElement);
            renderer.setClearColor(0x000000);

            // 调用场景
            var scene = new THREE.Scene();

            // 调用相机
            var camera = new THREE.OrthographicCamera(-4, 4, 3, -3, 0.1, 100);
            camera.position.set(5, 5, 20);
            camera.lookAt(new THREE.Vector3(1.1, 0, 0));
            scene.add(camera);

            // 定义材质
            var material = new THREE.MeshBasicMaterial({
                color: 0xffff00,
                wireframe: true
            });

            // 加载文字模板
            var loader = new THREE.FontLoader();
            loader.load('helvetiker_regular.typeface.json', function(font) {
                // 中文字符不能解析
                var mesh = new THREE.Mesh(new THREE.TextGeometry('hello', {
                    font: font,
                    size: 1,
                    height: 1
                }), material);
                scene.add(mesh);
                // 渲染必定要在load函数里面
                renderer.render(scene, camera);
            })
        }
    </script>
</body>
</html>
  • 效果图:

image

  • 咱们能够改变材质和添加光照来改变显示效果(灯光、材质没必要深究,后面会细讲)
// 将材质改成lambert材质
var material = new THREE.MeshLambertMaterial({
    color: 0xffff00
});

// 加上一束方向光
var light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(1, 0, 0.5);
scene.add(light);
  • 效果图:

image

  • 这里只是给你们看了一个效果,具体材质、灯光的原理不要去深究,直接跳过,看下面的知识点。

6.3 自定义形状

对于Three.js没有提供的形状,能够经过自定义形状来建立。
  • 因为自定义形状须要手动指定每一个顶点位置,以及顶点链接状况,若是该形状很是复杂,程序员计算量就会比较大。这种状况,建议使用建模工具,建立好以后,再经过three.js导入到场景中,这样会十分高效、方便。
  • 自定义形状使用的是Geometry类,它是其余如CubeGeometry、SphereGeometry等几何形状的父类,其构造函数是:
new THREE.Geometry()
  • 咱们以建立一个梯台为例,首先,初始化一个几何形状,而后设置顶点位置以及顶点链接状况。

    • 顶面建立4个点,底面建立4个点,按照顺时针的顺序逐个建立
    • geometry建立点的时候都是push到数组vertices里面的
    • 因此这8个点,按照顺序都有一个对应的索引值
    • 利用Face3的方法将3点连成一个三角面

image

  • 看代码
// 初始化几何形状
var geometry = new THREE.Geometry();

// 设置顶点的位置 
// 顶部4个点
geometry.vertices.push(new THREE.Vector3(-1, 2, -1));
geometry.vertices.push(new THREE.Vector3(1, 2, -1));
geometry.vertices.push(new THREE.Vector3(1, 2, 1));
geometry.vertices.push(new THREE.Vector3(-1, 2, 1));
// 底部4顶点
geometry.vertices.push(new THREE.Vector3(-2, 0, -2));
geometry.vertices.push(new THREE.Vector3(2, 0, -2));
geometry.vertices.push(new THREE.Vector3(2, 0, 2));
geometry.vertices.push(new THREE.Vector3(-2, 0, 2));

// 设置顶点链接状况
// 顶面
geometry.faces.push(new THREE.Face3(0, 1, 3));
geometry.faces.push(new THREE.Face3(1, 2, 3));
// 底面
geometry.faces.push(new THREE.Face3(4, 5, 6));
geometry.faces.push(new THREE.Face3(5, 6, 7));
// 四个侧面
geometry.faces.push(new THREE.Face3(1, 5, 6));
geometry.faces.push(new THREE.Face3(6, 2, 1));
geometry.faces.push(new THREE.Face3(2, 6, 7));
geometry.faces.push(new THREE.Face3(7, 3, 2));
geometry.faces.push(new THREE.Face3(3, 7, 0));
geometry.faces.push(new THREE.Face3(7, 4, 0));
geometry.faces.push(new THREE.Face3(0, 4, 5));
geometry.faces.push(new THREE.Face3(0, 5, 1));
  • 效果图:

image

  • 总结:

    • 须要注意的是,new THREE.Vector3(-1, 2, -1)建立一个矢量,做为顶点位置追加到geometry.vertices数组中。
    • 而由new THREE.Face3(0, 1, 3)建立一个三个顶点组成的面片,追加到geometry.faces数组中。三个参数分别是四个顶点在geometry.vertices中的序号。

7. 材质

材质( material),是独立于物体顶点信息以外的与渲染效果相关的属性。经过设置材质能够改变物体颜色、纹理贴图、光照模式等。
  • 下面将会为你们介绍基本材质两种基于光照模型材质法向量做为材质图像做为材质

7.1 基本材质

使用基本材质( BasicMaterial)的物体,渲染后物体的颜色,始终为 该材质的颜色,不会因为光照产生明暗、阴影效果。若是没有指定材质的颜色,则颜色是随机的,构造函数以下:
new THREE.MeshBasicMaterial(opt)
  • 其中参数opt能够缺省,或者为包含各属性的值。如,为一个黄色正方体添加一个1不透明度 (opacity)
new THREE.MeshBasicMaterial({
    color: 0xffff00,
    opacity: 0.75
});
  • 示例代码:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>基本材质</title>
    <script type="text/javascript" src="js/three.js"></script>
</head>

<body onload="init();">
    <script>
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(800, 600);
            document.body.appendChild(renderer.domElement);
            renderer.setClearColor(0x000000);

            // 场景
            var scene = new THREE.Scene();
            
            // 相机
            var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
            camera.position.set(25, 25, 25);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);

            // 光
            var light = new THREE.PointLight(0xffffff, 1, 100);
            light.position.set(10, 15, 5);
            scene.add(light);
            
            // 材质
            var material = new THREE.MeshBasicMaterial({
                color: 0xffff00,
                opacity: 0.75
            });

            // 几何体
            var cube = new THREE.Mesh(new THREE.CubeGeometry(2, 2, 2), material);
            scene.add(cube);
            
            // 渲染
            renderer.render(scene, camera);
        }
    </script>
</body>

</html>
  • 效果图:

image

  • 下面,介绍几个经常使用的属性

    • visible:是否可见,默认为true
    • side:渲染面片正面或是反面,默认为正面THREE.FrontSide,可设置为反面THREE.BackSide,或双面THREE.DoubleSide
    • wireframe:是否渲染线而非面,默认为false
    • color:十六进制RGB颜色,如红色表示为0xff0000
    • map:使用纹理贴图(下面会着重讲解)
  • 对于基本材质,即便改变场景中的光源,使用该材质的物体也始终为颜色到处相同的效果。固然,这不是很具备真实感,所以,接下来咱们将介绍更为真实的光照模型:Lambert光照模型以及Phong光照模型。

7.2 Lambert 材质

Lambert材质( MeshLambertMaterial)是符合Lambert光照模型的材质。Lambert光照模型的主要特色是只考虑 漫反射而不考虑 镜面反射的效果,于是对于金属、镜子等须要镜面反射效果的物体就 不适应,对于其余大部分物体的漫反射效果都是适用的。
  • 它的光照模型的公式为:
Idiffuse = Kd * Id * cos(theta)
  • 其中,Idiffuse是漫反射光强,Kd是物体表面的漫反射属性,Id是光强,theta是光的入射角弧度。
  • 固然,对于使用Three.js的Lambert材质,不须要了解以上公式就能够直接使用。建立Lambert材质的构造函数以下:
new THREE.MeshLambertMaterial()
  • 示例代码(建立一个黄色并使用光照的立方体):

    • 光照这里不细讲,后面会着重讲解,这里你们只须要知道是干什么用的就行
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Lambert材质</title>
    <script type="text/javascript" src="js/three.js"></script>
</head>

<body onload="init();">
    <script>
        function init() {
            // 渲染
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(800, 600);
            document.body.appendChild(renderer.domElement);
            renderer.setClearColor(0x000000);

            // 场景
            var scene = new THREE.Scene();
            
            // 相机
            var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
            camera.position.set(25, 25, 25);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);
            
            // 添加光照
            var light = new THREE.PointLight(0xffffff, 1, 100);
            light.position.set(10, 15, 5);
            scene.add(light);

            // Lambert材质
            var material = new THREE.MeshLambertMaterial({
                color: 0xffff00,
            });
            
            // 几何体
            var cube = new THREE.Mesh(new THREE.CubeGeometry(2, 2, 2), material);
            scene.add(cube);
            
            // 渲染
            renderer.render(scene, camera);
        }
    </script>
</body>

</html>
  • 效果图:

image

  • 下面,介绍几个经常使用的属性:

    • color是用来表现材质对散射光的反射能力,也是最经常使用来设置材质颜色的属性。除此以外,还能够用ambientemissive控制材质的颜色。
    • ambient表示对环境光反射能力,只有当设置了AmbientLight后,该值才是有效的,材质对环境光的反射能力与环境光强相乘后获得材质实际表现的颜色。
    • emissive是材质的自发光颜色,能够用来表现光源的颜色。
  • 单独使用红色自发光:
var material = new THREE.MeshLambertMaterial({
    emissive: 0xff0000
})
  • 效果图:

image

  • 若是同时使用红色的自发光与黄色的散射光:
var material = new THREE.MeshLambertMaterial({
    color: 0xffff00,
    emissive: 0xff0000
})
  • 效果图:

image

  • 这样就会出现一个渐变色的效果,咱们能够新建一个球体:
var material = new THREE.MeshLambertMaterial({
    color: 0xffff00,
    emissive: 0xff0000
});

var sphere = new THREE.Mesh(new THREE.SphereGeometry(1.6, 40, 16), material);
scene.add(sphere);
  • 效果图:

image

7.3 Phong材质

Phong材质( MeshPhongMaterial)是符合Phong光照模型的材质。和Lambert不一样的是,Phong模型考虑了 镜面反射的效果,所以对于金属、镜面的表现尤其适合。
  • 漫反射部分和Lambert光照模型是相同的,镜面反射模型的公式为:
Ispecular = Ks * Is * (cos(alpha)) ^ n
  • 其中,Ispecular是镜面反射的光强Ks是材质表面镜面反射系数Is是光源强度alpha是反射光与视线的夹角n高光指数,越大则高光光斑越小。
  • 因为漫反射部分与Lambert模型是一致的,所以,若是不指定镜面反射系数,而只设定漫反射,其效果与Lambert是相同的:
new THREE.MeshPhongMaterial({
    color: 0xffff00
});
  • 完整代码:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Phong材质</title>
    <script type="text/javascript" src="js/three.js"></script>
</head>

<body onload="init();">
    <script>
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(800, 600);
            document.body.appendChild(renderer.domElement);
            renderer.setClearColor(0x000000);

            // 场景
            var scene = new THREE.Scene();
            
            // 相机
            var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
            camera.position.set(25, 25, 25);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);
            
            // 光照
            var light = new THREE.PointLight(0xffffff, 1, 200);
            light.position.set(10, 15, 25);
            scene.add(light);
            
            // 材质
            var material = new THREE.MeshPhongMaterial({
                color: 0xffff00,
                //specular: 0xffff00,
                //shininess: 1000
            });
            // 几何体
            var cube = new THREE.Mesh(new THREE.CubeGeometry(2, 2, 2), material);
            scene.add(cube);
            //var sphere = new THREE.Mesh(new THREE.SphereGeometry(1.6, 40, 16), material);
            //scene.add(sphere);
            
            // 渲染
            renderer.render(scene, camera);
        }
    </script>
</body>

</html>
  • 效果图:

image

  • 下面,介绍几个经常使用的属性:

    • 一样地,能够指定emissiveambient值,这里再也不说明。
    • 下面就specular值指定镜面反射系数做说明。
  • 首先,咱们只使用镜面反射(specular),将高光设为红色,应用于一个球体:
var material = new THREE.MeshPhongMaterial({
    specular: 0xff0000
});

var sphere = new THREE.Mesh(new THREE.SphereGeometry(1.6, 40, 16), material);
scene.add(sphere);
  • 效果图:

image

  • 能够经过shininess属性控制光照模型中的n值*(高光指数,光斑),当shininess值越大时,高光的光斑越小,默认值为30。咱们将其设置为1000时:
var material = new THREE.MeshPhongMaterial({
    specular: 0xff0000,
    shininess: 1000
});
  • 效果图:

image

  • 使用黄色的镜面光,红色的散射光:
material = new THREE.MeshPhongMaterial({
    color: 0xff0000,
    specular: 0xffff00,
    shininess: 1000
});
  • 效果图:

image

7.4 法向材质

法向材质能够将材质的颜色设置为其 法向量的方向,有时候对于调试颇有帮助。
  • 法向材质的设定很简单,不须要设置参数。构造函数以下:
new THREE.MeshNormalMaterial()

材质的颜色与照相机与该物体的角度相关,下面咱们只改变照相机位置,观察两个角度的颜色变化:

  • 示例代码:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>法向材质</title>
    <script type="text/javascript" src="js/three.js"></script>
</head>

<body onload="init();">
    <script>
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(800, 600);
            document.body.appendChild(renderer.domElement);
            renderer.setClearColor(0x000000);

            // 场景
            var scene = new THREE.Scene();

            // 相机
            var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
            /* 修改这里如下的值 */ 
            camera.position.set(25, 25, 25);
            /* 修改这里以上的值 */
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);

            // 光照
            var light = new THREE.PointLight(0xffffff, 1, 200);
            light.position.set(10, 15, 25);
            scene.add(light);

            // 材质
            var material = new THREE.MeshNormalMaterial();

            // 几何体
            var cube = new THREE.Mesh(new THREE.CubeGeometry(2, 2, 2), material);
            scene.add(cube);

            // 渲染
            renderer.render(scene, camera);
        }
    </script>
</body>

</html>
  • camera.position.set(5, 25, 25);的效果图:

image

  • camera.position.set(25, 25, 25);的效果图:

image

  • 咱们观察的是一样的三个面,可是因为观察的角度不一样,物体的颜色就不一样了。所以,在调试时,要知道物体的法向量,使用法向材质就颇有效。

7.5 材质的纹理贴图

在此以前,咱们使用的材质都是单一颜色的,有时候,咱们却但愿使用图像做为材质。这时候,就须要导入图像做为纹理贴图,并添加到相应的材质中。

7.5.1 单张图像应用于长方体

  • 首先,咱们须要选择一张长宽均为128像素的图像:

image

  • 将其导入到纹理texture中:
var texture = THREE.ImageUtils.loadTexture('images/01.jpg');
  • 而后,将材质的map属性设置为texture
var material = new THREE.MeshLambertMaterial({
    map: texture
});
  • 这样就完成了将图片应用于材质的基本步骤。可是因为如今咱们还没使用动画,画面只被渲染了一次,而在导入纹理以前,已经完成了此次渲染,所以看到的只是一片黑。因此,若是没有重绘函数(将在下一章介绍),就须要在完成导入纹理的步骤后,从新绘制画面,这是在回调函数中实现的:
var texture = THREE.ImageUtils.loadTexture('images/01.jpg', {}, function() {
    renderer.render(scene, camera);
});
var material = new THREE.MeshLambertMaterial({
    map: texture
});
  • 注意:须要在本地服务器运行。
  • 完整代码:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>纹理贴图</title>
    <script type="text/javascript" src="js/three.js"></script>
</head>

<body onload="init();">
    <script>
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(800, 600);
            document.body.appendChild(renderer.domElement);
            renderer.setClearColor(0x000000);

            // 场景
            var scene = new THREE.Scene();

            // 相机
            var camera = new THREE.OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 1000);
            camera.position.set(25, 25, 25);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);

            // 光照
            var light = new THREE.PointLight(0xffffff, 1, 200);
            light.position.set(10, 15, 25);
            scene.add(light);

            // 纹理(须要重绘函数)
            var texture = THREE.ImageUtils.loadTexture('images/01.jpg', {}, function() {
                renderer.render(scene, camera);
            });

            // 材质
            var material = new THREE.MeshLambertMaterial({
                map: texture
            });

            // 几何体
            var cube = new THREE.Mesh(new THREE.CubeGeometry(2, 2, 2), material);
            scene.add(cube);
            // var sphere = new THREE.Mesh(new THREE.SphereGeometry(1.6, 40, 16), material);
            // scene.add(sphere);

            // 渲染
            renderer.render(scene, camera);
        }
    </script>
</body>

</html>
  • 如今,就能看到这样的效果了:

image

  • 相似地,若是将其应用于球体,将会把整个球体应用该图像:

image

7.5.2 六张图像应用于长方体

有时候,咱们但愿长方体的六面各类的贴图都不一样。所以,咱们首先准备了六张颜色各异的图像,分别写了数字01到06。而后,分别导入图像到六个纹理,并设置到六个材质中:
var materials = [];
for (var i = 1; i < 7; ++i) {
    materials.push(new THREE.MeshBasicMaterial({
        map: THREE.ImageUtils.loadTexture('images/0' + i + '.jpg', {}, function() {
            renderer.render(scene, camera);
        }),
        overdraw: true
    }));
}

var cube = new THREE.Mesh(
    new THREE.CubeGeometry(2, 2, 2),
    new THREE.MeshFaceMaterial(materials));
scene.add(cube);
  • 效果为:

image

7.5.3 棋盘

用黑白相间的图片绘制一副棋盘

image

  • 实现代码:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>棋盘</title>
    <script type="text/javascript" src="js/three.js"></script>
</head>

<body onload="init();">
    <script>
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(800, 600);
            document.body.appendChild(renderer.domElement);
            renderer.setClearColor(0xffffff);

            // 场景
            var scene = new THREE.Scene();

            // 相机
            var camera = new THREE.OrthographicCamera(-10, 10, 7.5, -7.5, 0.1, 100);
            camera.position.set(0, 0, 25);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);

            // 光照
            var light = new THREE.PointLight(0xffffff, 1, 1000);
            light.position.set(10, 15, 25);
            scene.add(light);

            var texture = THREE.ImageUtils.loadTexture('images/chess.png', {}, function() {
                renderer.render(scene, camera);
            });
            // texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
            // texture.repeat.set(4, 4);
            var material = new THREE.MeshLambertMaterial({
                map: texture
            });
            
            // 平面
            var plane = new THREE.Mesh(new THREE.PlaneGeometry(12, 12), material);
            scene.add(plane);

            // 渲染
            renderer.render(scene, camera);
        }
    </script>
</body>

</html>
  • 效果图:

image

但是,棋盘格是8横8纵64个小方格组成的,那应该怎么办呢?

  • 首先,咱们须要指定重复方式为两个方向(wrapSwrapT)都重复:
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
  • 而后,设置两个方向上都重复4次,因为咱们的图像原本是有2行2列,因此重复4次即为8行8列:
texture.repeat.set(4, 4);
  • 效果图:

image

8. 网格

在学习了几何形状和材质以后,咱们就能使用他们来建立物体了。最经常使用的一种物体就是网格(Mesh),网格是由顶点、边、面等组成的物体;其余物体包括线段( Line)、骨骼( Bone)、粒子系统( ParticleSystem)等。建立物体须要指定几何形状和材质,其中,几何形状决定了物体的 顶点位置等信息,材质决定了物体的 颜色、纹理等信息。
  • 本章将介绍建立较为经常使用的物体:网格,而后介绍如何修改物体的属性。

8.1 建立网格

在上两节中,咱们学习了如何建立几何形状与材质,而网格的建立很是简单,只要把几何形状与材质传入其构造函数。最经常使用的物体是网格( Mesh),它表明包含 点、线、面的几何体,其构造函数是:
// geometry : 定义的几何体
// material : 材质
new THREE.Mesh(geometry,material)
  • 下面,让咱们经过一个具体的例子了解如何建立网格:
// 几何体(长方体)
var geometry = new THREE.CubeGeometry(0.6, 1.2, 1.8);

// 材质
var material = new THREE.MeshLambertMaterial({
    color: 0xffff00
});

// 网格
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
  • 若是materialgeometry以后不会复用的话,也能够合在一块儿写为:
var mesh = new THREE.Mesh(new THREE.CubeGeometry(0.6, 1.2, 1.8), 
    new THREE.MeshLambertMaterial({
        color: 0xffff00
    })
);
scene.add(mesh);
  • 完整代码:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>网格</title>
    <script type="text/javascript" src="js/three.js"></script>
</head>

<body onload="init();">
    <script>
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(800, 600);
            document.body.appendChild(renderer.domElement);
            renderer.setClearColor(0x000000);

            // 场景
            var scene = new THREE.Scene();

            // 相机
            var camera = new THREE.OrthographicCamera(-2.5, 2.5, 1.875, -1.875, 0.1, 100);
            camera.position.set(5, 5, 20);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);

            // 光照 
            var light = new THREE.DirectionalLight(0xffffff);
            light.position.set(20, 10, 5);
            scene.add(light);

            // 材质
            var material = new THREE.MeshLambertMaterial({
                color: 0xffff00
            });

            // 几何体
            var geometry = new THREE.CubeGeometry(0.6, 1.2, 1.8);

            // 网格
            var mesh = new THREE.Mesh(geometry, material);
            scene.add(mesh);

            // render
            renderer.render(scene, camera);
        }
    </script>
</body>

</html>
  • 效果图:

image

8.2 修改属性

8.2.1 材质

除了在构造函数中指定材质,在网格被建立后,也能对材质进行修改:
  • 示例代码:
var material = new THREE.MeshLambertMaterial({
    color: 0xffff00
});
var geometry = new THREE.CubeGeometry(1, 2, 3);
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

// 从新赋值
mesh.material = new THREE.MeshLambertMaterial({
    color: 0xff0000
});
  • 最终会显示红色,缘由很简单,在js语言预解析中,下面材质从新赋值后,就覆盖了上面定义的材质。
  • 效果图

image

8.2.2 位置、缩放、旋转

位置、缩放、旋转是物体三个经常使用属性。因为 THREE.Mesh基础自 THREE.Object3D,所以包含 scale、rotation、position三个属性。它们都是 THREE.Vector3实例,所以修改其值的方法是相同的,这里以 位置为例。
  • THREE.Vector3x、y、z三个属性,若是只设置其中一个属性,则能够用如下方法:
mesh.position.z = 1;
  • 若是须要同时设置多个属性,可使用如下两种方法:
mesh.position.set(1.5, -0.5, 0);
mesh.position = new THREE.Vector3(1.5, -0.5, 0);
  • 示例代码(修改位置):
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>修改位置</title>
    <script type="text/javascript" src="js/three.js"></script>
</head>

<body onload="init();">
    <script>
        function init() {
            // 渲染器
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(800, 600);
            document.body.appendChild(renderer.domElement);
            renderer.setClearColor(0x000000);

            // 场景
            var scene = new THREE.Scene();

            // 相机
            var camera = new THREE.OrthographicCamera(-2.5, 2.5, 1.875, -1.875, 0.1, 100);
            camera.position.set(5, 5, 10);
            camera.lookAt(new THREE.Vector3(0, 0, 0));
            scene.add(camera);

            var material = new THREE.MeshLambertMaterial({
                color: 0xffff00
            });
            var geometry = new THREE.CubeGeometry(0.6, 1.2, 1.8);
            var mesh = new THREE.Mesh(geometry, material);
            scene.add(mesh);

            // 修改位置属性
            mesh.position.set(1, 0, 0);
            // mesh.position = new THREE.Vector3(1.5, -0.5, 0);
            // mesh.position.x = 1;

            var light = new THREE.DirectionalLight(0xffffff);
            light.position.set(20, 10, 5);
            scene.add(light);

            // 坐标轴
            drawAxes(scene);

            // 渲染
            renderer.render(scene, camera);


            function drawAxes(scene) {
                // x-axis
                var xGeo = new THREE.Geometry();
                xGeo.vertices.push(new THREE.Vector3(0, 0, 0));
                xGeo.vertices.push(new THREE.Vector3(3, 0, 0));
                var xMat = new THREE.LineBasicMaterial({
                    color: 0xff0000
                });
                var xAxis = new THREE.Line(xGeo, xMat);
                scene.add(xAxis);

                // y-axis
                var yGeo = new THREE.Geometry();
                yGeo.vertices.push(new THREE.Vector3(0, 0, 0));
                yGeo.vertices.push(new THREE.Vector3(0, 3, 0));
                var yMat = new THREE.LineBasicMaterial({
                    color: 0x00ff00
                });
                var yAxis = new THREE.Line(yGeo, yMat);
                scene.add(yAxis);

                // z-axis
                var zGeo = new THREE.Geometry();
                zGeo.vertices.push(new THREE.Vector3(0, 0, 0));
                zGeo.vertices.push(new THREE.Vector3(0, 0, 3));
                var zMat = new THREE.LineBasicMaterial({
                    color: 0x00ccff
                });
                var zAxis = new THREE.Line(zGeo, zMat);
                scene.add(zAxis);
            }
        }
    </script>
</body>

</html>
  • 效果图

image

  • 缩放对应的属性是scale旋转对应的属性是rotation,具体方法与上例相同,分别表示沿x、y、z三轴缩放或旋转。
相关文章
相关标签/搜索