61 Three.js 从高级几何体创建THREE.Points

整如你所记得的,THREE.Points基于几何体的顶点来渲染每个粒子。也就是说,我们提供一个复杂的几何体(比如环状扭结或者管),我们就可以基于这个几何体的顶点创建出一个THREE.Points对象。这里写图片描述
如上图所示,每一个用来生成环状扭结的顶点都是一个粒子。这个发光的粒子是我们使用canvas绘制出来的。在案例中查看代码方法generateSprite
然后我们又书写了两个方法,一个是生成正常模型的createMesh方法。
另一个则是,生成粒子模型的createPointCloud,通过在gui中不同的配置,即可生成不同的内容。

案例查看地址:http://www.wjceo.com/blog/threejs/2018-03-12/119.html
案例代码:



<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        html, body {
            margin: 0;
            height: 100%;
        }

        canvas {
            display: block;
        }

    </style>
</head>
<body onload="draw();">
</body>
<script src="/lib/three.js"></script>
<script src="/lib/js/libs/stats.min.js"></script>
<script src="/lib/js/libs/dat.gui.min.js"></script>
<script>
    var renderer;

    function initRender() {
        renderer = new THREE.WebGLRenderer({antialias: true});
        renderer.setClearColor(new THREE.Color(0x000000)); //设置背景颜色
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);
    }

    var camera;

    function initCamera() {
        camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 200);
        camera.position.set(0, 0, 50);
    }

    var scene;

    function initScene() {
        scene = new THREE.Scene();
    }

    var light;

    function initLight() {
        scene.add(new THREE.AmbientLight(0x404040));

        light = new THREE.DirectionalLight(0xffffff);
        light.position.set(1, 1, 1);
        scene.add(light);
    }


    function initModel() {

        //轴辅助 (每一个轴的长度)
        var object = new THREE.AxesHelper(500);
        //scene.add(object);
    }

    //初始化性能插件
    var stats;

    function initStats() {
        stats = new Stats();
        document.body.appendChild(stats.dom);
    }

    //生成gui设置配置项
    var controls,knot;
    function initGui() {
        //声明一个保存需求修改的相关数据的对象
        controls = {
            "radius": 13,
            "tube": 1.7,
            "radialSegments": 156,
            "tubularSegments": 12,
            "p": 3,
            "q": 4,
            "heightScale": 3.5,
            "asParticles": false,
            "rotate": false,
            redraw: function () {
                // 删除掉原有的模型
                if (knot) scene.remove(knot);
                // 创建一个环形结构
                ///<param name ="radius" type="float">环形结半径</param>
                ///<param name ="tube" type="float">环形结弯管半径</param>
                ///<param name ="radialSegments" type="int">环形结圆周上细分线段数</param>
                ///<param name ="tubularSegments" type="int">环形结弯管圆周上的细分线段数</param>
                ///<param name ="p" type="float">p\Q:对knot(节)状方式有效,控制曲线路径缠绕的圈数,P决定垂直方向的参数.</param>
                ///<param name ="q" type="float">p\Q:对knot(节)状方式有效,控制曲线路径缠绕的圈数,Q决定水平方向的参数.</param>
                ///<param name ="heightScale" type="float">环形结高方向上的缩放.默认值是1</param>
                var geom = new THREE.TorusKnotGeometry(controls.radius, controls.tube, Math.round(controls.radialSegments), Math.round(controls.tubularSegments), Math.round(controls.p), Math.round(controls.q), controls.heightScale);

                //判断绘制的模型
                if (controls.asParticles) {
                    knot = createPointCloud(geom);
                } else {
                    knot = createMesh(geom);
                }

                // 将新创建的模型添加进去
                scene.add(knot);
            }
        };
        var gui = new dat.GUI();
        //将设置属性添加到gui当中,gui.add(对象,属性,最小值,最大值)gui.add(controls, 'size', 0, 10).onChange(controls.redraw);
        gui.add(controls, 'radius', 0, 40).onChange(controls.redraw);
        gui.add(controls, 'tube', 0, 40).onChange(controls.redraw);
        gui.add(controls, 'radialSegments', 0, 400).step(1).onChange(controls.redraw);
        gui.add(controls, 'tubularSegments', 1, 20).step(1).onChange(controls.redraw);
        gui.add(controls, 'p', 1, 10).step(1).onChange(controls.redraw);
        gui.add(controls, 'q', 1, 15).step(1).onChange(controls.redraw);
        gui.add(controls, 'heightScale', 0, 5).onChange(controls.redraw);
        gui.add(controls, 'asParticles').onChange(controls.redraw);
        gui.add(controls, 'rotate').onChange(controls.redraw);

        controls.redraw();
    }


    var step = 0;
    function render() {

        stats.update();

        if (controls.rotate) {
            knot.rotation.y = step += 0.01;
        }

        renderer.render(scene, camera);
    }

    // 使用canvas创建纹理
    function generateSprite() {

        var canvas = document.createElement('canvas');
        canvas.width = 16;
        canvas.height = 16;

        var context = canvas.getContext('2d');
        var gradient = context.createRadialGradient(canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2);
        gradient.addColorStop(0, 'rgba(255,255,255,1)');
        gradient.addColorStop(0.2, 'rgba(0,255,255,1)');
        gradient.addColorStop(0.4, 'rgba(0,0,64,1)');
        gradient.addColorStop(1, 'rgba(0,0,0,1)');

        context.fillStyle = gradient;
        context.fillRect(0, 0, canvas.width, canvas.height);

        var texture = new THREE.Texture(canvas);
        texture.needsUpdate = true;
        return texture;

    }

    // 创建粒子系统
    function createPointCloud(geom) {
        var material = new THREE.PointCloudMaterial({
            color: 0xffffff,
            size: 3,
            transparent: true,
            blending: THREE.AdditiveBlending,
            map: generateSprite(),
            depthTest: false
        });

        var cloud = new THREE.Points(geom, material);
        cloud.sortParticles = true;
        return cloud;
    }

    //创建模型
    function createMesh(geom) {

        // 创建两面都显示的纹理
        var meshMaterial = new THREE.MeshNormalMaterial({});
        meshMaterial.side = THREE.DoubleSide;

        // 生成模型
        var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial]);

        return mesh;
    }

    //窗口变动触发的函数
    function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();

        render();
        renderer.setSize(window.innerWidth, window.innerHeight);

    }

    function animate() {
        render();

        //更新性能插件
        stats.update();
        requestAnimationFrame(animate);
    }

    function draw() {
        initRender();
        initScene();
        initCamera();
        initLight();
        initModel();
        initStats();
        initGui();

        animate();
        window.onresize = onWindowResize;
    }
</script>
</html>
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Three.js是一个用于创建和展示3D图形的JavaScript库。它基于WebGL技术,可以在现代浏览器中实现高性能的3D渲染效果。Three.js提供了丰富的功能和API,使得开发者可以轻松地创建复杂的3D场景、模型和动画。 心几何图形是指以心形为基础的几何形状。在Three.js中,你可以使用几何体(Geometry)和材质(Material)来创建心几何图形。通过定义顶点坐标和面的连接关系,可以构建出心形的几何体。然后,通过给几何体添加材质,可以设置心形的颜色、纹理等属性。 补光(Ambient Lighting)是一种用于模拟环境光照效果的光照技术。在Three.js中,你可以通过设置场景(Scene)的环境光(AmbientLight)来实现补光效果。环境光会均匀地照亮场景中的所有物体,使其不会完全黑暗,增加整体的可见性和真实感。 以下是使用Three.js创建心几何图形并添加补光效果的代码示例: ```javascript // 创建场景 var scene = new THREE.Scene(); // 创建相机 var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.z = 5; // 创建渲染器 var renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // 创建几何体 var geometry = new THREE.ShapeGeometry(new THREE.Shape().fromPoints([ new THREE.Vector2(0, 1), new THREE.Vector2(1, 0), new THREE.Vector2(0, -1), new THREE.Vector2(-1, 0) ])); var material = new THREE.MeshBasicMaterial({ color: 0xff0000 }); var heart = new THREE.Mesh(geometry, material); scene.add(heart); // 添加环境光 var ambientLight = new THREE.AmbientLight(0xffffff, 0.5); scene.add(ambientLight); // 渲染循环 function animate() { requestAnimationFrame(animate); heart.rotation.x += 0.01; heart.rotation.y += 0.01; renderer.render(scene, camera); } animate(); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值