关于THREE.js中ParametricGeometry画不出来的原因

因为计图项目是海底世界创建,所以虽然画出了个竹子,但是还是想画海草。
由于海草也是波浪形的,想起之前在一个博客里看到了波浪平面的生成是利用ParametricGeometry生成的,于是也想试一试,就写出了如下代码:

//海草形状
var radialWave = function (u, v) {

        var r = 150;

        var z = Math.sin(u) * r;

        var x = Math.sin(v / 2) * r;

        var y = (Math.sin(u * 4 * Math.PI) + Math.cos(v * 2 * Math.PI)) * 10;

        return new THREE.Vector3(x, y, z);

};
//按照形成海草形状的参数方程来生成海草几何体,再生成海草网格
var mesh = new THREE.Mesh(new THREE.ParametricGeometry(radialWave, 12, 12),
                             new THREE.MeshPhongMaterial( {
                                                size:50,
                                                color:0x00ff00,
                                                side:THREE.DoubleSide
                                            })
                             );
mesh.position.set(0,0,-200);
mesh.scale.set(1,0.5,2);
mesh.rotation.x = Math.PI*0.5;
scene.add(mesh);

在某个可以在线运行js代码的网站上成功画出了海草:
这里写图片描述

于是兴高采烈的搬到了本地代码里,然而什么都没画出来!!
以为是浏览器的锅,换成了高大上的chrome,还是没画出来orz..
然后就怀疑我的three.js是不是yan-ge版,找到了three官方的文件,对照下来,差不多嘛,
但是官网中的实现有这么一句话!!非常关键!!

if ( func.length < 3 ) {

        console.error( 'THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter.' );

    }

什么意思呢?就是说,参数方程那个函数的参数表必须有三个参数,而这个第三个参数是一个Vector3的类型,在我们的func里需要修改这个Vector3,而不是前面实现的返回值为Vector3!!

而我的本地代码里的three.js虽然实现是一样的,但是并没有提示报错…
于是把函数改成了这样:

var radialWave = function (u, v, p0) {

        var r = 150;

        var z = Math.sin(u) * r;

        var x = Math.sin(v / 2) * r;

        var y = (Math.sin(u * 4 * Math.PI) + Math.cos(v * 2 * Math.PI)) * 10;

        p0 = new THREE.Vector3(x, y, z);

};

对不起,还是没有画出来orz
再看了一次官网源码,感觉没有什么不对劲啊,于是去看了官网给出的示例的代码,发现别人是这样写的:

target.set( x, y, z );

噢,原来要用set方法,果然js还是不太熟,以为都是引用传参,其实这里的=是浅复制,等函数执行完,分配的内存就被释放了,p0并没有被改变。

改完代码,好了,终于看到这根绿油油亮的晃眼的海草了。

顺带一提官网的例子里还给了几个形状(克莱因瓶,平面,二维莫比乌斯带,三维莫比乌斯带)的产生函数,

贴一下地址:https://github.com/mrdoob/three.js/blob/master/examples/js/ParametricGeometries.js

也顺便贴一下代码:

klein: function ( v, u, target ) {

        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 );

        target.set( x, y, z );

    },

plane: function ( width, height ) {

        return function ( u, v, target ) {

            var x = u * width;
            var y = 0;
            var z = v * height;

            target.set( x, y, z );

        };

    },

mobius: function ( u, t, target ) {

        // flat mobius strip
        // http://www.wolframalpha.com/input/?i=M%C3%B6bius+strip+parametric+equations&lk=1&a=ClashPrefs_*Surface.MoebiusStrip.SurfaceProperty.ParametricEquations-
        u = u - 0.5;
        var v = 2 * Math.PI * t;

        var x, y, z;

        var a = 2;

        x = Math.cos( v ) * ( a + u * Math.cos( v / 2 ) );
        y = Math.sin( v ) * ( a + u * Math.cos( v / 2 ) );
        z = u * Math.sin( v / 2 );

        target.set( x, y, z );

    },

mobius3d: function ( u, t, target ) {

        // volumetric mobius strip

        u *= Math.PI;
        t *= 2 * Math.PI;

        u = u * 2;
        var phi = u / 2;
        var major = 2.25, a = 0.125, b = 0.65;

        var x, y, z;

        x = a * Math.cos( t ) * Math.cos( phi ) - b * Math.sin( t ) * Math.sin( phi );
        z = a * Math.cos( t ) * Math.sin( phi ) + b * Math.sin( t ) * Math.cos( phi );
        y = ( major + x ) * Math.sin( u );
        x = ( major + x ) * Math.cos( u );

        target.set( x, y, z );

    }

};

猜你喜欢

转载自blog.csdn.net/unirrrrr/article/details/80645993