在three.js中

时间:2015-08-04 12:51:43

标签: three.js bounding-box

大家好日子,

我遇到过几个关于这个主题的帖子,但没有解决方案可行。我有一个对象,我在三个.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/3471Any 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();

虽然第一个解决方案给我一个错误,上面写着“无法读取属性'updateMatrixWorld'的未定义”,第二个解决方案没有给我任何错误,但什么也没做,如果我尝试访问“几何”属性,它说它没有存在。

有人有工作解决方案吗? 任何帮助表示赞赏。

祝你有个美好的一天!

修改

        // 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不是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;
}

不幸的是,不知何故,对象没有通过,最后在尝试保存时最终会出现“未定义”:

var STLObjectLoaded = calculateSTLProperties('model/cases/iphone5.stl', 'phone-model');
    console.log(STLObjectLoaded);

我错过了什么?

2 个答案:

答案 0 :(得分:1)

模型加载是异步的,因此所有计算都应在模型加载后进行。添加一个回调,在模型加载时调用,并将调用添加到bbox。 scene.getObjectByName()调用的方式是使用一个空对象进行var bbox = new THREE.BoundingBoxHelper( mesh ); bbox.update(); scene.add( bbox ); 调用,你还要验证("如果我尝试访问"几何"属性,它表示它没有'存在")

<强>更新

使用:

loader.load()

来自setFromObject()函数。

bbox调用仅创建边界框,但不创建bbox的几何体。

更新II

如果您希望在loader.load()功能之外使用var bboxComputed = false; ,则需要使用全局变量

loader.load()

在计算scene.add( bbox ); bboxComputed = true; 函数中的bbox后立即设置为true:

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 );

你会使用类似的东西:

bbox

我设置了0.1秒的延迟,当最终计算出JSP时,我清除了间隔,使其不会永远运行。

答案 1 :(得分: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...
}