Threejs 画一个完美的圆环

 用Threejs画一个完美的圆环。参考Threejs Demo里 webgl_geometry_shapes.html 的代码写了测试程序 如下

const arcShape = new THREE.Shape()
    .moveTo( 0, 0 )
   .absarc( 0, 0, 40, 0, Math.PI * 2, false );

const holePath = new THREE.Path()
    .moveTo( 0, 0 )
    .absarc( 0, 0, 30, 0, Math.PI * 2, true );

arcShape.holes.push( holePath );              
let geometry = new THREE.ShapeGeometry( arcShape );
let mesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( { side: THREE.DoubleSide, color: '#00ff00' } ) );
scene.add( mesh );

圆环是有了,可惜圆环有明显的棱角,不太完美啊。很自然的想到absarc函数是否有类似CircleGeometry类构造时的segments参数把圆多分点三角形出来那不就圆滑了吗。

可惜Curve→CurvePath→Path→Shape 看了个遍都没找到类似的函数,不过看到Shape类extractPoints函数有个divisions参数。感觉找点了什么。赶紧测试代码写起来······

let arr = new THREE.Shape().absarc( 0, 0, 40, 0, Math.PI * 2 ).extractPoints(360),
    arrh = new THREE.Shape().absarc( 0, 0, 30, 0, Math.PI * 2 ).extractPoints(360),
    sp = new THREE.Shape( arr.shape ),
    ph = new THREE.Path( arrh.shape );
sp.holes.push( ph );
let geometry = new THREE.ShapeGeometry( sp );
let mesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( { side: THREE.DoubleSide, color: '#00ff00' } ) );
scene.add( mesh );

运行后结果

结果,感觉挺完美了。

完整代码

demo.html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no" name="viewport"/>
<title>canvas</title>
<style>
    html, body {
        width:100%;
        height:100%;
    }
    body {
        overflow:hidden;
        padding:0px;
        margin:0px;
    }
</style>
<script type="text/javascript" src="/js/jquery-1.11.1.min.js"></script>
<script type="importmap">
    {
        "imports": {
            "three": "/js/threejs/build/three.module.js",
            "three/addons/": "/js/threejs/examples/jsm/"
        }
    }
</script>
<script type="module">
    import * as Initer from '/js/InitThree.module.js';
    import * as THREE from 'three';

    $(document).ready(function() {
        Initer.Init( {
            Stats : true,
            AxesHelper : 0,
            orbitCtrl : true,
            cameraX : 0,
            cameraY : 0,
            cameraZ : 300
        } );
        
        let arr = new THREE.Shape().absarc( 0, 0, 40, 0, Math.PI * 2 ).extractPoints(360),
            arrh = new THREE.Shape().absarc( 0, 0, 30, 0, Math.PI * 2 ).extractPoints(360),
            sp = new THREE.Shape( arr.shape ),
            ph = new THREE.Path( arrh.shape );
        sp.holes.push( ph );
        let geometry = new THREE.ShapeGeometry( sp );
        let mesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( { side: THREE.DoubleSide, color: '#00ff00' } ) );
        scene.add( mesh );
    
    });
</script>

</head>
<body>
</body>
</html>

InitThree.module.js 

import * as THREE from 'three';
import Stats from 'three/addons/libs/stats.module.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

let scene, camera, renderer, light, axes, updateFnc, deltaT=0, stats = null, obctrl = null;

function animate( timestamp ) {
    if( deltaT == 0 ) {
        deltaT = timestamp;
    }
    if( updateFnc ) {
        updateFnc( timestamp - deltaT );
        deltaT = timestamp;
    }
    renderer.render( scene, camera );
    if( stats ) {
        stats.update();
    }
    requestAnimationFrame( animate );
}

function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize( window.innerWidth, window.innerHeight );
}

function Init( _params ) {
    let Params = _params || {};
    Params.alphaValue = Params.alphaValue || 1;
    Params.bgColor = typeof( Params.bgColor ) != 'undefined' ? Params.bgColor : 0x333;
    Params.cameraX = typeof( Params.cameraX ) != 'undefined' ? Params.cameraX : 100;
    Params.cameraY = typeof( Params.cameraY ) != 'undefined' ? Params.cameraY : 100;
    Params.cameraZ = typeof( Params.cameraZ ) != 'undefined' ? Params.cameraZ : 100;
    Params.Stats = Params.Stats || false;
    Params.AxesHelper = Params.AxesHelper || false;
    updateFnc =  _params.updateFnc || null;
    Params.orbitCtrl =  _params.orbitCtrl || null;
    if( typeof( updateFnc ) != "function" ) {
        updateFnc = null;
    }

    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 0.1, 10000);
    renderer = new THREE.WebGLRenderer({
        preserveDrawingBuffer:true,
        antialias: true,
        alpha: true
    });
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setClearAlpha( Params.alphaValue );
    renderer.setClearColor( Params.bgColor );
    document.body.appendChild(renderer.domElement);
    
    light = new THREE.AmbientLight(0xFFFFFF, 1.5);
    scene.add(light);

    if( Params.AxesHelper ) {
        axes = new THREE.AxesHelper(1000);
        axes.setColors( new THREE.Color( 0xff0000 ),
                        new THREE.Color( 0xffff00 ),
                        new THREE.Color( 0x0000ff ) );
        scene.add(axes);
    }
    
    if( Params.Stats ) {
        stats = new Stats();
        document.body.appendChild( stats.dom );
    }

    window.addEventListener( 'resize', onWindowResize );
    if( Params.orbitCtrl ) {
        obctrl = new OrbitControls( camera, renderer.domElement );
    }
    camera.position.x = Params.cameraX;
    camera.position.y = Params.cameraY;
    camera.position.z = Params.cameraZ;
    
    window.scene = scene;
    window.camera = camera;
    requestAnimationFrame( animate );
}

export { Init }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值