0

我正在尝试创建一个带有方形底座的随机地形,它将导出为 .STL(和 3d 打印)。

我很难将每个单独的几何图形组合成一个网格。从表面上看,我的形状看起来不错,但是当我尝试 3d 打印 .STL 时,很明显在每个单独的几何图形合并后存在一些间隙。

目前,我首先创建顶部几何体,然后创建左、右、前、后和底部,最后将这些几何体合并为一个网格。

我现在的代码是:

<!doctype html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>STL</title>
        <style>
            #container {
                background: #000;
                width: 800px;
                height: 600px;
            }
        </style>
    </head>
    <body>
        <input type="button" id="export" name="export" value="Export" />    
        <div id="container">


        </div>

    </body>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
    <script src="js/three.min.js"></script>
    <script src="js/loaders/STLLoader.js"></script>
    <script src="js/exporters/STLExporter.js"></script>
    <script src="js/Detector.js"></script>
    <script src="js/libs/stats.min.js"></script>
    <script src="js/ImprovedNoise.js"></script>
    <script src="js/blob/Blob.js"></script>
    <script src="js/filesaver/FileSaver.js"></script>
    <script src="js/controls/FirstPersonControls.js"></script>

    <script>

    $(document).ready(function() {

        var mouseX, mouseY = 0;
        var WIDTH = 800,
            HEIGHT = 600;

        var VIEW_ANGLE = 45,
            ASPECT = WIDTH / HEIGHT,
            NEAR = 0.1,
            FAR = 10000;

        var container = $('#container');

        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
        camera.position.z = 700;

        var controls = new THREE.FirstPersonControls( camera );
        controls.movementSpeed = 1000;
        controls.lookSpeed = 0.1;



        var exporter = new THREE.STLExporter();

        var renderer = new THREE.WebGLRenderer();
        var camera = new THREE.PerspectiveCamera(  VIEW_ANGLE,
                                        ASPECT,
                                        NEAR,
                                        FAR  );
        var scene = new THREE.Scene();

        camera.position.z = 300;

        renderer.setSize(WIDTH, HEIGHT);
        var clock = new THREE.Clock();
        animate();
        container.append(renderer.domElement);

        var sphereMaterial = new THREE.MeshLambertMaterial(
        {
            color: 0xCC0000
        });

        var worldWidth = 100, worldDepth = 100,
        worldHalfWidth = worldWidth / 2, worldHalfDepth = worldDepth / 2;

        var heightData = generateHeight( worldWidth, worldDepth );
        camera.position.y = heightData[ 0] ;
        var geometry = new THREE.PlaneGeometry( 300, 300, worldWidth - 1, worldDepth - 1 );

        geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );

        for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) {

            geometry.vertices[ i ].y = heightData[ i ] * 2;

        }

        var leftGeometry = new THREE.PlaneGeometry(300, 1, worldWidth - 1, worldDepth - 1 );
        for( var i = 0; i < worldWidth; i++ ) {
            for( var j = 0; j < worldDepth; j++ ) {
                var index = j * worldWidth + i;
                if ( j ==  worldDepth-1 ) {
                    leftGeometry.vertices[index].y = geometry.vertices[index].y +1;
                }
            }
        }

        var rightGeometry = new THREE.PlaneGeometry(300, 1, worldWidth - 1, worldDepth - 1 );
        for( var i = 0; i < worldWidth; i++ ) {
            for( var j = 0; j < worldDepth; j++ ) {
                var index = j * worldWidth + i;
                if ( j ==  0 ) {
                    rightGeometry.vertices[index].y = geometry.vertices[index].y + 1;
                }
            }
        }

        var topGeometry = new THREE.PlaneGeometry(1, 300, worldWidth - 1, worldDepth - 1 );

        topGeometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );

        for( var i = 0; i < worldWidth; i++ ) {
            for( var j = 0; j < worldDepth; j++ ) {
                var index = j * worldWidth + i;
                if ( i ==  0 ) {
                    topGeometry.vertices[index].y = geometry.vertices[index].y+1;
                }
            }
        }

        var bottomGeometry = new THREE.PlaneGeometry(1, 300, worldWidth - 1, worldDepth - 1 );

        bottomGeometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );

        for( var i = 0; i < worldWidth; i++ ) {
            for( var j = 0; j < worldDepth; j++ ) {
                var index = j * worldWidth + i;
                if ( i ==  worldWidth-1 ) {
                    bottomGeometry.vertices[index].y = geometry.vertices[index].y+1;
                }
            }
        }

        var baseGeometry = new THREE.PlaneGeometry(300, 300, worldWidth - 1, worldDepth - 1 );
        baseGeometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );

        // ------------------------------

        var combined = new THREE.Geometry();

        var meshA = new THREE.Mesh( geometry,  new THREE.MeshNormalMaterial() );
        var meshB = new THREE.Mesh( leftGeometry, new THREE.MeshNormalMaterial() );
        var meshC = new THREE.Mesh( rightGeometry, new THREE.MeshNormalMaterial() );
        var meshD = new THREE.Mesh( topGeometry, new THREE.MeshNormalMaterial() );
        var meshE = new THREE.Mesh( bottomGeometry, new THREE.MeshNormalMaterial() );
        var meshF = new THREE.Mesh( baseGeometry, new THREE.MeshNormalMaterial() );

        meshB.position.z = worldHalfWidth+100;
        meshB.position.y = 0;
        meshC.position.y = 0;
        meshC.position.z = -worldHalfWidth-100;
        meshD.position.x = -worldHalfWidth-99;
        meshE.position.x = worldHalfWidth+99;


        THREE.GeometryUtils.merge(combined, meshA);
        THREE.GeometryUtils.merge(combined, meshB);
        THREE.GeometryUtils.merge(combined, meshC);
        THREE.GeometryUtils.merge(combined, meshD);
        THREE.GeometryUtils.merge(combined, meshE);
        THREE.GeometryUtils.merge(combined, meshF);

        var out = new THREE.Mesh( combined, new THREE.MeshBasicMaterial({
            wireframe: true,
            color: 'white'
        }));

        scene.add(out);
        scene.add(camera);

        var pointLight = new THREE.PointLight( 0xFFFFFF );

        pointLight.position.x = 10;
        pointLight.position.y = 50;
        pointLight.position.z = 130;

        scene.add(pointLight);

        renderer.render(scene, camera);


        function generateHeight( width, height ) {

            var size = width * height, data = new Float32Array( size ),
            perlin = new ImprovedNoise(), quality = 1, z = Math.random() * 100;

            for ( var i = 0; i < size; i ++ ) {
                data[ i ] = 0
            }

            for ( var j = 0; j < 4; j ++ ) {
                for ( var i = 0; i < size; i ++ ) {
                    var x = i % width, y = ~~ ( i / width );
                    data[ i ] += Math.abs( perlin.noise( x / quality, y / quality, z ) * quality * 1.75 );
                }
                quality *= 5;
            }
            return data;

        }


        function animate() {

            requestAnimationFrame( animate );
            render();

        }


        function render() {

            controls.update( clock.getDelta() );
            renderer.render( scene, camera );
            camera.position.z = ( mouseX - camera.position.x ) * .6;
        }

       $("#export").click(function(){
            var out = exporter.exportScene(scene);
            var blob = new Blob([out], {type: 'text/plain'});
            saveAs(blob, 'please work.stl');
        });

        $("#container").mousemove(function(event) {
            mouseX = event.pageX; 
            mouseY = event.pageY;
        });


    });

    </script>
</html>

我的问题是:除了使用 GeometryUtils.merge 函数之外,还有其他方法可以创建这种类型的形状吗?目前,输出形状无法 3d 打印,我想知道是不是因为形状合并后,最终的几何图形包含间隙。我不确定如何解决这个问题。

4

0 回答 0