以下文章即Learn Threejs 第三版英文翻译学习记录,可以到正版书店购买对应书籍。
在之前的章节中,你学习了Three.js的基础。我们看了一些简单的例子,你也创建了你的第一个完整的Three.js项目,在这一小节中,我们将会深入探讨Three.js,并解释构成Three.js应用程序的基本组件,在课程中,我们将探讨以下话题:
可以用来创建Three.js应用程序的主要组件;
你使用THREE.Scene对象可以做一些什么;
几何体和网格对象的关系;(这个应该是说模型贴图)
正交摄影机和透视摄影机的区别;(这个应该是在讲不同的相机)
我们将从如何创建场景和添加模型对象开始。
创建一个场景
在第一章中,你通过Three.js 的THREE.scene创建了你的第一个3D场景,所以你也应该基本了解到了Three.js。我们看到能显示任何对象的场景,我们需要以下四个组合:
Camera:这个定义了屏幕上渲染要的东西;
Lights:这些作用于材料和阴影上(意思就是只有设置了光线,才能显示出阴影和材质)。
Objects(模型):这些将通过Camera的角度渲染主要对象,包括立方体、球体、点阵;
Renderer:将Camera所看到的东西,绘制输出出来。
THREE.Scene 是光线和对象的容器,THREE.Scene 本身是没有那么多属性和方法;
Tip:通常我们将THREE.Scene这样的结构体称为场景图;场景图是一个能够保存场景图形和一些必要信息的结构。在Three.js中,它的意思就是能够包含所有对象、光线、和一些对象渲染的相关信息。有趣的是,as the name implies(顾名思义),它不仅仅是一个对象数组。场景图是一个由多个节点组成的树的集合,在Three.js中,你可以添加任何的对象到场景里甚至是它自己,它是在THREE.Object 3D对象上做的扩展,所以它可以有自己的子对象(就是将自己作为自己的属性,嗯,就是它可以包含THREE.Scene的实例。)你可以用它来创建你的对象树。
THREE.Scene 一些基础的方法
探索THREE.Scene的成员方法最好的方法就是查看示例,这节的代码,你可以通过01-basic-scene.html找到,我们通过这个示例去介绍THREE.Scene的方法和属性。当我们通过浏览器打开这个示例,页面所呈现的结果将会和截图一样(通过使用a、s、d按键可以移动或缩放场景地图)
看起来和第一节中讲的一摸一样,通过Three.js创建一个3D场景,尽管场景里看起来什么都没有,但它已经包含了几个对象,查看02-02.js,可以看到通过THREE.Scene的 scene.add(object)方法将一个Plane面添加到了场景中,并且设置了贴图、(聚)光线和(环境)光线。渲染场景时,THREE.Camera对象由THREE.js自动添加,因此不需要将其添加到场景本身。请查看此场景的以下源代码:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth
/ window.innerHeight, 0.1, 100);
scene.add(camera);
...
var planeGeometry = new THREE.PlaneGeometry(60,40,1,1);
var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});
var plane = new THREE.Mesh(planeGeometry,planeMaterial);
...
scene.add(plane);
var ambientLight = new THREE.AmbientLight(0x3c3c3c);
scene.add(ambientLight);
...
var spotLight = new THREE.SpotLight(0xffffff, 1.2, 150, 120);
spotLight.position.set(-40, 60, -10);
spotLight.castShadow = true;
scene.add(spotLight);
在我们还没有深入研究THREE.Scene对象之前,我们首先解释一下你可通通过这个示例来做什么。(接下来说的就是运行项目,操作)。
经过我们的操作,我们发现,你可以添加一个立方体到场景中、可以从场景中删除一个立方体(这里应该是说设置了一个上限,到达某个上限后,再次添加将会删除之前的那个)
this.addCube = function() {
var cubeSize = Math.ceil((Math.random() * 3));
var cubeGeometry = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
var cubeMaterial = new THREE.MeshLambertMaterial({color: Math.random() * 0xffffff });
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial); cube.castShadow = true;
cube.name = "cube-" + scene.children.length;
cube.position.x= cube.position.y= cube.position.z= ......
scene.add(cube);
-30 + Math.round(Math.random() * planeGeometry.width)); Math.round((Math.random() * 5));
-20 + Math.round((Math.random() * planeGeometry.height));
this.numberOfObjects = scene.children.length; };
这段代码应该很容易被理解,这里不一一介绍。当你点击addCube按钮,一个新的THREE.BoxGeometry对象将被创建出来,它的长宽高是一个1-3的随机值,除此之外,还设置了随机的颜色和不同的位置坐标。
Tip:在这里没创建一个对象,我们都为它添加一个名字属性,这个名字属性非常重要,可用于场景中的对象访问,也可方便调试。如果你使用THREE.Scene.getObjectByName(name)方法,你可以得到这个对象,也可以修改这个对象的一些位置属性等,你无需将其设置为全局变量。你可能想知道最后一行干了些什么,numberOfObjects 属性表示在GUI场景中共渲染了多少个对象,所以,无论我们删除或者是添加也好,这个number都会刷新。
下一个方法需要介绍的就是removeCube,和上边的添加一样,点击删除按钮删除最后一个添加的立方体。
this.removeCube = function() {
var allChildren = scene.children;
var lastObject = allChildren[allChildren.length-1];
if (lastObject instanceof THREE.Mesh) {
scene.remove(lastObject);
this.numberOfObjects = scene.children.length; }
}
在场景里添加立方体我们调用add方法,删除立方体我们调用remove方法。Three.js 将对象通过列表的结构存储,(一个新的对象添加到列表的最后一个),我们可以使用children属性,它包含所有scene中添加的对象,所以获取最后一个对象时我们需要检查一下,它是否为网格mesh对象,已避免将光线对象删除。当我们删除了对象后,我们理解更新了GUI渲染(应该更新了numberOfObjects)保存对象数量。
(介绍了渲染的对象数,点击outputObjects 按钮 控制器输出场景渲染的对象数)
持续更新中...