本章的主要内容:
一,高级几何体-凸面体ConvexGeometry,扫描体LatheGeometry,管状几何体TubeGeometry;
二,使用拉伸几何体ExtrudeGeometry将一个二维图形生成三维图形,并基于从外部引入的SVG图片生成一个三维图形;
三,基于three.js提供的ParamtericGeometry对象的公式定制自己的图形
四,使用TextGeometry创建三维文字
五,使用二元操作从已有的几何体中创建出新的几何体;
1 ConvexGeometry--凸面体
<!DOCTYPE html> <html> <head> <title>Example 06.01 - Advanced 3D geometries - Convex Hull</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/ConvexGeometry.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; // position and point the camera to the center of the scene camera.position.x = -30; camera.position.y = 40; camera.position.z = 50; camera.lookAt(new THREE.Vector3(10, 0, 0)); // add the output of the renderer to the html element document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); // call the render function var step = 0; // the points group var spGroup; // the mesh var hullMesh; generatePoints(); // setup the control gui var controls = new function () { // we need the first child, since it's a multimaterial this.redraw = function () { scene.remove(spGroup); scene.remove(hullMesh); generatePoints(); }; }; var gui = new dat.GUI(); gui.add(controls, 'redraw'); render(); function generatePoints() { // add 10 random spheres var points = []; //生成20个随机点 for (var i = 0; i < 20; i++) { var randomX = -15 + Math.round(Math.random() * 30); var randomY = -15 + Math.round(Math.random() * 30); var randomZ = -15 + Math.round(Math.random() * 30); points.push(new THREE.Vector3(randomX, randomY, randomZ)); } //将这些随机点用红色的小圆球来标识,将这些标识点的小圆球添加到集合中,然后再将该集合追加到场景中 spGroup = new THREE.Object3D(); var material = new THREE.MeshBasicMaterial({color: 0xff0000, transparent: false}); //每一个点都生成一个红色的圆球来标识该点 points.forEach(function (point) { var spGeom = new THREE.SphereGeometry(0.2); var spMesh = new THREE.Mesh(spGeom, material); //网格的位置复制该点的位置 spMesh.position.copy(point); spGroup.add(spMesh); }); // add the points as a group to the scene scene.add(spGroup); // use the same points to create a convexgeometry //利用这些随机点生成一个凸面体,注意这些随机点是ConvexGeometry的参数 var hullGeometry = new THREE.ConvexGeometry(points); hullMesh = createMesh(hullGeometry); scene.add(hullMesh); } function createMesh(geom) { // assign two materials var meshMaterial = new THREE.MeshBasicMaterial({color: 0x00ff00, transparent: true, opacity: 0.2}); meshMaterial.side = THREE.DoubleSide; var wireFrameMat = new THREE.MeshBasicMaterial(); wireFrameMat.wireframe = true; // create a multimaterial var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial, wireFrameMat]); return mesh; } function render() { stats.update(); spGroup.rotation.y = step; hullMesh.rotation.y = step += 0.01; // render using requestAnimationFrame requestAnimationFrame(render); webGLRenderer.render(scene, camera); } function initStats() { var stats = new Stats(); stats.setMode(0); // 0: fps, 1: ms // Align top-left stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats; } } window.onload = init; </script> </body> </html>
2 LatheGeometry---扫描体
通过LatheGeometry你可以从一条光滑曲线开始创建图形,该曲线成为样条曲线,当该曲线绕一个固定点进行旋转就形成一个类似于花瓶的图形
注意,该函数有两个地方不明白,1 绕固定点进行旋转,这个固定点是谁,是否可以指定,2 gui中的segments中的step(1)是什么含义
属性 | 描述 |
points | 构成样条曲线的点的集合 |
segments | 分段数,段数越高,图形越光滑 |
phiStart | 开始角度 |
phiLength | 创建多大角度的图形 |
<!DOCTYPE html> <html> <head> <title>Example 06.02 - Advanced 3D geometries - Lathe</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; // position and point the camera to the center of the scene camera.position.x = -30; camera.position.y = 40; camera.position.z = 50; camera.lookAt(new THREE.Vector3(10, 0, 0)); // add the output of the renderer to the html element document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); // call the render function var step = 0; // the points group var spGroup; // the mesh var latheMesh; generatePoints(12, 2, 2 * Math.PI); // setup the control gui var controls = new function () { // we need the first child, since it's a multimaterial this.segments = 12; this.phiStart = 0; this.phiLength = 2 * Math.PI; this.redraw = function () { scene.remove(spGroup); scene.remove(latheMesh); generatePoints(controls.segments, controls.phiStart, controls.phiLength); }; }; var gui = new dat.GUI(); //以往gui的代码大致都能看懂,但是这里使用了一个step(1),不知道是什么含义 gui.add(controls, 'segments', 0, 50).step(1).onChange(controls.redraw); gui.add(controls, 'phiStart', 0, 2 * Math.PI).onChange(controls.redraw); gui.add(controls, 'phiLength', 0, 2 * Math.PI).onChange(controls.redraw); render(); function generatePoints(segments, phiStart, phiLength) { // add 10 random spheres var points = []; var height = 5; var count = 30; for (var i = 0; i < count; i++) { //x轴是正弦函数与余弦函数的结合 //z轴是基于变量i和count var x=(Math.sin(i * 0.2) + Math.cos(i * 0.3)) * height + 12; var y=0; var z=( i - count ) + count / 2 var point=new THREE.Vector3(x, y, z); points.push(point); } spGroup = new THREE.Object3D(); var material = new THREE.MeshBasicMaterial({color: 0xff0000, transparent: false}); points.forEach(function (point) { var spGeom = new THREE.SphereGeometry(0.2); var spMesh = new THREE.Mesh(spGeom, material); spMesh.position.copy(point); spGroup.add(spMesh); }); // add the points as a group to the scene scene.add(spGroup); // use the same points to create a LatheGeometry var latheGeometry = new THREE.LatheGeometry(points, segments, phiStart, phiLength); latheMesh = createMesh(latheGeometry); scene.add(latheMesh); } function createMesh(geom) { // assign two materials // var meshMaterial = new THREE.MeshBasicMaterial({color:0x00ff00, transparent:true, opacity:0.6}); var meshMaterial = new THREE.MeshNormalMaterial(); meshMaterial.side = THREE.DoubleSide; var wireFrameMat = new THREE.MeshBasicMaterial(); wireFrameMat.wireframe = true; // create a multimaterial var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial, wireFrameMat]); return mesh; } function render() { stats.update(); spGroup.rotation.x = step; latheMesh.rotation.x = step += 0.01; // render using requestAnimationFrame requestAnimationFrame(render); webGLRenderer.render(scene, camera); } function initStats() { var stats = new Stats(); stats.setMode(0); // 0: fps, 1: ms // Align top-left stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats; } } window.onload = init; </script> </body> </html>
3,TubeGeometry--管状几何体
管状几何体是沿着一条三维样条曲线拉伸出一根管子,可以通过指定顶点来定义路径,然后使用TubeGeometry来创建这根管子
属性 | 描述 |
path |
样条曲线, 在下面的demo中,我们使用SplineCurve对象对随机生成的点进行加工,构建出一条光滑曲线, 来作为TubeGeometry的样条曲线 |
segments | 管道的分段数,管道越长,分段数越多才能保持管道的光滑度 |
radius | 管道的半径 |
radiusSegmnts | 管道圆周的分段数,分段数越多,管道越圆 |
closed | 管道的头尾是否连接起来 |
debug | 额外的调试信息是否添加到管道上 |
<!DOCTYPE html> <html> <head> <title>Example 06.04 - Extrude TubeGeometry</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; // position and point the camera to the center of the scene camera.position.x = -30; camera.position.y = 40; camera.position.z = 50; camera.lookAt(new THREE.Vector3(10, 0, 0)); // add the output of the renderer to the html element document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); // call the render function var step = 0; // the points group var spGroup; // the mesh var tubeMesh; // setup the control gui var controls = new function () { this.numberOfPoints = 5; this.segments = 64; this.radius = 1; this.radiusSegments = 8; this.closed = false; this.points = []; // we need the first child, since it's a multimaterial this.newPoints = function () { var points = []; //生成一定数量的点,这些点的x,y,z的坐标都是随机生成的 for (var i = 0; i < controls.numberOfPoints; i++) { var randomX = -20 + Math.round(Math.random() * 50); var randomY = -15 + Math.round(Math.random() * 40); var randomZ = -20 + Math.round(Math.random() * 40); var point=new THREE.Vector3(randomX, randomY, randomZ); points.push(point); } controls.points = points; controls.redraw(); }; this.redraw = function () { scene.remove(spGroup); scene.remove(tubeMesh); generatePoints(controls.points, controls.segments, controls.radius, controls.radiusSegments, controls.closed); }; }; var gui = new dat.GUI(); gui.add(controls, 'newPoints'); gui.add(controls, 'numberOfPoints', 2, 15).step(1).onChange(controls.newPoints); gui.add(controls, 'segments', 0, 200).step(1).onChange(controls.redraw); gui.add(controls, 'radius', 0, 10).onChange(controls.redraw); gui.add(controls, 'radiusSegments', 0, 100).step(1).onChange(controls.redraw); gui.add(controls, 'closed').onChange(controls.redraw); controls.newPoints(); render(); function generatePoints(points, segments, radius, radiusSegments, closed) { // add n random spheres spGroup = new THREE.Object3D(); var material = new THREE.MeshBasicMaterial({color: 0xff0000, transparent: false}); points.forEach(function (point) { var spGeom = new THREE.SphereGeometry(0.2); var spMesh = new THREE.Mesh(spGeom, material); spMesh.position.copy(point); spGroup.add(spMesh); }); // add the points as a group to the scene scene.add(spGroup); // use the same points to create a convexgeometry //SplineCurve3函数的含义是通过一系列的点来创建一条平滑的曲线。 //在这里创建出这条平滑曲线,作为样条曲线参数传递给TubeGeometry,构建管状几何体 points=new THREE.SplineCurve3(points); var tubeGeometry = new THREE.TubeGeometry(points, segments, radius, radiusSegments, closed); tubeMesh = createMesh(tubeGeometry); scene.add(tubeMesh); } function createMesh(geom) { // assign two materials //var meshMaterial = new THREE.MeshNormalMaterial(); var meshMaterial = new THREE.MeshBasicMaterial({color: 0x00ff00, transparent: true, opacity: 0.2}); var wireFrameMat = new THREE.MeshBasicMaterial(); wireFrameMat.wireframe = true; // create a multimaterial var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial, wireFrameMat]); return mesh; } function render() { stats.update(); spGroup.rotation.y = step; tubeMesh.rotation.y = step += 0.01; // render using requestAnimationFrame requestAnimationFrame(render); webGLRenderer.render(scene, camera); } function initStats() { var stats = new Stats(); stats.setMode(0); // 0: fps, 1: ms // Align top-left stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats; } } window.onload = init; </script> </body> </html>
4,ExtrudeGeometry--拉伸几何体
属性 | 描述 |
amount(数量) | 该图形可以拉伸多高,只有一面跟着增减 |
bevelThickness(斜角厚度) |
图形拉伸后形成的中间的拉伸体,该属性标示斜角的深度,斜角就是拉伸体与前后面之间的倒角 amount和bevelThickness的区别没有看的很明白,暂时照抄下来,也许有一天忽然领悟了呢, 不过看着demo,amount,只有一面跟着增减,bevelThickness是两个面都跟着变化
|
bevelSize(斜角尺寸) | 指定斜角的高度,如图所示,是内凹的还是外凸的 ![]() |
bevelSegments(斜角分段数) |
![]() ![]()
|
bevelEnabled(是否应用斜角) | |
curveSegments(曲线分段数) | 拉伸图形时,二维曲线分为多少段 |
step(拉伸体的段数) | 拉伸体被分为多少段,该属性也么有看懂,demo也没有看出差别来 |
extrudePath(拉伸路径) | 该属性定义了图形沿着什么路径拉伸,没有指定的话,就会沿着z轴拉伸 |
material(材质) | 拉伸后立体图形的前后面所使用的材质 |
extrudeMaterial(拉伸材质) | 拉伸体所使用的材质 |
<!DOCTYPE html> <html> <head> <title>Example 06.03 - Extrude Geometry</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; var shape = createMesh(new THREE.ShapeGeometry(drawShape())); // add the sphere to the scene scene.add(shape); // position and point the camera to the center of the scene camera.position.x = -20; camera.position.y = 60; camera.position.z = 60; camera.lookAt(new THREE.Vector3(20, 20, 0)); // add the output of the renderer to the html element document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); // call the render function var step = 0; // setup the control gui var controls = new function () { this.amount = 2; this.bevelThickness = 2; this.bevelSize = 0.5; this.bevelEnabled = true; this.bevelSegments = 3; this.bevelEnabled = true; this.curveSegments = 12; this.steps = 1; this.asGeom = function () { // remove the old plane scene.remove(shape); // create a new one var options = { amount: controls.amount, bevelThickness: controls.bevelThickness, bevelSize: controls.bevelSize, bevelSegments: controls.bevelSegments, bevelEnabled: controls.bevelEnabled, curveSegments: controls.curveSegments, steps: controls.steps }; shape = createMesh(new THREE.ExtrudeGeometry(drawShape(), options)); // add it to the scene. scene.add(shape); }; }; var gui = new dat.GUI(); gui.add(controls, 'amount', 0, 20).onChange(controls.asGeom); gui.add(controls, 'bevelThickness', 0, 10).onChange(controls.asGeom); gui.add(controls, 'bevelSize', 0, 10).onChange(controls.asGeom); gui.add(controls, 'bevelSegments', 0, 30).step(1).onChange(controls.asGeom); gui.add(controls, 'bevelEnabled').onChange(controls.asGeom); gui.add(controls, 'curveSegments', 1, 30).step(1).onChange(controls.asGeom); gui.add(controls, 'steps', 1, 5).step(1).onChange(controls.asGeom); controls.asGeom(); render(); function drawShape() { // create a basic shape var shape = new THREE.Shape(); // startpoint shape.moveTo(10, 10); // straight line upwards shape.lineTo(10, 40); // the top of the figure, curve to the right shape.bezierCurveTo(15, 25, 25, 25, 30, 40); // spline back down shape.splineThru( [new THREE.Vector2(32, 30), new THREE.Vector2(28, 20), new THREE.Vector2(30, 10), ]); // curve at the bottom shape.quadraticCurveTo(20, 15, 10, 10); // add 'eye' hole one var hole1 = new THREE.Path(); hole1.absellipse(16, 24, 2, 3, 0, Math.PI * 2, true); shape.holes.push(hole1); // add 'eye hole 2' var hole2 = new THREE.Path(); hole2.absellipse(23, 24, 2, 3, 0, Math.PI * 2, true); shape.holes.push(hole2); // add 'mouth' var hole3 = new THREE.Path(); hole3.absarc(20, 16, 2, 0, Math.PI, true); shape.holes.push(hole3); // return the shape return shape; } function createMesh(geom) { geom.applyMatrix(new THREE.Matrix4().makeTranslation(-20, 0, 0)); // assign two materials var meshMaterial = new THREE.MeshNormalMaterial({ shading: THREE.FlatShading, transparent: true, opacity: 0.7 }); // meshMaterial.side = THREE.DoubleSide; var wireFrameMat = new THREE.MeshBasicMaterial(); wireFrameMat.wireframe = true; // create a multimaterial var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial]); return mesh; } function createLine(shape, spaced) { if (!spaced) { //使用shape的createPointsGeometry方法,将图形转化为一个点集,作为参数传递给Line var mesh = new THREE.Line(shape.createPointsGeometry(), new THREE.LineBasicMaterial({ color: 0xff3333, linewidth: 2 })); return mesh; } else { var mesh = new THREE.Line(shape.createSpacedPointsGeometry(20), new THREE.LineBasicMaterial({ color: 0xff3333, linewidth: 2 })); return mesh; } } function render() { stats.update(); shape.rotation.y = step += 0.01; // render using requestAnimationFrame requestAnimationFrame(render); webGLRenderer.render(scene, camera); } function initStats() { var stats = new Stats(); stats.setMode(0); // 0: fps, 1: ms // Align top-left stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats; } } window.onload = init; </script> </body> </html>
5,引入svg文件构建路径,然后使用extrudeGeometry来构建立体图形,
由于本人是svg小白一只,所以这里不对svg做解读,其实与上面的demo使用Shape构建路径一样,
只是一个使用svg构建二维图形,一个使用Shape构建二维图形,二维图形构建出来以后,使用ExtrudeGeometry对二维图形进行拉伸就没有区别了
<!DOCTYPE html> <html> <head> <title>Example 06.05 - Extrude SVG</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> <script type="text/javascript" src="../libs/d3-threeD.js"></script> <script type="text/javascript" src="../libs/OrbitControls.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> <div id="batman" style="display:none"> <svg version="1.0" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1152px" height="1152px" xml:space="preserve"> <g> <path id="batman-path" style="fill:rgb(0,0,0);" d="M 261.135 114.535 C 254.906 116.662 247.491 118.825 244.659 119.344 C 229.433 122.131 177.907 142.565 151.973 156.101 C 111.417 177.269 78.9808 203.399 49.2992 238.815 C 41.0479 248.66 26.5057 277.248 21.0148 294.418 C 14.873 313.624 15.3588 357.341 21.9304 376.806 C 29.244 398.469 39.6107 416.935 52.0865 430.524 C 58.2431 437.23 63.3085 443.321 63.3431 444.06 C 63.4748 446.883 102.278 479.707 120.51 492.418 C 131.003 499.734 148.168 509.93 158.654 515.075 C 169.139 520.22 179.431 525.34 181.524 526.454 C 187.725 529.754 187.304 527.547 179.472 515.713 C 164.806 493.553 158.448 464.659 164.322 446.861 C 169.457 431.303 192.013 421.501 214.324 425.132 C 234.042 428.341 252.142 439.186 270.958 459.064 C 286.677 475.67 292.133 482.967 295.31 491.634 C 297.466 497.514 298.948 495.91 304.862 481.293 C 313.673 459.519 329.808 445.735 346.35 445.851 C 367.654 446 399.679 478.239 412.801 512.745 C 414.093 516.144 416.593 522.632 418.355 527.163 C 420.118 531.695 423.604 542.319 426.103 550.773 C 430.848 566.832 432.355 566.851 434.872 550.88 C 436.395 541.215 451.403 502.522 455.655 497.298 C 457.038 495.599 460.63 489.896 463.636 484.625 C 471.696 470.498 492.318 452.688 505.387 448.568 C 514.602 445.663 517.533 445.549 525.51 447.782 C 539.676 451.749 553.43 467.773 560.706 488.788 L 563.242 496.114 L 567.096 490.012 C 577.709 473.208 593.665 453.899 602.47 447.206 C 607.884 443.09 613.378 438.825 614.679 437.729 C 615.98 436.632 622.927 433.259 630.118 430.233 C 655.159 419.693 681.195 423.407 693.273 439.241 C 697.957 445.382 698.932 448.971 699.538 462.294 C 700.174 476.284 699.51 479.864 693.686 493.854 C 690.073 502.533 684.912 512.883 682.217 516.854 C 679.523 520.825 678.172 524.074 679.215 524.074 C 681.932 524.074 718.787 504.481 732.525 495.734 C 760.018 478.228 788.909 452.599 803.9 432.418 C 807.266 427.886 810.569 423.715 811.239 423.149 C 814.498 420.395 828.253 393.099 833.17 379.627 C 838.223 365.782 838.713 361.822 838.741 334.582 C 838.776 300.425 836.431 291.124 820.154 260.873 C 810.649 243.207 807.498 239.005 788.417 218.543 C 751.511 178.968 688.147 142.549 621.582 122.654 C 581.7 110.734 580.388 110.465 580.388 114.195 C 580.388 115.328 581.302 116.255 582.418 116.255 C 584.279 116.255 587.705 122.106 603.399 152.085 C 613.977 172.29 618.077 189.427 618.264 214.21 C 618.42 234.928 617.88 238.368 612.285 252.269 C 604.327 272.04 590.066 286.889 572.829 293.352 C 558.526 298.714 549.193 297.86 535.704 289.955 C 526.777 284.723 512.304 267.644 509.816 259.404 C 509.132 257.138 507.129 251.358 505.366 246.558 C 503.602 241.759 501.646 231.564 501.018 223.902 C 500.39 216.24 498.491 198.402 496.797 184.261 C 495.104 170.121 493.307 152.047 492.803 144.097 C 492.299 136.147 491.292 125.625 490.565 120.715 L 489.242 111.787 L 483.323 118.267 C 480.067 121.832 477.404 125.618 477.404 126.681 C 477.404 127.744 476.603 128.613 475.624 128.613 C 474.645 128.613 471.275 132.321 468.135 136.852 L 462.426 145.091 L 431.038 145.091 L 399.65 145.091 L 386.811 128.494 C 379.749 119.365 373.509 112.36 372.943 112.926 C 372.377 113.491 371.57 118.875 371.15 124.888 C 370.73 130.902 368.94 147.744 367.172 162.315 C 365.405 176.887 363.523 195.424 362.99 203.509 C 360.283 244.622 352.784 266.044 335.323 282.544 C 326.456 290.923 312.488 297.497 303.508 297.518 C 294.864 297.539 278.732 290.063 269.473 281.748 C 246.952 261.521 238.846 229.614 245.481 187.314 C 247.894 171.928 266.562 131.612 275.927 121.56 C 277.987 119.348 279.673 116.786 279.673 115.867 C 279.673 114.947 279.905 113.593 280.188 112.856 C 281.28 110.017 271.977 110.837 261.136 114.536 L 261.135 114.535 "/> </g> </svg> </div> <!-- Javascript code that runs our Three.js examples --> <script type="text/javascript"> var orbit; // 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; var shape = createMesh(new THREE.ShapeGeometry(drawShape())); // add the sphere to the scene scene.add(shape); // position and point the camera to the center of the scene camera.position.x = -80; camera.position.y = 80; camera.position.z = 80; camera.lookAt(new THREE.Vector3(60, -60, 0)); var spotLight = new THREE.DirectionalLight(0xffffff); spotLight.position = new THREE.Vector3(70, 170, 70); spotLight.intensity = 0.7; spotLight.target = shape; scene.add(spotLight); // add the output of the renderer to the html element document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); orbit = new THREE.OrbitControls(camera, webGLRenderer.domElement); // call the render function var step = 0; // setup the control gui var controls = new function () { this.amount = 2; this.bevelThickness = 2; this.bevelSize = 0.5; this.bevelEnabled = true; this.bevelSegments = 3; this.bevelEnabled = true; this.curveSegments = 12; this.steps = 1; this.asGeom = function () { // remove the old plane scene.remove(shape); // create a new one var options = { amount: controls.amount, bevelThickness: controls.bevelThickness, bevelSize: controls.bevelSize, bevelSegments: controls.bevelSegments, bevelEnabled: controls.bevelEnabled, curveSegments: controls.curveSegments, steps: controls.steps }; shape = createMesh(new THREE.ExtrudeGeometry(drawShape(), options)); // add it to the scene. scene.add(shape); }; }; var gui = new dat.GUI(); gui.add(controls, 'amount', 0, 20).onChange(controls.asGeom); gui.add(controls, 'bevelThickness', 0, 10).onChange(controls.asGeom); gui.add(controls, 'bevelSize', 0, 10).onChange(controls.asGeom); gui.add(controls, 'bevelSegments', 0, 30).step(1).onChange(controls.asGeom); gui.add(controls, 'bevelEnabled').onChange(controls.asGeom); gui.add(controls, 'curveSegments', 1, 30).step(1).onChange(controls.asGeom); gui.add(controls, 'steps', 1, 5).step(1).onChange(controls.asGeom); controls.asGeom(); render(); function drawShape() { var svgString = document.querySelector("#batman-path").getAttribute("d"); var shape = transformSVGPathExposed(svgString); // return the shape return shape; } function createMesh(geom) { geom.applyMatrix(new THREE.Matrix4().makeTranslation(-390, -74, 0)); // assign two materials var meshMaterial = new THREE.MeshPhongMaterial({color: 0x333333, shininess: 100, metal: true}); var mesh = new THREE.Mesh(geom, meshMaterial); mesh.scale.x = 0.1; mesh.scale.y = 0.1; mesh.rotation.z = Math.PI; mesh.rotation.x = -1.1; return mesh; } function render() { stats.update(); shape.rotation.y = step += 0.005; orbit.update(); // render using requestAnimationFrame requestAnimationFrame(render); webGLRenderer.render(scene, camera); } function initStats() { var stats = new Stats(); stats.setMode(0); // 0: fps, 1: ms // Align top-left stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats; } } window.onload = init; </script> </body> </html>
6 ParametricGeometry
属性 | 描述 |
function | 一个函数,以u,v为参数,其中u,v的值是0-1,返回一个Vector3的点对象 |
slices | u分为多少份 |
stacks | v分为多少份,分的份数越多,创建出来的图形越光滑 |
useTris | 是否使用三角面片,在前面几章中,我们了解过构建面有两种方法,三角面或者是四边形 |
<!DOCTYPE html> <html> <head> <title>Example 06.06 - Parametric geometries</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; // position and point the camera to the center of the scene camera.position.x = -30; camera.position.y = 50; camera.position.z = 50; camera.lookAt(new THREE.Vector3(10, -20, 0)); var spotLight = new THREE.DirectionalLight(); spotLight.position = new THREE.Vector3(-20, 250, -50); spotLight.target.position.x = 30; spotLight.target.position.y = -40; spotLight.target.position.z = -20; spotLight.intensity = 0.3; scene.add(spotLight); // add the output of the renderer to the html element document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); // call the render function var step = 0; // setup the control gui var controls = new function () { }; var gui = new dat.GUI(); var width=10;var depth=10; pp=function(u,v){ var x=Math.cos(u*v)*width; var y=Math.sin(u)*width; var z=v*depth; return new THREE.Vector3(x,y,z); }; klein = function (u, v) { u *= Math.PI; v *= 2 * Math.PI; u = u * 2; var x, y, z; if (u < Math.PI) { x = 3 * Math.cos(u) * (1 + Math.sin(u)) + (2 * (1 - Math.cos(u) / 2)) * Math.cos(u) * Math.cos(v); z = -8 * Math.sin(u) - 2 * (1 - Math.cos(u) / 2) * Math.sin(u) * Math.cos(v); } else { x = 3 * Math.cos(u) * (1 + Math.sin(u)) + (2 * (1 - Math.cos(u) / 2)) * Math.cos(v + Math.PI); z = -8 * Math.sin(u); } y = -2 * (1 - Math.cos(u) / 2) * Math.sin(v); return new THREE.Vector3(x, y, z); }; radialWave = function (u, v) { var r = 50; var x = Math.sin(u) * r; var z = Math.sin(v / 2) * 2 * r; var y = (Math.sin(u * 4 * Math.PI) + Math.cos(v * 2 * Math.PI)) * 2.8; return new THREE.Vector3(x, y, z); }; //var mesh = createMesh(new THREE.ParametricGeometry(radialWave, 120, 120, false)); var mesh = createMesh(new THREE.ParametricGeometry(pp, 120, 120, false)); scene.add(mesh); render(); function createMesh(geom) { geom.applyMatrix(new THREE.Matrix4().makeTranslation(-25, 0, -25)); // assign two materials // var meshMaterial = new THREE.MeshLambertMaterial({color: 0xff5555}); //var meshMaterial = new THREE.MeshNormalMaterial(); var meshMaterial = new THREE.MeshPhongMaterial({ specular: 0xaaaafff, color: 0x3399ff, shininess: 40, metal: true }); meshMaterial.side = THREE.DoubleSide; // create a multimaterial var plane = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial]); return plane; } function render() { stats.update(); mesh.rotation.y = step += 0.01; mesh.rotation.x = step; // render using requestAnimationFrame requestAnimationFrame(render); webGLRenderer.render(scene, camera); } function initStats() { var stats = new Stats(); stats.setMode(0); // 0: fps, 1: ms // Align top-left stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats; } } window.onload = init; </script> </body> </html>
7 TextGeometry---渲染文本
属性 | 描述 |
size | 文本大小 |
height | 拉伸的长度 |
weight | 字体权重,normal/bold/bolder等 |
font | 字体名称 |
style | 字体样式,normal/italic |
bevelThickness | 斜角深度 |
bevelSize | 斜角高度 |
bevelSegments | 斜角的分段数 |
bevelEnabled | 是否使用斜角 |
curveSegments | 曲线分段数 |
steps | 拉伸分段数 |
extrudePath | 拉伸路径 |
material | 拉伸体前后面的材质 |
extrudeMaterial | 拉伸体中间的材质 |
<!DOCTYPE html> <html> <head> <title>Example 06.07 - Text geometry</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> <script type="text/javascript" src="../assets/fonts/helvetiker_regular.typeface.js"></script> <script type="text/javascript" src="../assets/fonts/helvetiker_bold.typeface.js"></script> <script type="text/javascript" src="../assets/fonts/bitstream_vera_sans_mono_roman.typeface.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(0x000000, 1.0)); webGLRenderer.setSize(window.innerWidth, window.innerHeight); webGLRenderer.shadowMapEnabled = true; // position and point the camera to the center of the scene camera.position.x = 100; camera.position.y = 300; camera.position.z = 600; camera.lookAt(new THREE.Vector3(400, 0, -300)); var dirLight = new THREE.DirectionalLight(); dirLight.position.set(25, 23, 15); scene.add(dirLight); var dirLight2 = new THREE.DirectionalLight(); dirLight2.position.set(-25, 23, 15); scene.add(dirLight2); // add the output of the renderer to the html element document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); // call the render function var step = 0; var text1; var text2; var controls = new function () { this.size = 90; this.height = 90; this.bevelThickness = 2; this.bevelSize = 0.5; this.bevelEnabled = true; this.bevelSegments = 3; this.bevelEnabled = true; this.curveSegments = 12; this.steps = 1; this.font = "helvetiker"; this.weight = "normal"; // this.style = "italics"; this.asGeom = function () { // remove the old plane scene.remove(text1); scene.remove(text2); // create a new one var options = { size: controls.size, height: controls.height, weight: controls.weight, font: controls.font, bevelThickness: controls.bevelThickness, bevelSize: controls.bevelSize, bevelSegments: controls.bevelSegments, bevelEnabled: controls.bevelEnabled, curveSegments: controls.curveSegments, steps: controls.steps }; console.log(THREE.FontUtils.faces); text1 = createMesh(new THREE.TextGeometry("Learning", options)); text1.position.z = -100; text1.position.y = 100; scene.add(text1); text2 = createMesh(new THREE.TextGeometry("Three.js", options)); scene.add(text2); }; }; controls.asGeom(); var gui = new dat.GUI(); gui.add(controls, 'size', 0, 200).onChange(controls.asGeom); gui.add(controls, 'height', 0, 200).onChange(controls.asGeom); gui.add(controls, 'font', ['bitstream vera sans mono', 'helvetiker']).onChange(controls.asGeom); gui.add(controls, 'bevelThickness', 0, 10).onChange(controls.asGeom); gui.add(controls, 'bevelSize', 0, 10).onChange(controls.asGeom); gui.add(controls, 'bevelSegments', 0, 30).step(1).onChange(controls.asGeom); gui.add(controls, 'bevelEnabled').onChange(controls.asGeom); gui.add(controls, 'curveSegments', 1, 30).step(1).onChange(controls.asGeom); gui.add(controls, 'steps', 1, 5).step(1).onChange(controls.asGeom); render(); function createMesh(geom) { // assign two materials // var meshMaterial = new THREE.MeshLambertMaterial({color: 0xff5555}); // var meshMaterial = new THREE.MeshNormalMaterial(); var meshMaterial = new THREE.MeshPhongMaterial({ specular: 0xffffff, color: 0xeeffff, shininess: 100, metal: true }); // meshMaterial.side=THREE.DoubleSide; // create a multimaterial var plane = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial]); return plane; } function render() { stats.update(); requestAnimationFrame(render); webGLRenderer.render(scene, camera); } function initStats() { var stats = new Stats(); stats.setMode(0); // 0: fps, 1: ms // Align top-left stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats; } } window.onload = init; </script> </body> </html>
7 二元操作
二元操作需要引入ThreeBSP库,地址如下:https://github.com/skalnik/ThreeBSP
二元操作的名称 | 描述 |
intersect相交 |
两个几何体相互交叠的部分就形成了一个相交几何体![]()
|
union联合 |
两个几何体联合起来一起创建的几何体就是联合几何体![]()
|
subtract相减 |
从第一个几何体中减去两个几何体交叠的部分就得到了相减的几何体![]()
|
下面demo中的二元操作都是针对sphere1进行的
<!DOCTYPE html> <html> <head> <title>Example 06.08 - Binary operations</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> <script type="text/javascript" src="../libs/spin.js"></script> <script type="text/javascript" src="../libs/ThreeBSP.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(0x999999, 1.0); webGLRenderer.setSize(window.innerWidth, window.innerHeight); webGLRenderer.shadowMapEnabled = true; var sphere1 = createMesh(new THREE.SphereGeometry(5, 20, 30)); sphere1.position.x = -2; var sphere2 = createMesh(new THREE.SphereGeometry(5, 20, 30)); sphere2.position.set(3, 0, 0); var cube = createMesh(new THREE.BoxGeometry(5, 5, 5)); cube.position.x = -7; var result; // add the sphere to the scene scene.add(sphere1); scene.add(sphere2); scene.add(cube); // position and point the camera to the center of the scene camera.position.x = 0; camera.position.y = 20; camera.position.z = 20; camera.lookAt(new THREE.Vector3(0, 0, 0)); // add the output of the renderer to the html element document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); // call the render function var step = 0; // setup the control gui var controls = new function () { this.sphere1PosX = sphere1.position.x; this.sphere1PosY = sphere1.position.y; this.sphere1PosZ = sphere1.position.z; this.sphere1Scale = 1; this.sphere2PosX = sphere2.position.x; this.sphere2PosY = sphere2.position.y; this.sphere2PosZ = sphere2.position.z; this.sphere2Scale = 1; this.cubePosX = cube.position.x; this.cubePosY = cube.position.y; this.cubePosZ = cube.position.z; this.scaleX = 1; this.scaleY = 1; this.scaleZ = 1; this.actionCube = "subtract"; // add, substract, intersect this.actionSphere = "subtract"; this.showResult = function () { redrawResult(); }; this.hideWireframes = false; this.rotateResult = false; }; var gui = new dat.GUI(); var guiSphere1 = gui.addFolder("Sphere1"); guiSphere1.add(controls, "sphere1PosX", -15, 15).onChange(function () { sphere1.position.set(controls.sphere1PosX, controls.sphere1PosY, controls.sphere1PosZ) }); guiSphere1.add(controls, "sphere1PosY", -15, 15).onChange(function () { sphere1.position.set(controls.sphere1PosX, controls.sphere1PosY, controls.sphere1PosZ) }); guiSphere1.add(controls, "sphere1PosZ", -15, 15).onChange(function () { sphere1.position.set(controls.sphere1PosX, controls.sphere1PosY, controls.sphere1PosZ) }); guiSphere1.add(controls, "sphere1Scale", 0, 10).onChange(function (e) { sphere1.scale.set(e, e, e) }); var guiSphere2 = gui.addFolder("Sphere2"); guiSphere2.add(controls, "sphere2PosX", -15, 15).onChange(function () { sphere2.position.set(controls.sphere2PosX, controls.sphere2PosY, controls.sphere2PosZ) }); guiSphere2.add(controls, "sphere2PosY", -15, 15).onChange(function () { sphere2.position.set(controls.sphere2PosX, controls.sphere2PosY, controls.sphere2PosZ) }); guiSphere2.add(controls, "sphere2PosZ", -15, 15).onChange(function () { sphere2.position.set(controls.sphere2PosX, controls.sphere2PosY, controls.sphere2PosZ) }); guiSphere2.add(controls, "sphere2Scale", 0, 10).onChange(function (e) { sphere2.scale.set(e, e, e) }); guiSphere2.add(controls, "actionSphere", ["subtract", "intersect", "union", "none"]); var guiCube = gui.addFolder("cube"); guiCube.add(controls, "cubePosX", -15, 15).onChange(function () { cube.position.set(controls.cubePosX, controls.cubePosY, controls.cubePosZ) }); guiCube.add(controls, "cubePosY", -15, 15).onChange(function () { cube.position.set(controls.cubePosX, controls.cubePosY, controls.cubePosZ) }); guiCube.add(controls, "cubePosZ", -15, 15).onChange(function () { cube.position.set(controls.cubePosX, controls.cubePosY, controls.cubePosZ) }); guiCube.add(controls, "scaleX", 0, 10).onChange(function (e) { cube.scale.x = e }); guiCube.add(controls, "scaleY", 0, 10).onChange(function (e) { cube.scale.y = e }); guiCube.add(controls, "scaleZ", 0, 10).onChange(function (e) { cube.scale.z = e }); guiCube.add(controls, "actionCube", ["subtract", "intersect", "union", "none"]); gui.add(controls, "showResult"); gui.add(controls, "rotateResult"); gui.add(controls, "hideWireframes").onChange(function () { if (controls.hideWireframes) { sphere1.material.visible = false; sphere2.material.visible = false; cube.material.visible = false; } else { sphere1.material.visible = true; sphere2.material.visible = true; cube.material.visible = true; } }); render(); var spinner; function redrawResult() { showSpinner(); // make the call async to avoid blocking the thread. Need // to set timeout > 1, if not executed immediately. setTimeout(function () { scene.remove(result); //生成球1,球2和方块的BSP对象 var sphere1BSP = new ThreeBSP(sphere1); var sphere2BSP = new ThreeBSP(sphere2); var cube2BSP = new ThreeBSP(cube); var resultBSP; // first do the sphere switch (controls.actionSphere) { case "subtract": //球1减去球2 resultBSP = sphere1BSP.subtract(sphere2BSP); break; case "intersect": //球1与球2相交 resultBSP = sphere1BSP.intersect(sphere2BSP); break; case "union": //球1与球2联合 resultBSP = sphere1BSP.union(sphere2BSP); break; case "none": // noop; } // next do the cube if (!resultBSP) resultBSP = sphere1BSP; switch (controls.actionCube) { case "subtract": //如果球1与球2的二元操作已经进行完毕,那么此处的操作,则是针对球1与球2二元操作后得到的BSP对象的 resultBSP = resultBSP.subtract(cube2BSP); break; case "intersect": resultBSP = resultBSP.intersect(cube2BSP); break; case "union": resultBSP = resultBSP.union(cube2BSP); break; case "none": // noop; } if (controls.actionCube === "none" && controls.actionSphere === "none") { // do nothing } else { //BSP对象还需要使用toMesh函数,使得BSP对象转化为网格对象 result = resultBSP.toMesh(); //由于二元操作后得到的几何体的法向量发生了改变,所以这里需要重新计算点和面的法向量 result.geometry.computeFaceNormals(); result.geometry.computeVertexNormals(); scene.add(result); } hideSpinner(spinner); }, 200); } function createMesh(geom) { // assign two materials var meshMaterial = new THREE.MeshNormalMaterial(); meshMaterial.side = THREE.DoubleSide; var wireFrameMat = new THREE.MeshBasicMaterial({transparency: true, opacity: 0.5, wireframeLinewidth: 0.5}); wireFrameMat.wireframe = true; // create a multimaterial var mesh = new THREE.Mesh(geom, wireFrameMat); return mesh; } function showSpinner() { var opts = { lines: 13, // The number of lines to draw length: 20, // The length of each line width: 10, // The line thickness radius: 30, // The radius of the inner circle corners: 1, // Corner roundness (0..1) rotate: 0, // The rotation offset direction: 1, // 1: clockwise, -1: counterclockwise color: '#000', // #rgb or #rrggbb or array of colors speed: 1, // Rounds per second trail: 60, // Afterglow percentage shadow: false, // Whether to render a shadow hwaccel: false, // Whether to use hardware acceleration className: 'spinner', // The CSS class to assign to the spinner zIndex: 2e9, // The z-index (defaults to 2000000000) top: 'auto', // Top position relative to parent in px left: 'auto' // Left position relative to parent in px }; var target = document.getElementById('WebGL-output'); spinner = new Spinner(opts).spin(target);//这个地方暂时没有看明白,好像使用了另外一个库函数 return spinner; } function hideSpinner(spinner) { spinner.stop(); } function render() { stats.update(); // sphere.rotation.y=step+=0.01; // if (typeof ThreeBSP!='undefined') {console.log(ThreeBSP)}; // console.log(ThreeBSP); if (controls.rotateResult && result) { result.rotation.y += 0.04; // result.rotation.x+=0.04; result.rotation.z -= 0.005; } // render using requestAnimationFrame requestAnimationFrame(render); webGLRenderer.render(scene, camera); } function initStats() { var stats = new Stats(); stats.setMode(0); // 0: fps, 1: ms // Align top-left stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats; } }; window.onload = init(); </script> </body> </html>
相关推荐
第6章 使用高级几何体和二元操作 6.1 ConvexGeometry 6.2 LatheGeometry 6.3 通过拉伸创建几何体 6.4 创建三维文本 6.5 使用二元操作组合网格 6.6 总结 第7章 粒子和粒子系统 7.1 理解粒子 7.2 粒子、粒子...
第二次作业///////
# 压缩文件中包含: 中文文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
内容概要:本文详细介绍了如何使用200smart PLC和威纶通触摸屏实现平面两轴直线插补的功能。首先解释了200smart PLC和威纶通触摸屏的基本概念及其在工业控制中的重要性。接着阐述了平面两轴直线插补的原理,即通过协调X轴和Y轴的运动,使物体沿直线轨迹移动。然后展示了基于PLS指令的具体代码实现,包括初始化设置、脉冲输出配置、中断处理等环节。此外还讨论了威纶通触摸屏在参数设置和实时监控方面的作用。文中提到该方案适用于不需要复杂加减速控制的场景,如旧设备改造或短距离精确定位。 适合人群:从事自动化控制系统开发的技术人员,尤其是熟悉PLC编程和触摸屏应用的工程师。 使用场景及目标:适用于需要进行简单直线运动控制的应用场景,如小型加工中心、激光切割机等。目标是在低成本的前提下,实现较为精准的两轴联动控制。 其他说明:文中提供了详细的代码示例和技术细节,有助于读者理解和实践。同时也提到了一些常见的调试问题及解决方案,帮助开发者规避潜在的风险。
# 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
机器人运动学.ppt
内容概要:本文详细介绍了低速四轮车控制器的设计与实现,涵盖异步电机控制方案、TI 28035系列控制芯片的应用、源代码实现、PCB与原理图设计等方面。文中首先讲解了异步电机的工作原理及其控制方法,如矢量控制(FOC)和直接转矩控制(DTC),并重点讨论了矢量控制的具体实现。随后,介绍了TI 28035系列控制芯片的特点及其在电机控制中的优势,包括高速ADC、ePWM模块等功能。接下来,提供了详细的源代码示例,涉及ADC初始化、PWM配置、SVPWM算法实现等内容。此外,还探讨了PCB与原理图设计中的注意事项,如电源电路、信号采集电路、电机驱动电路等的布局优化。最后,分享了一些调试经验和技巧,如死区时间配置、速度环PI控制、ADC采样同步等问题。 适合人群:具有一定硬件和嵌入式开发经验的研发人员,尤其是从事电机控制系统设计的技术人员。 使用场景及目标:适用于低速四轮车控制器的开发项目,帮助开发者深入了解异步电机控制原理和技术细节,掌握基于TI 28035芯片的实际应用方法,提高系统的性能和稳定性。 其他说明:本文不仅提供了理论知识,还包括大量实用的代码片段和实践经验,有助于读者更好地理解和应用于实际项目中。
踏入智慧校园的新时代,一场科技与教育的深度融合正在悄然上演。本方案以大数据、云计算、AI等前沿技术为基石,为校园管理带来前所未有的变革与便捷。 一、一键智控,校园管理轻松升级 想象一下,只需轻点手机,就能实现校园的全面智控。从教学教务到行政后勤,从师生考勤到校园安全,智慧校园解决方案一网打尽。通过构建统一的数据中台,实现各系统间的无缝对接与数据共享,让繁琐的管理工作变得轻松高效。智能排课、自动考勤、在线审批……一系列智能应用让校园管理如虎添翼,让校长和老师们从繁琐的事务中解放出来,专注于教学创新与质量提升。 二、寓教于乐,学习生活趣味无穷 智慧校园不仅让管理变得更简单,更让学习生活变得趣味无穷。AI赋能的教学系统能根据学生的学习习惯和能力,提供个性化的学习路径与资源推荐,让学习变得更加高效有趣。同时,丰富的课外活动与社团管理模块,让孩子们的课余生活也充满了欢声笑语。从智慧班牌到智能录播,从家校共育到虚拟实验室,智慧校园让每一个角落都充满了探索的乐趣与知识的光芒。 三、安全守护,校园生活无忧无虑 在智慧校园的守护下,校园生活变得更加安全无忧。通过高清视频监控、智能预警系统与人脸识别技术,校园安全得到了全方位保障。无论是外来人员的入侵还是学生的异常行为,都能被及时发现并处理。同时,智能化的健康管理系统还能实时监测师生的健康状况,为校园防疫工作提供有力支持。智慧校园,用科技的力量为每一位师生筑起了一道坚实的安全防线,让校园生活更加安心、舒心。
内容概要:本文深入探讨了基于折射反向学习策略和自适应惯性权重机制改进的蝴蝶优化算法(BOA)。首先介绍了折射对立学习策略用于构建精英种群的方法,通过折射对立操作提高种群质量和多样性。接着阐述了自适应惯性权重机制的作用,即通过动态调整权重来平衡全局搜索和局部开发的能力。文中详细展示了这两种改进策略的具体MATLAB代码实现,并通过23种测试函数进行了性能对比,证明改进后的BOA在复杂多峰函数上表现出显著优势。此外,文章还讨论了改进算法在工程优化问题中的应用实例,如光伏阵列参数优化,展示了其实用价值。 适合人群:对优化算法感兴趣的科研人员、研究生以及从事相关领域的工程师。 使用场景及目标:适用于解决复杂的多峰优化问题,特别是在需要高效求解全局最优解的情况下。目标是提供一种改进的BOA算法,能够更好地应对复杂优化任务,提高求解效率和准确性。 其他说明:文章提供了详细的代码注释和测试数据,便于读者理解和复现实验结果。同时,文中还分享了一些实用的小技巧,如如何调整参数以应对不同类型的优化问题。
uninstall.bat
道路交通标志与安全目标检测数据集 基础信息 数据集名称:道路交通标志与安全目标检测数据集 数据规模: - 训练集:7,625张道路场景图片 - 验证集:1,224张标注图片 - 测试集:1,153张高复杂度场景图片 分类类别: 覆盖72类交通标志与道路安全要素,包括: - 交通禁令标志(禁止超车/停车/掉头等) - 道路类型标识(窄桥/学校区域/施工路段等) - 安全警示标志(急弯/陡坡/落石区域等) - 限速标识(15-120km/h全系列) - 特殊区域标识(人行横道/铁路道口/危险路段) 技术规格: - 标注格式:YOLOv12兼容格式 - 数据来源:真实道路场景采集 - 标注内容:目标检测框+多级分类标签 适用场景 自动驾驶感知系统开发: 训练车辆准确识别复杂道路环境中的交通标志、障碍物和特殊区域,提升自动驾驶决策系统的安全性 智能交通管理系统: 支持开发路况实时分析系统,自动检测道路异常(坑洞/碎石/减速带)和违规行为 驾驶辅助应用研发: 用于开发ADAS系统的核心识别模块,实现限速提醒、危险区域预警、道路类型识别等功能 交通安全研究: 为道路安全算法研究提供基准数据集,支持交通标志识别率统计、道路危险系数评估等研究 数据集优势 全场景覆盖: 包含日间/夜间、城市/乡村、干燥/潮湿等多样化道路场景,覆盖72类高频交通要素 精准时空标注: 每张图片包含精确的YOLO格式标注,支持多目标重叠场景下的精准检测 动态任务适配: 兼容目标检测、标志分类、危险区域分割等多任务需求,支持模型从粗粒度到细粒度学习 高实战价值: 专为自动驾驶和智慧交通场景优化,包含急弯识别、临时施工标志、特殊天气标识等关键检测目标 标注一致性: 通过多阶段质量校验,确保跨场景、跨类别的标注标准统一,降低模型训练噪声
NI机器视觉选型指南VisionBrochure.pdf
# 压缩文件中包含: 中文文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
内容概要:本文详细介绍了西门子1200 PLC与台达MS300变频器之间的Modbus RTU通信配置方法。首先阐述了系统的三层架构,即触摸屏层、PLC控制层和执行层。接着深入讲解了PLC程序的具体实现步骤,包括硬件组态、Modbus主站初始化以及频率写入功能块的设计。对于触摸屏部分,则分别介绍了西门子KTP700和昆仑通态屏的配置要点。此外,还特别强调了变频器参数设置的重要性,并分享了一些常见的调试技巧和注意事项。最后提供了完整的程序框架供参考。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是对PLC编程和变频器通信感兴趣的读者。 使用场景及目标:适用于需要将西门子1200 PLC与台达MS300变频器进行通信集成的实际工程项目中。主要目的是帮助用户掌握Modbus RTU协议的应用,确保两者能够稳定可靠地协同工作。 其他说明:文中不仅包含了详细的理论解释,还有丰富的实践经验分享,如接线规范、参数调整、故障排查等,有助于提高项目的成功率。
内容概要:本文详细介绍了基于滑模观测器(SMO)的永磁同步电机(PMSM)和直流无刷电机(BLDC)的无感FOC控制方案。该方案具有对电机参数不敏感的优势,即使电机参数存在较大误差也能稳定控制。文中提供了完整的C代码实现,涵盖STM32和DSP平台,并附带丰富的参考资料,如原理图、SMO推导过程和Simulink仿真模型。此外,文章还详细解释了滑模观测器的工作原理及其核心代码,启动方式(V/F控制)、双闭环PID控制的具体实现方法,以及一些优化技巧,如抗积分饱和处理和动态调整SMO增益。 适合人群:电机控制领域的研究人员、工程师和技术爱好者,尤其是对无感FOC控制感兴趣的开发者。 使用场景及目标:适用于需要高性能、低成本的电机控制系统的设计和开发。主要目标是帮助读者理解和实现基于滑模观测器的无感FOC控制,提高系统的鲁棒性和稳定性。 其他说明:该方案不仅提供了理论支持,还有详细的代码实现和调试工具,便于快速上手并应用于实际项目中。
内容概要:本文详细探讨了三相离网逆变器的双环控制及其多种控制算法的设计与实现。首先介绍了双环控制的基本概念,包括电压环和电流环的作用以及PI控制器的具体实现方式。接着讨论了参数设计的关键因素,如电压环和电流环的比例系数选择。随后介绍了几种先进的控制算法,如PR(比例谐振)、QPR(准比例谐振)和重复控制,解释了它们的工作原理和应用场景。最后,重点讲述了这些控制算法的离散化实现方法,特别是在数字信号处理器(DSP)或微控制器(MCU)上的具体实现步骤。 适合人群:从事电力电子领域的工程师和技术人员,尤其是对逆变器控制策略感兴趣的读者。 使用场景及目标:适用于研究和开发三相离网逆变器控制系统的技术人员,旨在提高逆变器的性能,改善电能质量和系统稳定性。通过理解和应用文中提到的各种控制算法,可以更好地应对实际应用中的复杂工况。 其他说明:文章不仅提供了理论分析,还附有大量代码示例,帮助读者更好地理解和实现相关控制算法。此外,文中还分享了许多实际调试的经验和技巧,有助于解决实际工程中的常见问题。
1020331428735037HT糙汉合集.iso
内容概要:本文探讨了一种基于多时间尺度的源荷协调优化调度方法,旨在提高电力系统的低碳性能。文中详细介绍了利用Matlab和CPLEX工具实现的调度模型,涵盖日前24小时、日内1小时和实时15分钟三个时间尺度。针对风电并网带来的挑战,提出了碳捕集电厂和需求响应资源的联合优化策略。具体措施包括:通过乙醇胺溶液储碳装置实现碳捕集电厂的灵活运行;采用价格型和激励型需求响应机制进行快速负荷调整;以及通过多目标优化函数平衡经济性和碳排放。此外,还提供了代码实现细节和技术优化建议。 适用人群:适用于从事电力系统优化、低碳能源管理和智能电网研究的专业人士,尤其是那些关注风电并网和碳减排问题的研究人员和技术开发者。 使用场景及目标:该模型主要用于解决风电并网引起的系统灵活性不足问题,通过源荷协调优化调度,实现更高的风电消纳率和更低的碳排放。目标是在保障供电稳定性的前提下,最大化系统经济效益和社会环境效益。 其他说明:文中不仅分享了具体的数学模型和算法实现,还提供了许多实践经验,如并行计算加速、数据预处理技巧、热启动策略等。对于希望深入理解和应用此类优化模型的人来说,这些内容非常有价值。 适合人群:具备一定编程基础,工作1-3年的研发人员。 使用场景及目标:①解决风电并网引起的系统灵活性不足问题;②通过源荷协调优化调度,实现更高的风电消纳率和更低的碳排放;③保障供电稳定性的同时,最大化系统经济效益和社会环境效益。 阅读建议:此资源不仅提供具体的数学模型和算法实现,还分享了许多实践经验,如并行计算加速、数据预处理技巧、热启动策略等。因此,在学习过程中要结合这些内容一起实践,并调试对应的代码。
踏入智慧校园的新时代,一场科技与教育的深度融合正在悄然上演。本方案以大数据、云计算、AI等前沿技术为基石,为校园管理带来前所未有的变革与便捷。 一、一键智控,校园管理轻松升级 想象一下,只需轻点手机,就能实现校园的全面智控。从教学教务到行政后勤,从师生考勤到校园安全,智慧校园解决方案一网打尽。通过构建统一的数据中台,实现各系统间的无缝对接与数据共享,让繁琐的管理工作变得轻松高效。智能排课、自动考勤、在线审批……一系列智能应用让校园管理如虎添翼,让校长和老师们从繁琐的事务中解放出来,专注于教学创新与质量提升。 二、寓教于乐,学习生活趣味无穷 智慧校园不仅让管理变得更简单,更让学习生活变得趣味无穷。AI赋能的教学系统能根据学生的学习习惯和能力,提供个性化的学习路径与资源推荐,让学习变得更加高效有趣。同时,丰富的课外活动与社团管理模块,让孩子们的课余生活也充满了欢声笑语。从智慧班牌到智能录播,从家校共育到虚拟实验室,智慧校园让每一个角落都充满了探索的乐趣与知识的光芒。 三、安全守护,校园生活无忧无虑 在智慧校园的守护下,校园生活变得更加安全无忧。通过高清视频监控、智能预警系统与人脸识别技术,校园安全得到了全方位保障。无论是外来人员的入侵还是学生的异常行为,都能被及时发现并处理。同时,智能化的健康管理系统还能实时监测师生的健康状况,为校园防疫工作提供有力支持。智慧校园,用科技的力量为每一位师生筑起了一道坚实的安全防线,让校园生活更加安心、舒心。
内容概要:本文深入探讨了基于电压矢量定向的并网逆变器矢量控制系统,重点介绍了其基本原理、数学模型、控制策略以及关键技术如锁相环的应用。文中详细讲解了在MATLAB/SIMULINK环境下构建仿真模型的具体步骤,包括坐标变换、电流控制、PWM生成等模块的实现,并分享了仿真过程中的一些经验和优化技巧。最终的仿真结果显示,该系统能够有效提高逆变器输出电流的质量,满足并网要求。 适合人群:电力电子工程师、自动化控制研究人员、高校师生及相关领域的科研工作者。 使用场景及目标:适用于需要深入了解并网逆变器控制原理和技术实现的研究项目,旨在帮助读者掌握基于电压矢量定向的控制方法及其在MATLAB/SIMULINK中的仿真实现。 其他说明:文章不仅提供了理论分析,还结合了大量的实际案例和代码示例,有助于读者更好地理解和应用所学知识。同时,文中提到的一些调试技巧和注意事项对于实际工程项目也有重要参考价值。