Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Smart Centering and Scaling after Model Import in three.js

Tags:

three.js

Is there a way to determine the size and position of a model and then auto-center and scale the model so that it is positioned at the origin and within the view of the camera? I find that when I import a Collada model from Sketchup, if the model was not centered at the origin in Sketchup, then it is not centered in three.js. While that makes sense, it would be nice to auto-center to origin after importing.

I've seen some discussion in the different file loaders about getting the bounds of the imported model, but I have been unable to find any references to how to do that.

The scaling issue is less important, but I feel like it relates to a bounds function, which is why I asked it too.

EDIT:

More info after playing around a bit and a few more google searches...

The code for my callback function on loading the collada file now looks like this:

loader.load(mURL, function colladaReady( collada ) {

dae = collada.scene;
skin = collada.skins[ 0 ];

dae.scale.x = dae.scale.y = dae.scale.z = 1;
dae.updateMatrix();

//set arbitrary min and max for comparison              
var minX = 100000;
var minY = 100000;
var minZ = 100000;
var maxX = 0;
var maxY = 0;
var maxZ = 0;

var geometries = collada.dae.geometries;               
for(var propName in geometries){
if(geometries.hasOwnProperty(propName) && geometries[propName].mesh){
    dae.geometry = geometries[propName].mesh.geometry3js;
    dae.geometry.computeBoundingBox();
    bBox = dae.geometry.boundingBox;
    if(bBox.min.x < minX) minX = bBox.min.x;
    if(bBox.min.y < minY) minY = bBox.min.x;
    if(bBox.min.z < minZ) minZ = bBox.min.z;
    if(bBox.max.x > maxX) maxX = bBox.max.x;
    if(bBox.max.y > maxY) maxY = bBox.max.x;
    if(bBox.max.z > maxZ) maxZ = bBox.max.z;
}
}
//rest of function....

This is generating some interesting data about the model. I can get an overall extreme coordinate for the model, which I'm assuming (probably incorrectly) would be close to an overall bounding box for the model. But trying to do anything with those coordinates (like averaging and moving the model to the averages) generates inconsistent results.

Also, it seems inefficient to have to loop through every geometry for a model, is there a better way? If not, can this logic be applied to other loaders?

like image 695
shadyhill Avatar asked Aug 01 '12 19:08

shadyhill


1 Answers

You can use THREE.Box3#setFromObject to get the bounding box of any Object3D, including an imported model, without having to loop through the geometries yourself. So you could do something like

var bBox = new THREE.Box3().setFromObject(collada.scene);

to get the extreme bounding box of the model; then you could use any of the techniques in the answers that gaitat linked in order to set the camera position correctly. For instance, you could follow this technique (How to Fit Camera to Object) and do something like:

var height = bBox.size().y;
var dist = height / (2 * Math.tan(camera.fov * Math.PI / 360));
var pos = collada.scene.position;
camera.position.set(pos.x, pos.y, dist * 1.1); // fudge factor so you can see the boundaries
camera.lookAt(pos);

Quick fiddle: http://jsfiddle.net/p19r9re2/ .

like image 76
caseygrun Avatar answered Sep 30 '22 18:09

caseygrun