Three.js开发指南---创建,加载高级网格和几何体(第八章)
Posted Amy-lover
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Three.js开发指南---创建,加载高级网格和几何体(第八章)相关的知识,希望对你有一定的参考价值。
本章的主要内容:
一, 通过Three.js自带的功能来组合和合并已有的几何体,创建出新的几何体
二, 从外部资源中加载网格和几何体
1 前面的章节中,我们学习到,一个几何体创建的网格,想使用多个材质的方法:
var mesh=THREE.SceneUtils.createMultiMaterialObject(geometry,[material1,,material2]);
看似一个网格中有一个几何体,多个材质,其实该网格拥有与材质数量相对应的几何体,每个几何体都对应一种材质,形成一个网格,我们得到的是包含多个网格的组
在下面的demo中,我们将创建一个网格组,该组包含多个网格,当这个组进行缩放,移动,旋转,变形的时候,组内的网格都会跟着变化
注意点1:创建组,将球体和立方体都添加到该组中
var group = new THREE.Group();group.add(sphereMesh);group.add(boxMesh)
注意点2:计算组的边界,生成一个边界无限大的立方体,对组以及组内子对象应用矩阵变换,得到组内子对象顶点改变后的坐标,复制子对象的每个顶点坐标,重新设置立方体的边界,参见函数setFromObject
注意点3:辅助线ArrowHelper,其参数的解读,dir:方向,默认是法向量;origin:开始的坐标位置;length:辅助线的长度;color:辅助线的颜色;headLength:头部的长度;headWidth:头部的宽度
<!DOCTYPE html> <html> <head> <title>Example 08.01 - Grouping</title> <script type="text/javascript" src="../libs/three.js"></script> <script type="text/javascript" src="../libs/stats.js"></script> <script type="text/javascript" src="../libs/dat.gui.js"></script> <style> body { /* set margin to 0 and overflow to hidden, to go fullscreen */ margin: 0; overflow: hidden; } </style> </head> <body> <div id="Stats-output"> </div> <!-- Div which will hold the Output --> <div id="WebGL-output"> </div> <!-- Javascript code that runs our Three.js examples --> <script type="text/javascript"> // once everything is loaded, we run our Three.js stuff. function init() { var stats = initStats(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); // create a camera, which defines where we\'re looking at. var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); // create a render and set the size var webGLRenderer = new THREE.WebGLRenderer(); webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0)); webGLRenderer.setSize(window.innerWidth, window.innerHeight); webGLRenderer.shadowMapEnabled = true; // add the sphere to the scene // position and point the camera to the center of the scene camera.position.x = 30; camera.position.y = 30; camera.position.z = 30; camera.lookAt(new THREE.Vector3(0, 0, 0)); var ground = new THREE.PlaneGeometry(100, 100, 50, 50); var groundMesh = THREE.SceneUtils.createMultiMaterialObject(ground, [new THREE.MeshBasicMaterial({wireframe: false, overdraw: true, color: 000000}), new THREE.MeshBasicMaterial({color: 0x00ff00, transparent: true, opacity: 0.5} ) ]); groundMesh.rotation.x = -0.5 * Math.PI; scene.add(groundMesh); // add the output of the renderer to the html element document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); // call the render function var step = 0.03; var sphere; var cube; var group; var bboxMesh; // setup the control gui var controls = new function () { // we need the first child, since it\'s a multimaterial this.cubePosX = 0; this.cubePosY = 3; this.cubePosZ = 10; this.spherePosX = 10; this.spherePosY = 5; this.spherePosZ = 0; this.groupPosX = 10; this.groupPosY = 5; this.groupPosZ = 0; this.grouping = false; this.rotate = false; this.groupScale = 1; this.cubeScale = 1; this.sphereScale = 1; this.redraw = function () { // remove the old plane //scene.remove(sphere); //scene.remove(cube); scene.remove(group); // create a new one sphere = createMesh(new THREE.SphereGeometry(5, 10, 10)); cube = createMesh(new THREE.BoxGeometry(6, 6, 6)); sphere.position.set(controls.spherePosX, controls.spherePosY, controls.spherePosZ); cube.position.set(controls.cubePosX, controls.cubePosY, controls.cubePosZ); // add it to the scene. // also create a group, only used for rotating group = new THREE.Group(); group.add(sphere); group.add(cube); scene.add(group); controls.positionBoundingBox(); //dir, origin, length, color, headLength, headWidth /*ArrowHelper的参数: dir:方向,默认是法向量 origin:开始的坐标位置 length:辅助线的长度 color:辅助线的颜色 headLength:头部的长度 headWidth:头部的宽度 */ var arrow = new THREE.ArrowHelper(new THREE.Vector3(0, 1, 0), group.position, 10, 0x0000ff); scene.add(arrow); }; this.positionBoundingBox = function () { scene.remove(bboxMesh); var box = setFromObject(group);//group中的子对象的坐标变换完毕后,获取到组group的新的边界立方体 var width = box.max.x - box.min.x; var height = box.max.y - box.min.y; var depth = box.max.z - box.min.z; //得到group立方体边界的宽高和深度,根据这些值,生成一个立方几何体 var bbox = new THREE.BoxGeometry(width, height, depth); bboxMesh = new THREE.Mesh(bbox, new THREE.MeshBasicMaterial({ color: "red", vertexColors: THREE.VertexColors, wireframeLinewidth: 2, wireframe: true })); scene.add(bboxMesh); bboxMesh.position.x = ((box.min.x + box.max.x) / 2); bboxMesh.position.y = ((box.min.y + box.max.y) / 2); bboxMesh.position.z = ((box.min.z + box.max.z) / 2); } }; var gui = new dat.GUI(); var sphereFolder = gui.addFolder("sphere"); sphereFolder.add(controls, "spherePosX", -20, 20).onChange(function (e) { sphere.position.x = e; //当球体的坐标发生变化时,应该重新计算组group的范围 //包含区域的最小矩形,该区域应在最小矩形内部 controls.positionBoundingBox() }); sphereFolder.add(controls, "spherePosZ", -20, 20).onChange(function (e) { sphere.position.z = e; controls.positionBoundingBox() }); sphereFolder.add(controls, "spherePosY", -20, 20).onChange(function (e) { sphere.position.y = e; controls.positionBoundingBox() }); sphereFolder.add(controls, "sphereScale", 0, 3).onChange(function (e) { sphere.scale.set(e, e, e); controls.positionBoundingBox() }); var cubeFolder = gui.addFolder("cube"); cubeFolder.add(controls, "cubePosX", -20, 20).onChange(function (e) { cube.position.x = e; controls.positionBoundingBox() }); cubeFolder.add(controls, "cubePosZ", -20, 20).onChange(function (e) { cube.position.z = e; controls.positionBoundingBox() }); cubeFolder.add(controls, "cubePosY", -20, 20).onChange(function (e) { cube.position.y = e; controls.positionBoundingBox() }); cubeFolder.add(controls, "cubeScale", 0, 3).onChange(function (e) { cube.scale.set(e, e, e); controls.positionBoundingBox() }); var cubeFolder = gui.addFolder("group"); cubeFolder.add(controls, "groupPosX", -20, 20).onChange(function (e) { group.position.x = e; controls.positionBoundingBox() }); cubeFolder.add(controls, "groupPosZ", -20, 20).onChange(function (e) { group.position.z = e; controls.positionBoundingBox() }); cubeFolder.add(controls, "groupPosY", -20, 20).onChange(function (e) { group.position.y = e; controls.positionBoundingBox() }); cubeFolder.add(controls, "groupScale", 0, 3).onChange(function (e) { group.scale.set(e, e, e); controls.positionBoundingBox() }); gui.add(controls, "grouping"); gui.add(controls, "rotate"); controls.redraw(); render(); function createMesh(geom) { // assign two materials var meshMaterial = new THREE.MeshNormalMaterial(); meshMaterial.side = THREE.DoubleSide; var wireFrameMat = new THREE.MeshBasicMaterial(); wireFrameMat.wireframe = true; // 创建一个多种材质的网格 var plane = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial, wireFrameMat]); return plane; } function render() { stats.update(); if (controls.grouping && controls.rotate) { group.rotation.y += step; } if从对象创建一个网格数组(THREE.JS 和 GLTF)three.js - 网格组示例? (THREE.Object3D() 高级)
Three.js 加载已经三角剖分的网格是不是比使用四边形的网格更高效?