zoukankan      html  css  js  c++  java
  • 初探three.js几何体

    今天说说three.js的几何体,常见的几何体今天就不说了,今天说一说如何画直线,圆弧线,以及高级几何体。

    1. 画一条直线

    画直线我们使用THREE.Geometry()对象。

    //给空白几何体添加点信息,geometry会把这些点自动组合成线。
    var material = new THREE.LineBasicMaterial({color: 0x00ff00});
    var geometry = new THREE.Geometry();
    geometry.vertices.push(new THREE.Vector3(0,0,0));
    geometry.vertices.push(new THREE.Vector3(10,10,10));
    geometry.vertices.push(new THREE.Vector3(0,20,0));
    var line = new THREE.Line(geometry, material);

    这样就在空间画出了一条折线。

    2.画一条圆弧线

    画圆弧线我们借助THREE.ArcCurve()对象。这个对象有点类似于d3.js中的布局(layout),它的本质就是根据参数生成一系列点坐标,他有一些方法.getPoints()从圆弧线均匀获得圆弧上面点的坐标。下面是THREE.ArcCurve()的部分源码。

    THREE.ArcCurve = function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
    
        THREE.EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
    
    };

    我们可以知道有6个参数,并且继承自THREE.EllipseCurve()。加下来我们来画圆弧。

    var arc = new THREE.ArcCurve(0, 0, 30, 0, Math.PI * 2, true);
    var points = arc.getPoints(1000);
    var ring = new THREE.Geometry();
    points.forEach(v => ring.vertices.push(new THREE.Vector3(v.x,0,v.y)));
    var mat = new THREE.LineBasicMaterial({color: 0x999900});
    var line = new THREE.LineLoop(ring, mat);

    注意points都是XY平面上面的点。最后使用THREE.LineLoop来绘制圆弧线。

    3. 使用ConvexGeometry()凸包

    什么是凸包?简单地说凸包就是,在空间中每三个不在一条直线的点都可以组成一个平面,如果空间中有一组点,那么会组成很多平面,如果平面不透明,我们只能看到最外层的若干个面,这个面组成的几个体就是凸包。

    like this !(这个只是加了岩石纹理)

    凸包使用起来非常简单

    let asteroidMate = new THREE.MeshBasicMaterial();
    let points = [];
    let rad = Math.pow(Math.random(), 3) * ASTERIODRADIUS;
    for(var j=0; j<30; j++) {
        points.push(new THREE.Vector3(Math.random() * 10, Math.random() * 10, Math.random() * 10))
    }
    var asteroidGeom = new THREE.ConvexGeometry(points);
    
    var asterMesh = new THREE.Mesh(asteroidGeom, asteroidMate);

    这就是30个点组成的随机凸包。大家可以试试用它来自定义图形或者制作随机图形。

    4. LatheGeometry() 旋转体

    旋转体就是将由一组点组成的线绕固定轴旋转形成的几何体,LatheGeometry有4个参数,第一个是points点数组,第二个是分段数,第三个是旋转开始角度,第四个是旋转角度。

    ar points = [];
    for(var i=-12; i<=10; i = i + 0.5) {
        if(i < 0) {
            console.log(Math.sqrt(36 - Math.pow(i + 6, 2)) * 1.2, i)
            points.push(new THREE.Vector3(Math.sqrt(36 - Math.pow(i + 6, 2)) * 1.2, i))
        } else if(i < 8 && i >= 0) {
            console.log(Math.sqrt(16 - Math.pow(i - 4, 2)) * 1.2, i)
            points.push(new THREE.Vector3(Math.sqrt(16 - Math.pow(i - 4, 2)) * 1.2, i))
        } else {
            console.log(Math.sqrt(1 - Math.pow(i - 9, 2)) * 1.2, i)
            points.push(new THREE.Vector3(Math.sqrt(1 - Math.pow(i - 9, 2)) * 1.2, i))
        }
    }
    var latheGeo = new THREE.LatheGeometry(points, 30, 0, Math.PI * 2);
    latheMesh = createMesh(latheGeo);;

    5. ExtrudeGeometry()拉伸几何体

    拉伸几何体就是将一个几何体沿着Z轴拉伸形成的几何体。它的参数比较多但是不难理解。

    var material = new THREE.MeshNormalMaterial();
    var shapeGeomery = new THREE.Shape();
    shape.moveTo(-10, -10);
    shape.lineTo(10, -10);
    shape.lineTo(10, 10);
    shape.lineTo(-10,10);
    shape.lineTo(-10, -10);
    var geometry = new THREE.ExtrudeGeometry(shapeGeomery, {
        amount: 2, //拉伸的深度
        bevelThickness: 2,  //斜角的深度
        bevelSize: 3,  //斜角的高度
        bevelSegments: 30,  //斜角分段数
        bevelEnabled: true, //开启斜角
        curveSegments: 12,  //拉伸的段数
        steps: 1  //沿深度方向的段数
    })
    var shape = new THREE.Mesh(geometry, material);

    这里注意几点,
    1.ExtrudeGeometry()的第一个参数是一个shape对象,
    2.区分一下这三个分段数,bevelSegments是斜角的分段,它影响斜角的光滑程度,curveSegments是拉伸曲线的段数,steps是沿深度方向的段数。

    6.TubeGeometry()沿曲线拉伸

    这个方法很简单,就是验证曲线拉伸成一根管,简单的东西直接上代码

    var points = [];
    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);
    
        points.push(new THREE.Vector3(randomX, randomY, randomZ));
    }
    var tubeGeometry = new THREE.TubeGeometry(new THREE.SplineCurve3(points), 64, 3, 16, false);
    var meshMaterial = new THREE.MeshBasicMaterial({color: 0x00ff00, transparent: true, opacity: 0.2});
    var tubeMesh = new THREE.Mesh(tubeGeometry, meshMaterial)

    这里只需注意TubeGeometry()的第一个参数是一个SplineCurve3对象,需要将三维点数组用SplineCurve3处理成三维曲线。

    7.ParametricGeometry()基于等式的几何体

    这个东西类似于高数中的参数方程,通过三阶等式来创建空间曲面,使用ParametricGeometry()的时候,我特意使用了v69版本和v104两个版本,使用方法是不同的。下面我们从代码中寻找区别。

    // v69
    var oldVersion = function (u, v) {
        var x = u * 50 - 25;
        var z = v * 50 - 25;
        var y = Math.sin(u * 50 - 25) + Math.sin(v * 50 - 25) +  Math.pow((Math.pow((u - 0.5), 2) + Math.pow((v - 0.5), 2)) * 10, 2) - 10;
        return new THREE.Vector3(x, y, z);
    };
    var geometry = new THREE.ParametricGeometry(oldVersion, 120, 120)
    var newVersion = function (u, v, target) {
        var x = u * 50 - 25;
        var z = v * 50 - 25;
        var y = Math.sin(u * 50 - 25) + Math.sin(v * 50 - 25) +  Math.pow((Math.pow((u - 0.5), 2) + Math.pow((v - 0.5), 2)) * 10, 2) - 10;
        target.set(x,y,z);
    };
    var geometry = new THREE.ParametricGeometry(newVersion, 120, 120)

    可以看出方法中传递了第三个参数,这里使用set方法做了优化,(所以说每当出现新的js标准后,都出新生一些框架或者出现新版本)。相信喜欢数学的小伙伴都会非常喜欢这个几何体。下面随便展示一个demo

    ### 8. 组合网格
    未完待续。。。(这将是一个非常有意思的几何体)
    ### 9. Geometry()实现自定义面
    未完待续。。。(同样可以很发散)

    更多demo请移步至原文

    转载请注明原文地址 http://www.bettersmile.cn 郭志强的博客

  • 相关阅读:
    小工具合集使用体验
    php计算金额精度丢失问题与二维数组排序
    layui treeSelect
    thinkphp5.1 使用小记
    thinkphp软删除
    移动端meta标签设置
    (kotlin异常) java.lang.NoSuchFieldError: No static field xxx of type I in class Lcom/XX/R$id; or its superclasses
    微信小程序map地图的一些使用注意事项
    修改UIScrollView 的手势代理
    awk命令详解
  • 原文地址:https://www.cnblogs.com/vadim-web/p/12064604.html
Copyright © 2011-2022 走看看