Three.js: BoundingBox dari objek Object3D gabungan?

Dibuat pada 26 Sep 2011  ·  15Komentar  ·  Sumber: mrdoob/three.js

Hallo teman-teman,

Saya memiliki instance Object3D, yang mencakup CubeGeometry dan TextGeometry. Pertanyaan saya: Anda bisa mendapatkan file
kotak pembatas dari geometri gabungan ini? saya menanyakan ini, karena saya melihat bahwa kelas Object3D tidak memiliki Metode-boundingBox
dan saya tidak memiliki pendekatan untuk menghitungnya untuk semua objek yang termasuk dalam wadah Object3D.

Ide saya adalah untuk memusatkan kamera tergantung pada Object3D- container centeroid dan oleh karena itu saya harus mengetahui boundingBox tersebut.

Salam roundrobin

Question

Komentar yang paling membantu

Saya menemukan ini mencari hal yang sama dan akhirnya memutuskan ini:

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

Semua 15 komentar

Object3D tidak memiliki metode untuk menghitung kotak pembatas, tetapi Geometry memilikinya .

Dengan itu, Anda hanya perlu mengikuti ini .

terima kasih sejauh ini. Mungkin saya salah bertanya, maksud saya adalah mendapatkan kotak pembatas dari dua objek. Saya tahu cara menghitung kotak pembatas untuk satu geometri, tetapi ketika saya memiliki objek 3D gabungan, bagaimana cara menghitung kotak pembatas, misalnya dua kubus. Atau perlu untuk menggabungkan objek sebelumnya menjadi satu geometri?

Saya harap Anda mengerti maksud saya :) sulit untuk dijelaskan.

Saya melihat. Saya kira satu-satunya cara saat ini adalah membandingkan semua kotak pembatas dan melakukan max() dan min() s dengan semua nilai.

oke terima kasih. Saya akan memposting solusi saya jika saya berhasil

Inilah solusi saya. Cukup lewati objek ke fungsi ini dan itu akan melihat melalui turunannya untuk menghitung tinggi / lebar objek dan menetapkan properti tinggi dan lebar ke objek.


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


Saya menemukan ini mencari hal yang sama dan akhirnya memutuskan ini:

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 Terlihat bagus!

Saya memiliki masalah yang persis sama dan ide yang sama dengan roundrobin, dua tahun lalu. Solusi dari @NickLarsen terlihat sangat bagus, seperti yang dikatakan @mrdoob , tetapi ada masalah besar ... Saya akan mencoba menjelaskannya.

Dalam adegan saya selalu ada satu Object3D yang berisi semua geometri. Misalnya saya punya 8 bola dengan radius berbeda dan koordinat y berbeda. Semuanya terletak di x = 0 dan z = 0.
Kemudian saya mencoba menghitung seluruh kotak pembatas dengan fungsi dari NickLarsen, tetapi hasilnya sangat aneh. Untuk menemukan kesalahannya, saya mencatat semua kotak pembatas tunggal ke konsol:

({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}, maks: {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}})

Seperti yang Anda lihat, kotak pembatas selalu dihitung dalam sistem koordinat lokal dari bola tunggal. Dan ketika Anda menyatukannya, itu tidak masuk akal! Bagaimana saya bisa mendapatkan kotak pembatas dalam koordinat dunia untuk mendapatkan kotak pembatas nyata dari Object3D saya?

Di cabang r.59dev, lihat Box3.setFromObject( object ) .

@PanChan Anda perlu meresap transformasi Anda sebelum Anda menjalankan ini dan itu akan bekerja sebagaimana mestinya. Dalam penggunaan aktual saya ini, saya mengkloning geometri untuk setiap objek dan menerapkan transformasinya sebelum menghitung kotak pembatas. Anda dapat melihat implementasi saya yang sebenarnya di sini . Saya cukup pemula dalam hal ini, jadi ambillah implementasi saya dengan skeptisisme yang baik.

@NickLarsen Saya menemukan solusi lain yang tampaknya berhasil. Setelah menghitung kotak pembatas, saya menerjemahkannya ke sistem dunia:

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

Tidak tahu apakah ini solusi yang bagus, tetapi berhasil untuk saat ini. Pikir saya sedang menunggu revisi baru dengan solusi profesional;) ​​Terima kasih atas penjelasannya!

Menggunakan solusi @NickLarsen dalam proyek saya, saya sedikit mengoptimalkan perhitungan untuk kasus-kasus di mana kotak pembatas objek sudah ada, dan dengan demikian menghitungnya lagi tidak diperlukan.

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 Kondisi JIKA - ini tentu bukan contoh kode yang baik, tetapi apa yang harus dilakukan, lebih baik lagi saya belum berhasil? :)

Ini adalah utas yang sangat tua. Saat ini Anda hanya bisa baru new THREE.Box3().setFromObject(object3d)

Saya akan mencoba metode ini, terima kasih!

Tidak masalah. Saya sendiri mengalami realisasi ini beberapa bulan yang lalu: https://github.com/danielribeiro/three-hub/commit/859f148349ca64ede9ee224d55ad2ea3f51c0da0#diff -0dad6abd7a4801d561b83deddedc1baa

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

clawconduce picture clawconduce  ·  3Komentar

scrubs picture scrubs  ·  3Komentar

yqrashawn picture yqrashawn  ·  3Komentar

Horray picture Horray  ·  3Komentar

ghost picture ghost  ·  3Komentar