web-dev-qa-db-fra.com

Est-il possible d'obtenir une boîte englobante à partir d'un Object3D three.js?

Je charge un fichier OBJ à l'aide de Three.js et OBJLoader.js. Cela renvoie un objet Three.Object3D, qui a ce que vous attendez d'un modèle 3D (vecteur de position, vecteur haut ...)

Ce que je ne peux pas comprendre, c'est comment obtenir un cadre de délimitation pour cela - est-ce possible?

44
larryq

Vous n'avez pas besoin d'itérer sur tous les enfants de l'objet; il y a une méthode dans la bibliothèque pour ce faire: THREE.Box3#setFromObject: voir la documentation . Par exemple, vous pouvez faire:

var bbox = new THREE.Box3().setFromObject(obj);

pour obtenir la boîte englobante de obj, y compris tous ses enfants, et en tenant compte des traductions, rotations, etc.

Notez que l'assistant BoundingBox est destiné à dessiner un cadre de délimitation dans la scène, pas seulement pour calculer le cadre de délimitation d'un objet.

71
caseygrun

Si vous voulez la position et la taille du cadre de sélection comme l'objet apparaît dans la scène, essayez le BoundingBoxHelper:

var helper = new THREE.BoundingBoxHelper(someObject3D, 0xff0000);
helper.update();
// If you want a visible bounding box
scene.add(helper);
// If you just want the numbers
console.log(helper.box.min);
console.log(helper.box.max);

Le .boundingBox sur la géométrie ne tient pas compte des traductions, des rotations ou de la mise à l'échelle qui peuvent être appliquées au maillage parent, etc. et j'ai trouvé très difficile de régler cela manuellement, mais l'aide le fait pour vous.

27
ammulder

Pour toute forme, sur son objet géométrique, il existe une propriété boundingBox. Cette propriété contient un THREE.Box3 objet. Cette Box3 l'objet se compose de deux THREE.Vector3 objets, min et max.

var geometry = new THREE.CylinderGeometry(...);
var material = new THREE.LineBasicMaterial(...);
var mesh = new THREE.Mesh(geometry, material);

var boundingBox = mesh.geometry.boundingBox.clone();
alert('bounding box coordinates: ' + 
    '(' + boundingBox.min.x + ', ' + boundingBox.min.y + ', ' + boundingBox.min.z + '), ' + 
    '(' + boundingBox.max.x + ', ' + boundingBox.max.y + ', ' + boundingBox.max.z + ')' );

Pour les formes plus complexes, comme celles chargées à partir de fichiers objets JSON , la propriété du cadre de sélection n'est pas définie par défaut. Il doit être calculé explicitement.

var loader = new THREE.ObjectLoader();
loader.load(imagePath, function(object){

    geometry = object.children[0].children[0].geometry;  // substitute the path to your geometry

    geometry.computeBoundingBox();  // otherwise geometry.boundingBox will be undefined

    var boundingBox = geometry.boundingBox.clone();
    alert('bounding box coordinates: ' + 
        '(' + boundingBox.min.x + ', ' + boundingBox.min.y + ', ' + boundingBox.min.z + '), ' + 
        '(' + boundingBox.max.x + ', ' + boundingBox.max.y + ', ' + boundingBox.max.z + ')' );
}
17
CL22

Oui, vous auriez besoin de quelque chose comme ceci:

if (object instanceof THREE.Object3D)
{
    object.traverse (function (mesh)
    {
        if (mesh instanceof THREE.Mesh)
        {
            mesh.geometry.computeBoundingBox ();
            var bBox = mesh.geometry.boundingBox;

            // compute overall bbox
            minX = Math.min (minX, bBox.min.x);
            minY = Math.min (minY, bBox.min.y);
            minZ = Math.min (minZ, bBox.min.z);
            maxX = Math.max (maxX, bBox.max.x);
            maxY = Math.max (maxY, bBox.max.y);
            maxZ = Math.max (maxZ, bBox.max.z);
        }
    });

    var bBox_min = new THREE.Vector3 (minX, minY, minZ);
    var bBox_max = new THREE.Vector3 (maxX, maxY, maxZ);
    var bBox_new = new THREE.Box3 (bBox_min, bBox_max);

    scene.add (object);
}

MODIFIER:

Cette méthode est antérieure à la disponibilité de la BoundingBoxHelper() ou BoxHelper()

12
gaitat