如何在Three.js中构建自定义平面几何体?

6
我希望在three.js中创建一个平面,但点数比默认值更多(因此我不想使用PlaneGeometry,因为我认为它不会让我定义自定义点)。原因是我想能够在任何给定时间动画或移动任何给定点。
这是我目前的进展:
var camera;
var scene;
var renderer;
var mesh;

init();
animate();

function init() {

    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000);

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


    var geometry = new THREE.PlaneGeometry( 50, 50);  

    var texture = THREE.ImageUtils.loadTexture('images/03032122.png', {}, function() {
    renderer.render(scene, camera);
    })
    var material = new THREE.MeshBasicMaterial({map: texture, transparent: true })


    mesh = new THREE.Mesh(geometry, material );
    mesh.position.z = -50;
    scene.add( mesh );

    renderer = new THREE.WebGLRenderer({ alpha: true });
    renderer.setSize( window.innerWidth, window.innerHeight );

    renderer.setClearColor( 0xffffff, 1);
    document.body.appendChild( renderer.domElement );

    window.addEventListener( 'resize', onWindowResize, false );

    render();
}

function animate() {
    //mesh.scale.x+= 0.0003;


    render();
    requestAnimationFrame( animate );

}

function render() {
    renderer.render( scene, camera );
}


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

我希望做的是创建类似于这个的东西:
http://www.math.ubc.ca/~cass/courses/m308-02b/projects/schweber/square%20tiles.gif
4个回答

6

请注意PlaneGeometry已经被弃用(所以将在下一个版本中被删除),请改用PlaneBufferGeometry。

如果您想要“正常”的平面分割,则@pailhead的答案是正确的。

如果您希望顶点具有其他位置,则必须逐个构建几何体的顶点,这是另一种方法*。

此外,这也回答了您需要在稍后移动/动画顶点的需求,您可以通过编写以下内容在几何体创建后更改每个顶点的位置:

planeMesh.geometry.vertices[i].set(x,y,z);// this way you can move each vertex coordinates
planeMesh.geometry.verticesNeedUpdate=true;

* :以具有4个顶点(=2个三角形)的平面为例:
var geo=new THREE.Geometry();
geometry.vertices.push(
    new THREE.Vector3(x1,y1,z1),//vertex0
    new THREE.Vector3(x2,y2,z2),//1
    new THREE.Vector3(x3,y3,z3),//2
    new THREE.Vector3(x4,y4,z4)//3
    );
geometry.faces.push(
    new THREE.Face3(2,1,0),//use vertices of rank 2,1,0
    new THREE.Face3(3,1,2)//vertices[3],1,2...
    );

当然,使这个几何图形成为平面的原因是它的四个顶点共面。 当你创建一个由许多面组成的几何图形时,你需要用笔和纸来画出这些面。根据你的几何图形,你也可以使用算法。

你会如何逐个顶点地构建它? - blazerix
抱歉,忽略上面的帖子(我还在适应stackoverflow)。所以,我尝试了以下代码:geometry.vertices.push( new THREE.Vector3(0,1,10),//顶点0 new THREE.Vector3(1,0,10),//1 new THREE.Vector3(1,1,10),//2 new THREE.Vector3(0,0,10)//3 ); geometry.faces.push( new THREE.Face3(2,1,0),//使用排名为2、1、0的顶点 new THREE.Face3(1,1,2)//vertices[3],1,2... );但是我遇到了一个错误:glDrawElements: attempt to access out of range vertices in attribute 1。 - blazerix
你正在要求我调试代码,请提供一个 jsfiddle 链接。顺便说一下,你可以给喜欢的答案点赞,并验证对你最有帮助的答案。 - Mouloud85
我已经更新了fiddle,使用了最新版本的threejs并将Face3(1,1,2)更正为(3,1,2)。这是错误的原因(你需要3个点来绘制一个面...)。然而,你还有工作要做。我不能替你完成,但你可能需要检查这些问题:http://stackoverflow.com/questions/17640089/face-is-not-drawn,https://dev59.com/DHfZa4cB1Zd3GeqPRGn9。 - Mouloud85
请不要在评论中进行对话 :) 只需按照您的方式进行操作。您可能会遇到这些链接可以回答的问题。 - Mouloud85
显示剩余2条评论

1
我创建了我的定制飞机,使用的是:

        // Plane
            var size = 500, step = 100;
            var geometry = new THREE.Geometry();
            for ( var i = - size; i <= size; i += step ) {

                geometry.vertices.push( new THREE.Vector3( - size, 0, i ) );
                geometry.vertices.push( new THREE.Vector3(   size, 0, i ) );

                geometry.vertices.push( new THREE.Vector3( i, 0, - size ) );
                geometry.vertices.push( new THREE.Vector3( i, 0,   size ) );

            }

            var material = new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.5 } );

            var line = new THREE.Line( geometry, material, THREE.LinePieces );
            scene.add( line );

你好 Victor, 能否给你的自定义飞机添加纹理呢? - blazerix
是的,我的自定义是为了在我的计划中创建一个“地面”,并且它起作用了。代码如下:var ground = new THREE.Mesh( new THREE.PlaneGeometry(1000, 1000, 50, 50), new THREE.MeshLambertMaterial({color:0xFFFFFF}) ); ground.receiveShadow = true; ground.position.set(0, -25, 0); ground.rotation.x = -Math.PI / 2; scene.add(ground); - Víctor Romário Paz de Jesus
嗨Victor,如果可以的话,你能看一下我的JS Fiddle吗?我只看到屏幕上有一条线。 https://jsfiddle.net/z9z28ume/ - blazerix

0

0
如果您想添加带有自定义边框的平面,我建议您直接更改位置属性数组并更新几何点的位置:
// Here you chose the divisions in x
    const x_lenght = 1 
    const divisions = 10
    
    let geometry = new THREE.PlaneBufferGeometry( x_lenght, 1, divisions, 1 )
    let material = new THREE.MeshPhongMaterial( { color: 0xecf0f1, wireframe: true } )
    
    let pointPos = geometry.getAttribute("position").array
        
    for (let i = 0; i < divisions + 1; i++) {
      let x = pointPos[3 * i] + x_lenght/2

      // This case is making y = x^2
      pointPos[3 * i + 1] = Math.pow(x, 2) 
      pointPos[3 * ( divisions + 1 ) + 3 * i + 1] = - pointPos[3 * i  + 1]
      
      console.log(`x = ${pointPos[3 * i]}; y = ${pointPos[3 * ( divisions + 1 ) + 3 * i + 1]}`)

        }
    
    pointPos.needsUpdate = true;
    
    mesh = new THREE.Mesh(geometry, material )

    scene.add(mesh)

这是我的示例 https://codepen.io/ferrari212/pen/bGpgLBd?editors=0010


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接