three.js 中 stl 对象的边界框
Bounding Box of a stl object in three.js
大家好,
我看过几篇关于这个主题的帖子,但没有解决方案。我在 three.js 中借助 STLLoader 加载了一个对象,我想为其获取一个边界框。
// Add stl objects and a name
function addSTLObject(url, name) {
var loader = new THREE.STLLoader();
loader.load(url, function (geometry) {
var material = new THREE.MeshPhongMaterial({ color: 0xff5533 });
var mesh = new THREE.Mesh(geometry, material);
// To scale element, use:
// mesh.scale.set(0.01, 0.01, 0.01);
// Add a name to the object to find it if it needs to be removed
mesh.name = name;
mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = 0;
scene.add(mesh);
});
}
我正在按如下方式加载此对象:
addSTLObject('model/cases/iphone5.stl', 'phone-model');
var phoneModelAdded = scene.getObjectByName('phone-model', true);
现在我已经尝试了这里提供的解决方案:https://github.com/mrdoob/three.js/issues/3471 and here Any way to get a bounding box from a three.js Object3D?
var bbox = new THREE.Box3().setFromObject(phoneModelAdded);
var geometry = phoneModel.children[0].children[0].geometry;
geometry.computeBoundingBox();
虽然第一个解决方案给我一个错误说 "Cannot read property 'updateMatrixWorld' of undefined",但第二个解决方案没有给我任何错误但什么都不做,如果我尝试访问 "geometry" 属性 它说它不存在。
有人有可行的解决方案吗?
感谢您的帮助。
祝你有美好的一天!
编辑:
// Add stl objects and a name
function addSTLObject(url, name) {
var bbox;
var loader = new THREE.STLLoader();
loader.load(url, function (geometry) {
var material = new THREE.MeshPhongMaterial({ color: 0xff5533 });
var mesh = new THREE.Mesh(geometry, material);
// To scale element, use:
// mesh.scale.set(0.01, 0.01, 0.01);
// Add a name to the object to find it if it needs to be removed
mesh.name = name;
mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = 0;
bbox = new THREE.Box3().setFromObject(mesh);
scene.add(mesh);
return bbox;
});
}
及之后
var bbox = addSTLObject('model/cases/iphone5.stl', 'phone-model');
scene.add(bbox);
错误:"THREE.Object3D.add: object not an instance of THREE.Object3D"
编辑 2:
var bbox, bboxComputed = false;
function addSTLObject(url, name) {
var bbox;
var loader = new THREE.STLLoader();
loader.load(url, function (geometry) {
var material = new THREE.MeshPhongMaterial({ color: 0xff5533 });
var mesh = new THREE.Mesh(geometry, material);
// To scale element, use:
// mesh.scale.set(0.01, 0.01, 0.01);
// Add a name to the object to find it if it needs to be removed
mesh.name = name;
mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = 0;
bbox = new THREE.BoundingBoxHelper(mesh);
bbox.update();
bboxComputed = true;
scene.add(mesh);
});
}
addSTLObject('model/cases/iphone5.stl', 'phone-model');
var myInterval = setInterval( function(){
if( bboxComputed ) {
alert( bbox.box.min, bbox.box.max, bbox.box.size() );
scene.add(bbox);
clearInterval( myInterval );
bboxComputed = false;
}
}, 100 );
这行不通。
编辑 3:
我试图建立一个函数,它拥有我需要的一切,并返回一个包含所有计算信息的对象:
function calculateSTLProperties(url, name) {
var STLObject, STLbbox, STLComputed = false, STLGeometry;
var loader = new THREE.STLLoader();
loader.load(url, function (geometry) {
var material = new THREE.MeshPhongMaterial({ color: 0xff5533 });
var mesh = new THREE.Mesh(geometry, material);
// To scale element, use:
// mesh.scale.set(0.01, 0.01, 0.01);
// Add a name to the object to find it if it needs to be removed
mesh.name = name;
mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = 0;
// Compute a bounding box for the element
STLbbox = new THREE.BoundingBoxHelper(mesh);
STLbbox.update();
// Get the geometry of the case
STLGeometry = geometry;
STLComputed = true;
});
// Set an interval to wait for the corresponding bounding box and geometry to be computed
var myInterval = setInterval( function(){
if( STLComputed ) {
STLObject = {
"geometry" : STLGeometry,
"bbox" : STLbbox,
"x" : STLbbox.box.size().x,
"y" : STLbbox.box.size().y,
"z" : STLbbox.box.size().z
};
clearInterval( myInterval );
bboxComputed = false;
}
}, 100 );
return STLObject;
}
不幸的是,不知何故对象没有通过,我在尝试保存它时最终得到了一个 "undefined":
var STLObjectLoaded = calculateSTLProperties('model/cases/iphone5.stl', 'phone-model');
console.log(STLObjectLoaded);
我错过了什么?
模型加载是异步的,因此所有计算都应该在模型加载后进行。添加一个回调,它在模型加载时调用,并在其中添加对 bbox 的调用。你拥有它的方式 scene.getObjectByName()
调用是用一个你也验证的空对象进行的 ("if I try accessing the "geometry" 属性 它说它不存在")
更新:
使用:
var bbox = new THREE.BoundingBoxHelper( mesh ); bbox.update();
scene.add( bbox );
来自 loader.load()
函数内部。
setFromObject()
调用仅创建边界框而不是 bbox 的几何图形。
更新二
如果您希望 bbox
在 loader.load()
函数之外可用,您需要使用全局变量
var bboxComputed = false;
在计算 loader.load()
函数中的 bbox 后立即将其设置为 true:
scene.add( bbox );
bboxComputed = true;
然后在你的 main 而不是使用:
console.log( bbox.box.min, bbox.box.max, bbox.box.size() );
你会使用类似的东西:
var myInterval = setInterval( function(){
if( bboxComputed ) {
console.log( bbox.box.min, bbox.box.max, bbox.box.size() );
clearInterval( myInterval );
}
}, 100 );
我设置了 0.1 秒的延迟,当最终计算出 bbox
时,我清除了间隔,这样它就不会永远 运行。
从 three.js R125 开始,推荐的方法是使用 loadAsync 方法,该方法现在是 three.js:
的原生方法
https://threejs.org/docs/#api/en/loaders/Loader.loadAsync
那个方法returns一个承诺。然后,您可以使用 'then' 获取 STL 的几何形状并创建网格。您也可以使用前面答案中的传统回调,或 async/await 结构,但我认为下面使用本机 three.js 方法的示例是最简单的方法。该示例显示了如何在解决承诺并加载 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...
}
大家好,
我看过几篇关于这个主题的帖子,但没有解决方案。我在 three.js 中借助 STLLoader 加载了一个对象,我想为其获取一个边界框。
// Add stl objects and a name
function addSTLObject(url, name) {
var loader = new THREE.STLLoader();
loader.load(url, function (geometry) {
var material = new THREE.MeshPhongMaterial({ color: 0xff5533 });
var mesh = new THREE.Mesh(geometry, material);
// To scale element, use:
// mesh.scale.set(0.01, 0.01, 0.01);
// Add a name to the object to find it if it needs to be removed
mesh.name = name;
mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = 0;
scene.add(mesh);
});
}
我正在按如下方式加载此对象:
addSTLObject('model/cases/iphone5.stl', 'phone-model');
var phoneModelAdded = scene.getObjectByName('phone-model', true);
现在我已经尝试了这里提供的解决方案:https://github.com/mrdoob/three.js/issues/3471 and here Any way to get a bounding box from a three.js Object3D?
var bbox = new THREE.Box3().setFromObject(phoneModelAdded);
var geometry = phoneModel.children[0].children[0].geometry;
geometry.computeBoundingBox();
虽然第一个解决方案给我一个错误说 "Cannot read property 'updateMatrixWorld' of undefined",但第二个解决方案没有给我任何错误但什么都不做,如果我尝试访问 "geometry" 属性 它说它不存在。
有人有可行的解决方案吗? 感谢您的帮助。
祝你有美好的一天!
编辑:
// Add stl objects and a name
function addSTLObject(url, name) {
var bbox;
var loader = new THREE.STLLoader();
loader.load(url, function (geometry) {
var material = new THREE.MeshPhongMaterial({ color: 0xff5533 });
var mesh = new THREE.Mesh(geometry, material);
// To scale element, use:
// mesh.scale.set(0.01, 0.01, 0.01);
// Add a name to the object to find it if it needs to be removed
mesh.name = name;
mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = 0;
bbox = new THREE.Box3().setFromObject(mesh);
scene.add(mesh);
return bbox;
});
}
及之后
var bbox = addSTLObject('model/cases/iphone5.stl', 'phone-model');
scene.add(bbox);
错误:"THREE.Object3D.add: object not an instance of THREE.Object3D"
编辑 2:
var bbox, bboxComputed = false;
function addSTLObject(url, name) {
var bbox;
var loader = new THREE.STLLoader();
loader.load(url, function (geometry) {
var material = new THREE.MeshPhongMaterial({ color: 0xff5533 });
var mesh = new THREE.Mesh(geometry, material);
// To scale element, use:
// mesh.scale.set(0.01, 0.01, 0.01);
// Add a name to the object to find it if it needs to be removed
mesh.name = name;
mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = 0;
bbox = new THREE.BoundingBoxHelper(mesh);
bbox.update();
bboxComputed = true;
scene.add(mesh);
});
}
addSTLObject('model/cases/iphone5.stl', 'phone-model');
var myInterval = setInterval( function(){
if( bboxComputed ) {
alert( bbox.box.min, bbox.box.max, bbox.box.size() );
scene.add(bbox);
clearInterval( myInterval );
bboxComputed = false;
}
}, 100 );
这行不通。
编辑 3: 我试图建立一个函数,它拥有我需要的一切,并返回一个包含所有计算信息的对象:
function calculateSTLProperties(url, name) {
var STLObject, STLbbox, STLComputed = false, STLGeometry;
var loader = new THREE.STLLoader();
loader.load(url, function (geometry) {
var material = new THREE.MeshPhongMaterial({ color: 0xff5533 });
var mesh = new THREE.Mesh(geometry, material);
// To scale element, use:
// mesh.scale.set(0.01, 0.01, 0.01);
// Add a name to the object to find it if it needs to be removed
mesh.name = name;
mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = 0;
// Compute a bounding box for the element
STLbbox = new THREE.BoundingBoxHelper(mesh);
STLbbox.update();
// Get the geometry of the case
STLGeometry = geometry;
STLComputed = true;
});
// Set an interval to wait for the corresponding bounding box and geometry to be computed
var myInterval = setInterval( function(){
if( STLComputed ) {
STLObject = {
"geometry" : STLGeometry,
"bbox" : STLbbox,
"x" : STLbbox.box.size().x,
"y" : STLbbox.box.size().y,
"z" : STLbbox.box.size().z
};
clearInterval( myInterval );
bboxComputed = false;
}
}, 100 );
return STLObject;
}
不幸的是,不知何故对象没有通过,我在尝试保存它时最终得到了一个 "undefined":
var STLObjectLoaded = calculateSTLProperties('model/cases/iphone5.stl', 'phone-model');
console.log(STLObjectLoaded);
我错过了什么?
模型加载是异步的,因此所有计算都应该在模型加载后进行。添加一个回调,它在模型加载时调用,并在其中添加对 bbox 的调用。你拥有它的方式 scene.getObjectByName()
调用是用一个你也验证的空对象进行的 ("if I try accessing the "geometry" 属性 它说它不存在")
更新:
使用:
var bbox = new THREE.BoundingBoxHelper( mesh ); bbox.update();
scene.add( bbox );
来自 loader.load()
函数内部。
setFromObject()
调用仅创建边界框而不是 bbox 的几何图形。
更新二
如果您希望 bbox
在 loader.load()
函数之外可用,您需要使用全局变量
var bboxComputed = false;
在计算 loader.load()
函数中的 bbox 后立即将其设置为 true:
scene.add( bbox );
bboxComputed = true;
然后在你的 main 而不是使用:
console.log( bbox.box.min, bbox.box.max, bbox.box.size() );
你会使用类似的东西:
var myInterval = setInterval( function(){
if( bboxComputed ) {
console.log( bbox.box.min, bbox.box.max, bbox.box.size() );
clearInterval( myInterval );
}
}, 100 );
我设置了 0.1 秒的延迟,当最终计算出 bbox
时,我清除了间隔,这样它就不会永远 运行。
从 three.js R125 开始,推荐的方法是使用 loadAsync 方法,该方法现在是 three.js:
的原生方法https://threejs.org/docs/#api/en/loaders/Loader.loadAsync
那个方法returns一个承诺。然后,您可以使用 'then' 获取 STL 的几何形状并创建网格。您也可以使用前面答案中的传统回调,或 async/await 结构,但我认为下面使用本机 three.js 方法的示例是最简单的方法。该示例显示了如何在解决承诺并加载 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...
}