three.js 02-02 之使用几何与网格对象

来源:互联网 发布:什么是软件嵌入式培养 编辑:程序博客网 时间:2024/06/12 13:27

    上一篇我们对场景 Scene 对象进行了单独讲解。本篇我们将来看看 Three.js 中的几个标准的几何体的用法。我们先上一段完整的代码,如下所示:

<!DOCTYPE html><html><head>    <title>示例 02.02 - 使用几何及网格对象</title><script src="../build/three.js"></script><script src="../build/js/ParametricGeometries.js"></script><script src="../build/js/QuickHull.js"></script><script src="../build/js/geometries/ConvexGeometry.js"></script><script src="../build/js/controls/OrbitControls.js"></script><script src="../build/js/libs/stats.min.js"></script><script src="../build/js/libs/dat.gui.min.js"></script><script src="../jquery/jquery-3.2.1.min.js"></script>    <style>        body {            /* 设置 margin 为 0,并且 overflow 为 hidden,来完成页面样式 */            margin: 0;            overflow: hidden;        }/* 统计对象样式 */#Stats-output {position: absolute;left: 0px;top: 0px;}    </style></head><body><!-- 用于 WebGL 输出的 Div --><div id="WebGL-output"></div><!-- 用于统计 FPS 输出的 Div --><div id="Stats-output"></div><!-- 运行 Three.js 示例的 Javascript 代码 --><script type="text/javascript">var scene;var camera;var render;var controls;var stats;var plane;    // 当所有元素加载完毕后,就执行我们 Three.js 相关的东西    $(function() {stats = initStats();scene = new THREE.Scene();camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); // 2147483647camera.position.set(-63, 37, 23);render = new THREE.WebGLRenderer( {antialias: true} ); // antialias 抗锯齿render.setSize(window.innerWidth, window.innerHeight);render.setClearColor(0xEEEEEE);render.shadowMap.enabled = true; // 允许阴影投射$('#WebGL-output')[0].appendChild(render.domElement);window.addEventListener('resize', onWindowResize, false);controls = new THREE.OrbitControls(camera, render.domElement);camera.lookAt(new THREE.Vector3(0, -10, -3));scene.add(new THREE.AxisHelper(20));// 加入坐标轴// 加入一个平面var planeGeometry = new THREE.PlaneGeometry(60, 40, 1, 1);var planeMaterial = new THREE.MeshLambertMaterial( {color: 0xFFFFFF} );plane = new THREE.Mesh(planeGeometry, planeMaterial);plane.rotation.x = -0.5 * Math.PI; // 沿着 X轴旋转-90°plane.position.x = 0;plane.position.y = 0;plane.position.z = 0;plane.receiveShadow = true; // 几何平面接收阴影scene.add(plane);// 加入一个环境光源var ambientLight = new THREE.AmbientLight(0x090909);scene.add(ambientLight);// 加入一个聚光灯光源// 注:基础材质 MeshBasicMaterial 不会对光源产生反应,因此要改用 MeshLambertMaterial 或 MeshPhongMaterial 材质才有效果var spotLight = new THREE.SpotLight( 0xFFFFFF);spotLight.position.set(-40, 40, 50);spotLight.castShadow = true; // 光源产生阴影spotLight.shadow.mapSize.width = 1024; // 必须是 2的幂,默认值为 512spotLight.shadow.mapSize.height = 1024; // 必须是 2的幂,默认值为 512scene.add(spotLight);addGeomtries(scene);renderScene();    });/** 初始化 stats 统计对象 */function initStats() {stats = new Stats();stats.setMode(0); // 0 为监测 FPS;1 为监测渲染时间$('#Stats-output').append(stats.domElement);return stats;}/** 渲染场景 */function renderScene() {stats.update();rotateMesh(); // 旋转物体requestAnimationFrame(renderScene);render.render(scene, camera);}/** 当浏览器窗口大小变化时触发 */function onWindowResize() {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();render.setSize(window.innerWidth, window.innerHeight);}function addGeomtries(scene) {var geoms = [];// 圆柱体:radiusTop, radiusBottom, heightgeoms.push(new THREE.CylinderGeometry(1, 4, 4));// 立方体:width, height, depthgeoms.push(new THREE.BoxGeometry(2, 2, 2));// 球体:radiusgeoms.push(new THREE.SphereGeometry(2));// 十二面体:radiusgeoms.push(new THREE.IcosahedronGeometry(4));// 通过一系列点创建一个凸状体var points = [new THREE.Vector3(2, 2, 2),new THREE.Vector3(2, 2, -2),new THREE.Vector3(-2, 2, -2),new THREE.Vector3(-2, 2, 2),new THREE.Vector3(2, -2, 2),new THREE.Vector3(2, -2, -2),new THREE.Vector3(-2, -2, -2),new THREE.Vector3(-2, -2, 2)];geoms.push(new THREE.ConvexGeometry(points));var pts = []; // 点数组:存储路径外形的点var detail = .1; // 半圆形细节:将使用多少个角度增量来生成点var radius = 3; // 半球体半径for (var angle = 0.0; angle < Math.PI; angle += detail) // 从0.0 到 PI 弧度(0 - 180度)pts.push(new THREE.Vector2(Math.abs(Math.cos(angle)) * radius, Math.sin(angle) * radius)); // 到 x,y 的弧度/半径geoms.push(new THREE.LatheGeometry(pts, 12));// 八面体:radiusgeoms.push(new THREE.OctahedronGeometry(3));// 通过函数创建几何形状geoms.push(new THREE.ParametricGeometry(THREE.ParametricGeometries.mobius3d, 20, 10));// 四面体:radiusgeoms.push(new THREE.TetrahedronGeometry(3));// 圆环体:radius(圆环半径), tube(管直径), radialSegments(径向分段), tubularSegments(管子分段)geoms.push(new THREE.TorusGeometry(3, 1, 16, 24));// 环形节:radius(圆环半径), tube(管直径), tubularSegments(管子分段), radialSegments(径向分段)geoms.push(new THREE.TorusKnotGeometry(3, 0.5, 64, 16));var j = 0;for (var i = 0; i < geoms.length; i++) {var materials = [new THREE.MeshLambertMaterial( {color: Math.random() * 0xffffff, shading: THREE.FlatShading} ),new THREE.MeshBasicMaterial( {color: 0x000000, wireframe: true} )];// 创建多材质对象var mesh = THREE.SceneUtils.createMultiMaterialObject(geoms[i], materials);mesh.traverse(function(e){e.castShadow = true;});mesh.position.x = -24 + ((i % 4) * 12);mesh.position.y = 4;mesh.position.z = -8 + (j * 12);mesh.name = geoms[i].type + "-" + (i+4);scene.add(mesh);if ((i + 1) % 4 == 0) j++;//if (geoms[i] instanceof THREE.LatheGeometry) mesh.rotation.x = Math.PI / 2;}}/** 转动立方体 */rotationSpeed = 0.02function rotateMesh() {// 遍历整个场景scene.traverse(function(e) {if (e instanceof THREE.Mesh && e != plane) {e.rotation.x += rotationSpeed;e.rotation.y += rotationSpeed;e.rotation.z += rotationSpeed;}});}</script></body></html>

    可见,Three.js 中的 Geometry 和其他多数三维库中的一样,基本上是三维空间中的点集,以及一些将这些点连接起来的面。譬如一个立方体:

  • 一个立方体有 8个角,每个角都可以定义为 x, y 和 z 坐标的一个组合。所以每个立方体都是三维空间中的 8个点,称为顶点(vertice);
  • 一个立方体有 6个侧面,每个侧面都称为面(face)。
    在 Three.js 中,想要创建一个立方体,你不必亲自定义所有这些顶点和面,你只要定义长宽高即可。Three.js 会在正确的位置创建一个拥有 8个顶点的几何体,并用正确的面连接起来。
    当然,你也可以自己定义这些顶点和面,来手工创建几何体。创建方法可以参考下面的代码片段:

var vertices = [    new THREE.Vector3(1, 3, 1),    new THREE.Vector3(1, 3, -1),    new THREE.Vector3(1, -1, 1),    new THREE.Vector3(1, -1, -1),    new THREE.Vector3(-1, 3, -1),    new THREE.Vector3(-1, 3, 1),    new THREE.Vector3(-1, -1, -1),    new THREE.Vector3(-1, -1, 1)];var faces = [    new THREE.Face3(0, 2, 1),    new THREE.Face3(2, 3, 1),    new THREE.Face3(4, 6, 5),    new THREE.Face3(6, 7, 5),    new THREE.Face3(4, 5, 1),    new THREE.Face3(5, 0, 1),    new THREE.Face3(7, 6, 2),    new THREE.Face3(6, 3, 2),    new THREE.Face3(5, 7, 0),    new THREE.Face3(7, 2, 0),    new THREE.Face3(1, 3, 4),    new THREE.Face3(3, 6, 4)];var geom = new THREE.Geometry();geom.vertices = vertices;geom.faces = faces;geom.center();geom.mergeVertices();

这段代码展示的是如何创建一个简单的立方体。我们在一个 vertices 数组里定义了构成这个立方体的顶点。将这些点连接起来,创建三角面片,并保存在 faces 数组里。例如,元素 new THREE.Face3(0, 2, 1) 就是用 vertices 数组里下标为 0, 2 和 1 的点创建的一个三角面片。
未完待续···

原创粉丝点击