Centrado y escala inteligente después de la importación del modelo en three.js
(1)
Puede usar THREE.Box3#setFromObject
para obtener el cuadro delimitador de cualquier Object3D, incluido un modelo importado, sin tener que recorrer las geometrías usted mismo. Entonces podrías hacer algo como
var bBox = new THREE.Box3().setFromObject(collada.scene);
para obtener el cuadro delimitador extremo del modelo; entonces puedes usar cualquiera de las técnicas en las respuestas que enlaza la gaita para establecer correctamente la posición de la cámara. Por ejemplo, puede seguir esta técnica ( Cómo ajustar la cámara al objeto ) y hacer algo como:
var height = bBox.size().y;
var dist = height / (2 * Math.tan(f * 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 violín: http://jsfiddle.net/p19r9re2/ .
¿Hay alguna forma de determinar el tamaño y la posición de un modelo y, a continuación, centrar automáticamente y escalar el modelo para que se ubique en el origen y dentro de la vista de la cámara? Me parece que cuando importo un modelo de Collada desde Sketchup, si el modelo no estaba centrado en el origen en Sketchup, entonces no está centrado en three.js. Si bien eso tiene sentido, sería bueno autocentrar al origen después de la importación.
He visto una discusión en los cargadores de archivos diferentes sobre cómo obtener los límites del modelo importado, pero no he podido encontrar ninguna referencia sobre cómo hacerlo.
El problema de escalamiento es menos importante, pero siento que se relaciona con una función de límites, por lo que también lo pregunté.
EDITAR:
Más información después de jugar un poco y algunas búsquedas de google más ...
El código para mi función de devolución de llamada al cargar el archivo collada ahora se ve así:
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....
Esto genera algunos datos interesantes sobre el modelo. Puedo obtener una coordenada extrema global para el modelo, que asumo (probablemente incorrectamente) que estaría cerca de un cuadro delimitador general para el modelo. Pero intentar hacer algo con esas coordenadas (como promediar y mover el modelo a los promedios) genera resultados inconsistentes.
Además, parece ineficiente tener que pasar por todas las geometrías de un modelo, ¿hay alguna otra manera mejor? De lo contrario, ¿se puede aplicar esta lógica a otros cargadores?