使用Javascript的Three.js库绘制带有边框的实心立方体

12

我按照 threejs 的示例:webgl_interactive_draggablecubes.html,我的项目是使用 Threejs 制作一个容器装载方案。因此我想制作一个带边框的实心立方体,在有/无边框的情况下都能看到。

image with border,image without border

我可以使用多材质,但那样我的拖放功能就会出现问题。在创建 Geometry3 的代码片段中已经注释掉了。

我的问题是:如何制作既可以带边框又可以拖放的实心立方体?

 <!DOCTYPE html>
<html lang="en">
    <head>
        <title>three.js webgl - draggable cubes</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <style>
            body {
                font-family: Monospace;
                background-color: #f0f0f0;
                margin: 0px;
                overflow: hidden;
            }
        </style>
    </head>
    <body>

        <script src="js/three.js"></script>
        <script src="js/TrackballControls.js"></script>
        <script src="js/stats.min.js"></script>

        <script>

            var container, stats;
            var camera, controls, scene, renderer;
            var cubes = [];
            var plane = new THREE.Plane();
            var raycaster = new THREE.Raycaster();
            var mouse = new THREE.Vector2(),
            offset = new THREE.Vector3(),
            intersection = new THREE.Vector3(),
            INTERSECTED, SELECTED;

            init();
            animate();

            function init() {

                container = document.createElement( 'div' );
                document.body.appendChild( container );

                camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
                camera.position.z = 10;

                controls = new THREE.TrackballControls( camera );
                controls.rotateSpeed = 1.0;
                controls.zoomSpeed = 1.2;
                controls.panSpeed = 0.8;
                controls.noZoom = false;
                controls.noPan = false;
                controls.staticMoving = true;
                controls.dynamicDampingFactor = 0.3;

                scene = new THREE.Scene();

                scene.add( new THREE.AmbientLight( 0x505050 ) );

                
                var geometry = new THREE.BoxGeometry( 2, 5, 7);
                var hex =  0xff0000;
                for ( var i = 0; i < geometry.faces.length; i++ ) {                 
                    geometry.faces[ i ].color.setHex( hex );
                }
                var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors, overdraw: 0.5,wireframe:true } );
                var cube = new THREE.Mesh( geometry, material );
                cubes.push( cube );
     
                var geometry2 = new THREE.BoxGeometry(2,4, 5);              
                var hex2 = 0x009fff;
                for ( var i = 0; i < geometry2.faces.length; i++ ) {                
                    geometry2.faces[ i ].color.setHex( hex2 );
                }                  
                var material2 = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors, overdraw: 0.5,wireframe:true } );
                var cube2 = new THREE.Mesh( geometry2, material2 );             
                cubes.push( cube2 );

                var geometry3 = new THREE.BoxGeometry(1,3,4);
                var hex3 = 0x0f0ff0;
                for ( var i = 0; i < geometry3.faces.length; i++ ) {
                    geometry3.faces[ i ].color.setHex( hex3 );
                }              
    /*          var darkMaterial3= new THREE.MeshBasicMaterial( { color: 0xffffcc } );
                var wireframeMaterial3= new THREE.MeshBasicMaterial( { color: 0x0f0000, wireframe: true, transparent: false } ); 
                var multiMaterial3= [ darkMaterial3, wireframeMaterial3 ];          
                var cube3 = THREE.SceneUtils.createMultiMaterialObject(geometry3,multiMaterial3);*/
                var material3 = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors, overdraw: 0.5,wireframe:true } );
                var cube3 = new THREE.Mesh( geometry3, material3 );   
                cubes.push( cube3 );
                
                scene.add(cube);
                scene.add(cube2);
                scene.add(cube3);

                renderer = new THREE.WebGLRenderer( { antialias: true } );
                renderer.setClearColor( 0xf0f0f0 );
                renderer.setPixelRatio( window.devicePixelRatio );
                renderer.setSize( window.innerWidth, window.innerHeight );
                renderer.sortObjects = false;

                renderer.shadowMap.enabled = true;
                renderer.shadowMap.type = THREE.PCFShadowMap;
                container.appendChild( renderer.domElement );
                
                stats = new Stats();
                container.appendChild( stats.dom );

                renderer.domElement.addEventListener( 'mousemove', onDocumentMouseMove, false );
                renderer.domElement.addEventListener( 'mousedown', onDocumentMouseDown, false );
                renderer.domElement.addEventListener( 'mouseup', onDocumentMouseUp, false );

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

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

            function onDocumentMouseMove( event ) {
                event.preventDefault();

                mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
                mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;

                raycaster.setFromCamera( mouse, camera );

                if ( SELECTED ) {
                    if ( raycaster.ray.intersectPlane( plane, intersection ) ) {
                        SELECTED.position.copy( intersection.sub( offset ) );
                    }
                    return;
                }

                var intersects = raycaster.intersectObjects( cubes );
                if ( intersects.length > 0 ) {
                    if ( INTERSECTED != intersects[ 0 ].object ) {
                        if ( INTERSECTED ) INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
                        INTERSECTED = intersects[ 0 ].object;
                        INTERSECTED.currentHex = INTERSECTED.material.color.getHex();

                        plane.setFromNormalAndCoplanarPoint(
                            camera.getWorldDirection( plane.normal ),
                            INTERSECTED.position );
                    }
                    container.style.cursor = 'pointer';
                } else {
                    if ( INTERSECTED ) INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
                    INTERSECTED = null;
                    container.style.cursor = 'auto';
                }
            }

            function onDocumentMouseDown( event ) {
                event.preventDefault();
                raycaster.setFromCamera( mouse, camera );
                var intersects = raycaster.intersectObjects( cubes );

                if ( intersects.length > 0 ) {
                    controls.enabled = false;
                    SELECTED = intersects[ 0 ].object;
                    if ( raycaster.ray.intersectPlane( plane, intersection ) ) {
                        offset.copy( intersection ).sub( SELECTED.position );
                    }
                    container.style.cursor = 'move';
                }
            }

            function onDocumentMouseUp( event ) {
                event.preventDefault();
                controls.enabled = true;
                if ( INTERSECTED ) {
                    SELECTED = null;
                }
                container.style.cursor = 'auto';
            }

            function animate() {
                requestAnimationFrame( animate );
                render();
                stats.update();
            }

            function render() {
                controls.update();
                renderer.render( scene, camera );
            }
        </script>
    </body>
</html> 
2个回答

22

WireframeGeometryEdgesGeometry作为可拖动对象的子级添加。

scene.add( object );
objects.push( object );

// wireframe
var geo = new THREE.EdgesGeometry( object.geometry );
var mat = new THREE.LineBasicMaterial( { color: 0x000000 } );
var wireframe = new THREE.LineSegments( geo, mat );
object.add( wireframe );

还可以查看这个相关答案

three.js r.144


太好了!回答得又快又准确。如何使线条加粗?当我增加线宽时,似乎已经达到了最大值。 - user84592
1
老天,这是唯一帮助我解决问题的方法。我渲染了立方体和线段,看起来很棒,直到我使用Orbitcontrols移动相机,立方体会保留但线段消失了。设置renderorder解决了这个问题!谢谢! - RobertT

-1

我建议使用 EdgesHelper

      this.scene.add(image3D);

      edges                             =   new THREE.EdgesHelper(image3D, 0x808080);
      edges.material.linewidth          =   3;

      this.scene.add(edges);

例子:

Example


EdgesHelper 已在 three.js r.81 中从库中移除。 - WestLangley
我正在使用r82,对于我的情况来说它更好。对于容器装载3D,这是更好的解决方案。它已经过时了吗?无论如何,我正在使用r82,并且它可以正常工作。 - user84592
1
@user84592 请注意你的控制台警告信息:"THREE.EdgesHelper已被移除,请使用THREE.EdgesGeometry代替。" - WestLangley
@WestLangley 您是正确的,这个API已经过时了。但我们的业务人员喜欢这种边缘类型。 - user84592
1
@user84592,您需要将事件添加到画布容器中。this.canva_container.addEventListener('mousemove', this.onWindowMouseMoveHandler, false); - Jorge Abraham Jimenez Molina
显示剩余2条评论

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