三个JS:加载OBJ,转换为原点(场景中心),轨道

时间:2016-12-04 21:40:07

标签: javascript three.js 3d-model

我想做的就是加载OBJ文件并将其坐标转换为世界原点(0,0,0),以便轨道控制完美运行(请不要转动点)。

我想加载具有不同几何/中心点的随机OBJ对象,并将它们自动转换为场景原点。换句话说,针对特定模型的“硬编码”翻译解决方案将无效

这必须是Three JS(基本的3d对象查看器)最常见的场景之一,所以我很惊讶我无法在SO上找到明确的解决方案。

不幸的是,有许多旧的答案都有不推荐使用的功能,所以即使有类似的解决方案,我也会非常感谢新答案。

我尝试过的事情

  1. 下面的代码非常适合相机,但不能解决翻译/轨道问题。

    // fit camera to object
    var bBox = new THREE.Box3().setFromObject(scene);
    var height = bBox.size().y;
    var dist = height / (2 * Math.tan(camera.fov * Math.PI / 360));
    var pos = scene.position;
    
    // fudge factor so the object doesn't take up the whole view
    camera.position.set(pos.x, pos.y, dist * 0.5); 
    camera.lookAt(pos);
    
  2. 显然geometry.center()适合将对象的坐标转换回原点,但THREE.GeometryUtils.center已被geometry.center()取代,并且在尝试使用时我一直收到错误它

  3. 加载OBJ时,几何体现已被bufferGeometry取代。我似乎无法将缓冲测量法转换为几何体以便使用center()函数。我必须将它放在对象遍历>这样的孩子循环?这似乎不必要地复杂化了。

    geometry = new THREE.Geometry().fromBufferGeometry( child.geometry );
    
  4. 我的代码只是一个非常简单的OBJLoader。

          var objLoader = new THREE.OBJLoader();
          objLoader.setPath('assets/');
          objLoader.load('BasketballNet_Skull.obj', function (object) {
    
    
                object.traverse( function ( child ) {
    
                    if ( child instanceof THREE.Mesh ) {
    
                       child.material = material;
    
                    }
    
            } );
           scene.add(object);
    });
    

    (BTW关于SO的第一个真正的问题,请原谅任何格式/ noob问题)

3 个答案:

答案 0 :(得分:1)

好的,使用Meshviewer Master的一些非常有用的函数来解决这个问题,Meshviewer Master是一个较旧的Three JS对象查看器。 https://github.com/ideesculture/meshviewer 所有这些都归功于Gautier Michelin的代码 https://github.com/gautiermichelin

加载OBJ后,您需要做三件事:

<强> 1。根据OBJ创建边界框

    boundingbox = new THREE.BoundingBoxHelper(object, 0xff0000);

    boundingbox.update();

    sceneRadiusForCamera = Math.max(
        boundingbox.box.max.y - boundingbox.box.min.y,
        boundingbox.box.max.z - boundingbox.box.min.z,
        boundingbox.box.max.x - boundingbox.box.min.x
    )/2 * (1 + Math.sqrt(5)) ; // golden number to beautify display

<强> 2。根据此边界框/场景半径设置摄像机

function showFront() {
if (objectCopy !== undefined) objectCopy.rotation.z =  0;
    controls.reset();
    camera.position.z = 0;
    camera.position.y = 0;
    camera.position.x = sceneRadiusForCamera;
    camera.lookAt(scene.position);
}

(网格查看器代码还包含用于查看左,上等的函数)

第3。将OBJ重新定位到场景原点 像任何定心练习一样,位置是宽度和高度除以2

function resetObjectPosition(){
    boundingbox.update();

    size.x = boundingbox.box.max.x - boundingbox.box.min.x;
    size.y = boundingbox.box.max.y - boundingbox.box.min.y;
    size.z = boundingbox.box.max.z - boundingbox.box.min.z;

    // Repositioning object
    objectCopy.position.x = -boundingbox.box.min.x - size.x/2;
    objectCopy.position.y = -boundingbox.box.min.y - size.y/2;
    objectCopy.position.z = -boundingbox.box.min.z - size.z/2;
    boundingbox.update();
    if (objectCopy !== undefined) objectCopy.rotation.z =  0;

} 

答案 1 :(得分:1)

为什么不object.geometry.center()

var objLoader = new THREE.OBJLoader();
      objLoader.setPath('assets/');
      objLoader.load('BasketballNet_Skull.obj', function (object) {


            object.traverse( function ( child ) {

                if ( child instanceof THREE.Mesh ) {

                   child.material = material;
                   child.geometry.center();

                }

        } );
       scene.add(object);

答案 2 :(得分:0)

根据我对您的问题的理解,您希望在摄像机视图的原点中添加到场景中的对象。我相信实现对象查看器解决方案的常用方法是在场景中为摄像机添加摄像机控件,主要是THREE.OrbitControls并指定摄像机的目标作为您想要关注的对象。这使得对象聚焦在中心,相机旋转和移动将基于该对象。