1

我正在尝试使用 Three.js STLLoader 从 STL 文件中读取和缓存几何图形。我正在使用事件循环回调来获取数据(类似于 STLLoader 示例)。我打算存储在外部变量“cgeom”中。但是,看起来几何在事件 CB 之外不可用并且 cgeom 未定义(运行时错误:cgeom 未定义)。有人能告诉我我在那里做错了什么(代码如下):

<!DOCTYPE html>

<html>
<head>
    <title>Thee.js STL geometry caching test</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
</head>

<body>

    <script src="js/three.min.js"></script>
    <script src="js/STLLoader.js"></script>
    <script>

        alert("We'are here");

        var cgeom;

        function load_geometry( stl_file ) {

            var loader = new THREE.STLLoader();     
            loader.addEventListener( 'load', function ( event ) {
            cgeom = event.content;
                alert('inside listener - vertices: ' + cgeom.vertices.length);
            } );
            loader.load(stl_file);
            alert('inside load_geometry - vertices: ' + cgeom.vertices.length); // error - cgeom is not defined
        }

        load_geometry('./data/a90.stl');     
        alert('inside load_geometry - vertices: ' + cgeom.vertices.length); // error - cgeom is not defined

    </script>

</body>
</html>

所有示例都从几何体创建网格并将其立即添加到场景中。那不是我想要的。我需要稍后添加它,以替换场景中的另一个网格。这就是为什么我想先缓存它。

提前谢谢你,西蒙

PS 我不是 JS 专家,但有 10 年以上的 c++ 和 java 经验。

4

4 回答 4

0

cgeom只有在你的事件处理程序被执行后才会有价值。您的所有代码都会立即运行,除了:

       loader.addEventListener( 'load', function ( event ) {
           cgeom = event.content;
            alert('inside listener - vertices: ' + cgeom.vertices.length);
        } );

因此,您需要等待几何图形加载(此回调运行),然后才能尝试使用它。

于 2013-05-16T16:12:34.493 回答
0

您不必立即添加到场景中,但可以将其添加到外部对象。因此,在您的装载机之前,您可以执行以下操作:

var geometriesToLoad = 2;
var geom1 = new THREE.Object3D ();
var geom2 = new THREE.Object3D ();

在回调中你会做:

geom.add (cgeom);
geometriesToLoad --;

您传递给例程geom的附加变量在哪里?load_geometry()geom1 或 geom2。

geometriesToLoad为 0 时,您的所有模型都已加载,您可以继续处理。您可以通过 setTimeout 调用进行检查。

于 2013-05-16T17:34:50.540 回答
0

感谢 gaitat 和 yaku,谜题得以解决。问题是加载是并行完成的,我在模型实际加载之前检查了结果。这是工作代码(我正在等待模型在 setTimeout 回调中加载):

<script>

    var cgeom;
    var mt;

    function load_geometry( stl_file ) {

            var loader = new THREE.STLLoader();     
            loader.addEventListener( 'load', function ( event ) {
                cgeom = event.content;
                cgeom.dynamic = true;
                console.log('inside listener - vertices: ' + cgeom.vertices.length);
            } );
            loader.load(stl_file);

    }

    load_geometry('./data/a.stl');     

    // start waiting
    mt = setInterval(function () {
        if (cgeom == undefined )
            console.log('wating ...')
        else {
            console.log('cgeom is defined, loaded vertices: ' + cgeom.vertices.length);
            clearInterval(mt);
        }            
    }, 1000);

    if (cgeom == undefined )
            console.log('cgeom - UNDEFINED ...');

</script>
于 2013-05-17T17:27:58.890 回答
0

迟到了,但是从 three.js R125 开始,推荐的方法是使用 loadAsync 方法,该方法现在是 three.js 的原生方法:

https://threejs.org/docs/#api/en/loaders/Loader.loadAsync

该方法返回一个承诺。然后,您可以使用“then”来获取 STL 的几何形状并创建网格。您也可以使用传统的回调,或 async/await 结构,但我认为下面使用本机 three.js 方法的示例是最简单的方法。该示例展示了如何在 promise 被解析并加载 STL 文件后将几何图形获取到全局变量:

// Global variables for bounding boxes
let bbox;

const loader = new STLLoader();
const promise = loader.loadAsync('model1.stl');
promise.then(function ( geometry ) {
  const material = new THREE.MeshPhongMaterial();
  const mesh = new THREE.Mesh( geometry, material );
  mesh.geometry.computeBoundingBox();
  bbox = mesh.geometry.boundingBox;
  scene.add( mesh );
  buildScene();
  console.log('STL file loaded!');
}).catch(failureCallback);

function failureCallback(){
  console.log('Could not load STL file!');
}

function buildScene() {
  console.log('STL file is loaded, so now build the scene');
  // !VA bounding box of the STL mesh accessible now
  console.log(bbox);
  // Build the rest of your scene...
}
于 2021-02-06T21:26:31.333 回答