guntrumm
guntrumm

Reputation: 171

generate bounding spheres for child objects

we are trying to generate bounding Spheres for child objects. Sadly we do not know how to get the proper positions for them. Even if the child objects are clearly NOT placed in the center, the position vector is still 0,0,0

We are using the UTF8Loader for importing objects and do not have access to the "standard" vertices array.

Furthermore it looks like bounding radius is calculated by distance from center of the parent.

Any ideas?

Live demo:

Login with this demo account: http://threever.org/login user: Demo passw: demoacc

and go to: threever.org/editor

A picture of the problem: picture

And the code snippet when traversing the object:

object.traverse( function( node ) {
    if( node.geometry ) {
        if(node.geometry.boundingSphere){
            [...]
            var sphere = new THREE.Mesh( spheregeometry, material);
            sphere.position.copy(node.position);
            [...]
            _this.scene.add(sphere);
        }
    }
});

EDIT: We tried the described workflow (thanks @WestLangley) for updating the matrix position but still had no luck. Since it looks like that the bounding spheres are not generated correctly either (in general to large) we decided to try out another approach: We were generating bounding geometry for the sole purpose of having "selection meshes" for ray casting (which can be somewhat difficult if the mesh is THREE.BufferGeometry [not?]). So we looked in the THREE.UTF8Loader file and tried to reconstruct the way geometry is created when useBuffers is false . Then we set the dynamic flag for THREE.BufferGeometry to true which gives access to the attribute Arrays. When the mesh is generated we use our createSelectionDummy function to generate a simplified THREE.Geometry version of the mesh (no uvs, merged Vertices, normal vector(0,0,0)) using the attribute Arrays. What do you think of this technique? Does this have a performance gain vs useBuffers:false ?

this.createSelectionDummy = function( indices, positions ) {

    var geom = new THREE.Geometry();

    for( var i = 0; i < indices.length; i += 3 ) {

        geom.vertices.push( new THREE.Vector3( positions[ i*3 ], positions[ i*3+1 ], positions[ i*3+2 ] ) );
        geom.vertices.push( new THREE.Vector3( positions[ i*3+3 ], positions[ i*3+4 ], positions[ i*3+5 ] ) );
        geom.vertices.push( new THREE.Vector3( positions[ i*3+6 ], positions[ i*3+7 ], positions[ i*3+8 ] ) );

        geom.faces.push( new THREE.Face3( indices[ i ], indices[ i + 1 ], indices[ i + 2 ], new THREE.Vector3(0,0,0) , null, 0 ) ); 

    }

    //reduce mesh size by 3
    geom.mergeVertices();
    geom.computeCentroids();
    geom.computeFaceNormals();

    return (new THREE.Mesh( geom, new THREE.MeshBasicMaterial({wireframe:true}) ));

};

Upvotes: 1

Views: 4985

Answers (1)

WestLangley
WestLangley

Reputation: 104783

You can get an object's world position like so:

var position = object.matrixWorld.getPosition();

It is important to make sure the object's world matrix is updated first. This normally happens in each render call. But if for some reason it is not, you can call the following first:

object.updateMatrixWorld( true );

You can compute the bounding sphere radius object.geometry.boundingSphere.radius this way:

object.geometry.computeBoundingSphere();

Upvotes: 2

Related Questions