我正在尝试使用Three.js STLLoader从STL文件中读取和缓存几何体。我正在使用事件循环回调来获取数据(类似于STLLoader示例)。我打算存储在外部变量“cgeom”中。但是,看起来几何体在事件CB之外是不可用的并且未定义cgeom(运行时错误:未定义cgeom)。有人可以告诉我我在那里做错了(代码如下):< / p>
<!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>
所有示例都从几何体创建网格并立即将其添加到场景中。那不是我想要的。我需要稍后添加它,以替换场景中的另一个网格。这就是为什么我要首先缓存它。
提前谢谢你, 西蒙
P.S。我不是JS专家,但有10年以上的c ++和java经验。
答案 0 :(得分:0)
cgeom
才会有值。您的所有代码都会立即运行,但不包括:
loader.addEventListener( 'load', function ( event ) {
cgeom = event.content;
alert('inside listener - vertices: ' + cgeom.vertices.length);
} );
因此,您需要等待几何体加载(此回调才能运行),然后才能尝试使用它。
答案 1 :(得分: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调用来检查它。
答案 2 :(得分: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>
答案 3 :(得分: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...
}