Three.js: BoundingBox لكائن Object3D مركب؟

تم إنشاؤها على ٢٦ سبتمبر ٢٠١١  ·  15تعليقات  ·  مصدر: mrdoob/three.js

مرحبا يا شباب،

لدي مثيل Object3D ، والذي يتضمن CubeGeometry و TextGeometry. سؤالي: من الممكن الحصول على
المربع المحيط لهذه الأشكال الهندسية المركبة؟ أسأل هذا ، لأنني رأيت أن فئة Object3D لا تحتوي على أسلوب مربع محيط
وليس لدي أي نهج لحسابه لجميع الكائنات المدرجة في حاوية Object3D.

كانت فكرتي هي توسيط الكاميرا اعتمادًا على حاويات Object3D-centeroid وبالتالي يجب أن أعرف الصندوق المحيط.

تحياتي

Question

التعليق الأكثر فائدة

صادفت هذا أبحث عن نفس الشيء وانتهى بي الأمر بالاستقرار على هذا:

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

ال 15 كومينتر

Object3D لايوجد طريقة لحساب المربع المحيط، ولكن Geometry يفعل .

مع هذا بعيدًا ، ما عليك سوى اتباع هذا .

شكرا حتى الآن. ربما أسأل خطأ ، كان هدفي هو الحصول على الصندوق المحيط لكائنين. أعرف كيفية حساب المربع المحيط لهندسة واحدة ، ولكن عندما يكون لدي كائنات ثلاثية الأبعاد مركبة ، كيف يمكنني حساب المربع المحيط ، على سبيل المثال من مكعبين. أم أنه من الضروري دمج الأشياء من قبل في هندسة واحدة؟

أتمنى أن تكون قد فهمت وجهة نظري :) من الصعب شرحها.

أنا أرى. أعتقد أن الطريقة الوحيدة الآن هي مقارنة جميع المربعات المحيطة والقيام ببعض القيم max() و min() s مع جميع القيم.

حسنا شكرا. سأقوم بنشر الحل الخاص بي إذا نجحت

هذا هو الحل الخاص بي. ببساطة قم بتمرير الكائن إلى هذه الوظيفة وسوف يبحث من خلال أطفاله لحساب ارتفاع / عرض الكائن وتعيين خاصية الارتفاع والعرض للكائن.


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


صادفت هذا أبحث عن نفس الشيء وانتهى بي الأمر بالاستقرار على هذا:

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

تضمين التغريدة

لدي نفس المشكلة بالضبط ونفس الفكرة مثل roundrobin ، منذ عامين. يبدو حل NickLarsen جيدًا حقًا ، كما قال mrdoob ، لكن هناك مشكلة كبيرة ... سأحاول شرحها.

يوجد دائمًا في المشهد الخاص بي كائن واحد ثلاثي الأبعاد يحتوي على جميع الأشكال الهندسية. على سبيل المثال ، لدي 8 كرات بنصف قطر مختلف وإحداثيات y مختلفة. تقع جميعها عند x = 0 و z = 0.
ثم حاولت حساب الصندوق المحيط بأكمله باستخدام الوظيفة من NickLarsen ، لكن النتيجة كانت غريبة جدًا. للعثور على الخطأ ، قمت بتسجيل جميع المربعات المحيطة الفردية بوحدة التحكم:

({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}})
({الحد الأدنى: {س: -3 ، ص: -3 ، ض: -3} ، الحد الأقصى: {س: 3 ، ص: 3 ، ض: 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}})

كما ترى ، يتم حساب المربعات المحيطة دائمًا في نظام الإحداثيات المحلي للكرة الواحدة. وعندما توحدهم ، لا معنى لذلك! كيف يمكنني الحصول على المربع المحيط في إحداثيات العالم للحصول على المربع المحيط الحقيقي لـ Object3D الخاص بي؟

في فرع r.59dev ، راجع Box3.setFromObject( object ) .

PanChan تحتاج إلى ترشيح هنا . أنا مستاء للغاية عندما يتعلق الأمر بهذه الأشياء ، لذا خذ تنفيذي بجرعة جيدة من الشك.

NickLarsen لقد وجدت حلاً آخر يبدو أنه يعمل. بعد حساب المربع المحيط ، قمت بترجمته إلى النظام العالمي:

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

لا أعرف ما إذا كان هذا حلاً جيدًا ، لكنه يعمل في الوقت الحالي. أعتقد أنني في انتظار المراجعة الجديدة مع الحل الاحترافي ؛) شكرًا على التوضيح!

باستخدام حل NickLarsen في مشروعي ، أقوم بعملية حسابية محسّنة قليلاً للحالات التي يوجد فيها المربع المحيط للكائن بالفعل ، وبالتالي فإن حسابه مرة أخرى ليس ضروريًا.

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 إذا كانت الشروط - فهي بالتأكيد ليست مثالاً على الكود الجيد ، ولكن ماذا أفعل ، لكن من الأفضل أن أفعل ذلك؟ :)

هذا حقا خيط قديم في الوقت الحاضر ، يمكنك فقط new THREE.Box3().setFromObject(object3d)

سأحاول هذه الطريقة ، شكرا!

ليس هناك أى مشكلة. لقد مررت بهذا الإدراك قبل بضعة أشهر بنفسي: https://github.com/danielribeiro/three-hub/commit/859f148349ca64ede9ee224d55ad2ea3f51c0da0#diff -0dad6abd7a4801d561b83deddedc1baa

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات