Three.js: BoundingBox de un objeto Object3D compuesto?

Creado en 26 sept. 2011  ·  15Comentarios  ·  Fuente: mrdoob/three.js

Hola chicos,

Tengo una instancia de Object3D, que incluye CubeGeometry y TextGeometry. Mi pregunta: es posible obtener el
cuadro delimitador de estas geometrías compuestas? pregunto esto, porque vi que la clase Object3D no tiene un método boundingBox
y no tengo ningún enfoque para calcularlo para todos los objetos incluidos en el contenedor Object3D.

Mi idea fue centrar la cámara dependiendo del Object3D- contenedores centeroid y por lo tanto tengo que conocer el boundingBox.

Saludos roundrobin

Question

Comentario más útil

Me encontré con esto buscando lo mismo y terminé decidiéndome por esto:

function getCompoundBoundingBox(object3D) {
    var box = null;
    object3D.traverse(function (obj3D) {
        var geometry = obj3D.geometry;
        if (geometry === undefined) return;
        geometry.computeBoundingBox();
        if (box === null) {
            box = geometry.boundingBox;
        } else {
            box.union(geometry.boundingBox);
        }
    });
    return box;
}

Todos 15 comentarios

Object3D no tiene un método para calcular el cuadro delimitador, pero Geometry .

Con eso fuera del camino, solo necesita seguir esto .

gracias hasta ahora. tal vez pregunte mal, mi intención era obtener el cuadro delimitador de los dos objetos. Sé cómo calcular el cuadro delimitador para una geometría, pero cuando tengo objetos 3D compuestos, ¿cómo puedo calcular el cuadro delimitador, por ejemplo, de dos cubos? ¿O es necesario fusionar los objetos antes en una geometría?

Espero que hayas entendido mi punto :) es difícil de explicar.

Veo. Supongo que la única forma en este momento es comparar todos los cuadros delimitadores y hacer algunos max() y min() s con todos los valores.

bien gracias. Publicaré mi solución si tengo éxito

Esta es mi solución. Simplemente pase el objeto a esta función y verá a través de sus hijos para calcular el alto / ancho del objeto y asignar una propiedad de alto y ancho al objeto.


calculateDimensions(myObject);

...

/*
* Get the size of the compound object by computing the bounding box and getting the max/min of each of its children
*/
function calculateDimensions(_object) {

    var absoluteMinX = 0, absoluteMaxX = 0, absoluteMinY = 0, absoluteMaxY = 0, absoluteMinZ = 0, absoluteMaxZ = 0;

    for (var i = 0; i < _object.children.length; i++) {
        _object.children[i].geometry.computeBoundingBox();
        absoluteMinX = Math.min(absoluteMinX,_object.children[i].geometry.boundingBox.min.x);
        absoluteMaxX = Math.max(absoluteMaxX,_object.children[i].geometry.boundingBox.max.x);
        absoluteMinY = Math.min(absoluteMinY,_object.children[i].geometry.boundingBox.min.y);
        absoluteMaxY = Math.max(absoluteMaxY,_object.children[i].geometry.boundingBox.max.y);
        absoluteMinZ = Math.min(absoluteMinZ,_object.children[i].geometry.boundingBox.min.z);
        absoluteMaxZ = Math.max(absoluteMaxZ,_object.children[i].geometry.boundingBox.max.z);
    }

    // set generic height and width values
    _object.depth = (absoluteMaxX - absoluteMinX) * _object.scale.x;
    _object.height = (absoluteMaxY - absoluteMinY) * _object.scale.y;
    _object.width = (absoluteMaxZ - absoluteMinZ) * _object.scale.z;

    // remember the original dimensions
    if (_object.originalDepth === undefined) _object.originalDepth = _object.depth;
    if (_object.originalHeight === undefined) _object.originalHeight = _object.height;
    if (_object.originalWidth === undefined) _object.originalWidth = _object.width;

    console.log("Depth: " + _object.depth + ", Height: " + _object.height + ", Width: " + _object.width);
}


Me encontré con esto buscando lo mismo y terminé decidiéndome por esto:

function getCompoundBoundingBox(object3D) {
    var box = null;
    object3D.traverse(function (obj3D) {
        var geometry = obj3D.geometry;
        if (geometry === undefined) return;
        geometry.computeBoundingBox();
        if (box === null) {
            box = geometry.boundingBox;
        } else {
            box.union(geometry.boundingBox);
        }
    });
    return box;
}

@NickLarsen ¡Se ve bien!

Tengo exactamente el mismo problema y la misma idea que roundrobin, hace dos años. La solución de @NickLarsen se ve muy bien, como dijo @mrdoob , pero hay un gran problema ... intentaré explicarlo.

En mi escena siempre hay un Object3D que contiene todas las geometrías. Por ejemplo, tengo 8 esferas con diferente radio y diferente coordenada y. Todos están ubicados en x = 0 y z = 0.
Luego intenté calcular todo el cuadro delimitador con la función de NickLarsen, pero el resultado fue muy extraño. Para encontrar el error, registré todos los cuadros delimitadores individuales en la consola:

({min: {x: -10, y: -10, z: -10}, max: {x: 10, y: 10, z: 10}})
({min: {x: -20, y: -20, z: -20}, max: {x: 20, y: 20, z: 20}})
({min: {x: -7, y: -7, z: -7}, max: {x: 7, y: 7, z: 7}})
({min: {x: -18, y: -18, z: -18}, max: {x: 18, y: 18, z: 18}})
({min: {x: -15, y: -15, z: -15}, max: {x: 15, y: 15, z: 15}})
({min: {x: -3, y: -3, z: -3}, max: {x: 3, y: 3, z: 3}})
({min: {x: -10, y: -10, z: -10}, max: {x: 10, y: 10, z: 10}})
({min: {x: -25, y: -25, z: -25}, max: {x: 25, y: 25, z: 25}})

Como puede ver, los cuadros delimitadores siempre se calculan en el sistema de coordenadas local de la esfera única. ¡Y cuando los unes, no tiene sentido! ¿Cómo puedo obtener el cuadro delimitador en coordenadas mundiales para obtener el cuadro delimitador real de mi Object3D?

En la rama r.59dev, vea Box3.setFromObject( object ) .

@PanChan necesita aquí . Sin embargo, soy bastante novato cuando se trata de estas cosas, así que toma mi implementación con una buena dosis de escepticismo.

@NickLarsen Encontré otra solución que parece funcionar. Después de calcular el cuadro delimitador, lo traduzco al sistema mundial:

var bb = geometry.boundingBox;
bb.translate(obj3D.localToWorld( new THREE.Vector3()));

No sé si es una buena solución, pero funciona por ahora. Creo que estoy esperando la nueva revisión con la solución profesional;) ​​¡Gracias por la explicación!

Usando la solución @NickLarsen en mi proyecto, soy un cálculo un poco optimizado para los casos en los que el cuadro delimitador del objeto ya existe y, por lo tanto, no es necesario volver a calcularlo.

function getComplexBoundingBox(object3D) {
    var box = null;
    object3D.traverse(function(obj3D) {
        if (obj3D.matrixWorldNeedsUpdate) obj3D.updateMatrixWorld();
        var geometry = obj3D.geometry;
        // If current is not a geometry (THREE.Geometry), proceed to the next one
        if (geometry === undefined) return null;
        // If this object is already bounding box, then use it
        if (geometry.boundingBox) { 
            var workableBox = geometry.boundingBox.clone();
            // Move the resulting bounding box to the position of the object itself
            workableBox.applyMatrix4(obj3D.matrixWorld);
            if (box === null) {
                box = workableBox;
            } else {
                box.union(workableBox);
            }
        // If there is no bounding box for current object - creating
        } else {
            var workableGeometry = geometry.clone();
            // Move the resulting geometry in the position of the object itself
            workableGeometry.applyMatrix(obj3D.matrixWorld);
            // Calculate the bounding box for the resulting geometry
            workableGeometry.computeBoundingBox();
            if (box === null) {
                box = workableGeometry.boundingBox;
            } else {
                box.union(workableGeometry.boundingBox);
            }
        }
    });
    return box;
}

5 SI condiciones: ciertamente no es un ejemplo de buen código, pero ¿qué hacer, mejor aún no he funcionado? :)

Este es un hilo muy antiguo. Hoy en día puedes simplemente new THREE.Box3().setFromObject(object3d)

Probaré este método, ¡gracias!

No hay problema. Yo mismo pasé por esta realización hace unos meses: https://github.com/danielribeiro/three-hub/commit/859f148349ca64ede9ee224d55ad2ea3f51c0da0#diff -0dad6abd7a4801d561b83deddedc1baa

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

boyravikumar picture boyravikumar  ·  3Comentarios

zsitro picture zsitro  ·  3Comentarios

yqrashawn picture yqrashawn  ·  3Comentarios

danieljack picture danieljack  ·  3Comentarios

Horray picture Horray  ·  3Comentarios