Three.js: Get center of object

Created on 23 Aug 2011  ·  11Comments  ·  Source: mrdoob/three.js

I encountered problem, - when clicking on some object in scene, camera must center on this object. For this i need center coordinates of object (y axis). How i can compute this? Tried to sum all vertices of this object and divide it on vertices count, but this, of course, wrong decision.

Question

Most helpful comment

You can get center of geometry bounding box:

geometry.computeBoundingBox();

var centerX = 0.5 * ( geometry.boundingBox.x[ 1 ] - geometry.boundingBox.x[ 0 ] );
var centerY = 0.5 * ( geometry.boundingBox.y[ 1 ] - geometry.boundingBox.y[ 0 ] );
var centerZ = 0.5 * ( geometry.boundingBox.z[ 1 ] - geometry.boundingBox.z[ 0 ] );

Then you could set your camera's target to object position plus center:

camera.target.position.copy( object.position );
camera.target.position.addSelf( new THREE.Vector3( centerX, centerY, centerZ ) );

All 11 comments

object.position.y?

in our models it's always 0, models absolutely positoned

What do you mean absolute positioned? All the objects are in 0,0,0 but the vertices cluster isn't around the center?

You can get center of geometry bounding box:

geometry.computeBoundingBox();

var centerX = 0.5 * ( geometry.boundingBox.x[ 1 ] - geometry.boundingBox.x[ 0 ] );
var centerY = 0.5 * ( geometry.boundingBox.y[ 1 ] - geometry.boundingBox.y[ 0 ] );
var centerZ = 0.5 * ( geometry.boundingBox.z[ 1 ] - geometry.boundingBox.z[ 0 ] );

Then you could set your camera's target to object position plus center:

camera.target.position.copy( object.position );
camera.target.position.addSelf( new THREE.Vector3( centerX, centerY, centerZ ) );

This is a little function I wrote a while back. Maybe it'l help you out a bit.

getCentroid: function ( mesh ) {

    mesh.geometry.computeBoundingBox();
    boundingBox = mesh.geometry.boundingBox;

    var x0 = boundingBox.x[ 0 ];
    var x1 = boundingBox.x[ 1 ];
    var y0 = boundingBox.y[ 0 ];
    var y1 = boundingBox.y[ 1 ];
    var z0 = boundingBox.z[ 0 ];
    var z1 = boundingBox.z[ 1 ];


    var bWidth = ( x0 > x1 ) ? x0 - x1 : x1 - x0;
    var bHeight = ( y0 > y1 ) ? y0 - y1 : y1 - y0;
    var bDepth = ( z0 > z1 ) ? z0 - z1 : z1 - z0;

    var centroidX = x0 + ( bWidth / 2 ) + mesh.position.x;
    var centroidY = y0 + ( bHeight / 2 )+ mesh.position.y;
    var centroidZ = z0 + ( bDepth / 2 ) + mesh.position.z;

    return mesh.geometry.centroid = { x : centroidX, y : centroidY, z : centroidZ };

}

you might be able to incorporate alteredq's math (I wish I was smart enough to understand his shortcut)

I wonder... wouldn't it be simpler to do this?

geometry.centroid = new THREE.Vector3();

for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) {

    geometry.centroid.addSelf( geometry.vertices[ i ].position );

} 

geometry.centroid.divideScalar( geometry.vertices.length );

Yeah, if you just need a center this is simpler. If you already have a bounding box, or you need a bounding box for something else, then it's simpler just to compute its center.

Hmmm, now I wonder if these two methods would give the same results. If you have a tons of points at one side and small number of points on other side, center of bounding box would be center of geometry, while centroid would be in "center of gravity", closer to a denser cluster of points.

>>> points = [ 0, 10, 11, 12 ]
>>> sum(points)/float(len(points)) # centroid
8.25
>>> 0.5 * (min(points) + max(points)) # center of bounding box
6.0

I guess both methods are useful, for different use cases.

True that. Centroid of bounding box is what most people would need.

yea I guess mine isn't really a centroid function after all :s

var x0 = boundingBox.x[ 0 ];
var x1 = boundingBox.x[ 1 ];
var y0 = boundingBox.y[ 0 ];
var y1 = boundingBox.y[ 1 ];
var z0 = boundingBox.z[ 0 ];
var z1 = boundingBox.z[ 1 ];

is now:

var x0 = boundingBox.min.x;
var x1 = boundingBox.max.x;
var y0 = boundingBox.min.y;
var y1 = boundingBox.max.y;
var z0 = boundingBox.min.z;
var z1 = boundingBox.max.z;

(as of r47)

Conceptually, it's adding two vectors and taking the half of the result. I'm not sure if it's faster, but it's more... concpetual:

        c.addVectors( 
            object.children[0].geometry.boundingBox.min,
            object.children[0].geometry.boundingBox.max
        );

        c.divideScalar(2);
Was this page helpful?
0 / 5 - 0 ratings