使用OrbitControls进行交互时,ThreeJs 3D对象不会停留在修复原点

时间:2018-02-12 15:17:43

标签: 3d three.js

我刚刚开始探索Three.js以完成我需要渲染从maya导出的3D对象的任务,我已设法通过将.obj文件转换为.js来加载此对象使用提供的脚本。

现在我需要添加交互性,例如放大和围绕对象旋转相机,非常类似于此示例here

因此,通过文档OrbitControlsTrackballControls完全符合我的要求,但问题是对象不会停留在修复原点,它会在滚动时旋转,并移动放大和缩小时在飞机周围。

虽然它是非常基本的东西,但我很难弄清楚,我已经尝试为控件设置各种属性,但我无法获得预期的输出。这是我的code

编辑: 屏幕截图

Skull movement screen shot

2 个答案:

答案 0 :(得分:2)

您可以使用THREE.Box3()及其.setFromObject()方法将对象移动到场景的中心(请参阅createScene()函数):

var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
var container;
var camera, scene, controls;
var canvasRenderer, webglRenderer;
var mesh, zmesh, geometry;
var meshes = [];
var mouse = new THREE.Vector2(),
  INTERSECTED;

init();
animate();

function init() {
  container = document.createElement('div');
  document.body.appendChild(container);
  camera = new THREE.PerspectiveCamera(70, SCREEN_WIDTH / SCREEN_HEIGHT, 0.1, 1000);
  camera.position.set( 0, 5, 50 );
  scene = new THREE.Scene();
  // LIGHTS
  var ambient = new THREE.AmbientLight(0x666666);
  scene.add(ambient);
  var directionalLight = new THREE.DirectionalLight(0xffeedd);
  directionalLight.position.set(100, 200, -100).normalize();
  scene.add(directionalLight);

  // RENDERER
  webglRenderer = new THREE.WebGLRenderer();
  webglRenderer.setPixelRatio(window.devicePixelRatio);
  webglRenderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
  webglRenderer.domElement.style.position = "relative";
  container.appendChild(webglRenderer.domElement);

  var loader = new THREE.JSONLoader(),
    callbackKey = function(geometry, materials) {
      createScene(geometry, materials, 0, 0, 0, 20, "skull.jpg")
    };
  loader.load("https://raw.githubusercontent.com/FahadSHK/Skull3d/master/assets/skulld.js", callbackKey);
  controls = new THREE.OrbitControls(camera, webglRenderer.domElement);
  controls.rotateSpeed = 1.0;
  controls.zoomSpeed = 1.5;
  controls.panSpeed = 0.8;
  controls.enableZoom = true;
  controls.enablePan = false;
  controls.enableDamping = true;
  controls.dampingFactor = 0.3;
  controls.keys = [65, 83, 68];
  window.addEventListener('resize', onWindowResize, false);
}
$(document).on('mouseup', function(e) {
  console.log("mouse up called");
  isDragging = false;
});

function createScene(geometry, materials, x, y, z, scale, tmap) {
  zmesh = new THREE.Mesh(geometry, materials);
  zmesh.position.set(x, y, z);
  zmesh.scale.setScalar(scale);
  zmesh.updateMatrixWorld();

  // Move the object to the center of the scene
  var box3 = new THREE.Box3().setFromObject(zmesh);
  zmesh.position.sub(box3.getCenter());

  scene.add(zmesh);
}

function onWindowResize() {
  windowHalfX = window.innerWidth / 2;
  windowHalfY = window.innerHeight / 2;
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  controls.handleResize();
  webglRenderer.setSize(window.innerWidth, window.innerHeight);
}

function animate() {
  requestAnimationFrame(animate);
  controls.update();
  webglRenderer.render(scene, camera);
}
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

供参考:https://discourse.threejs.org/t/problem-with-fbxmodel-position/1617/5

答案 1 :(得分:0)

我带了你的代码并将其修改为在这里的代码片段中运行。 (如你所见,我没有太多修改)。当我运行代码片段时,它的行为完全符合我的预期。我没有看到任何错误的轮换或平移。

看到几个控制台警告,建议您使用旧版本的three.js。尝试更新到最新版本,并修复警告。如果您仍然发现问题,请更新您的帖子,并提供您所看到的视频或动画。

<!DOCTYPE html>
<html lang="en">

<head>
  <title>Skull 3d</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
  <style>
    body {
      margin: 0;
    }
    
    canvas {
      width: 100%;
      height: 100%
    }
  </style>
</head>

<body>

  <script src="https://threejs.org/build/three.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script src="https://threejs.org/examples/js/controls/OrbitControls.js">
  </script>

  <!-- <script src="JSONLoader.js"> </script> -->

  <script>
    var SCREEN_WIDTH = window.innerWidth;
    var SCREEN_HEIGHT = window.innerHeight;
    var container;
    var camera, scene, controls;
    var canvasRenderer, webglRenderer;
    var mesh, zmesh, geometry;
    var windowHalfX = window.innerWidth / 2;
    var windowHalfY = window.innerHeight / 2;
    var meshes = [];
    var mouse = new THREE.Vector2(),
      INTERSECTED;
    var raycaster = new THREE.Raycaster();
    var isDragging = false;
    var previousMousePosition = {
      x: 0,
      y: 0
    };

    init();
    animate();
    //	update(0, totalGameTime);

    function init() {
      container = document.createElement('div');
      document.body.appendChild(container);
      camera = new THREE.PerspectiveCamera(70, SCREEN_WIDTH / SCREEN_HEIGHT, 0.1, 1000);

      camera.position.x = 300;
      camera.position.y = 500;
      camera.position.z = 500;
      // camera.position.set( 100, 200, 100 );
      scene = new THREE.Scene();
      // LIGHTS
      var ambient = new THREE.AmbientLight(0x666666);
      scene.add(ambient);
      var directionalLight = new THREE.DirectionalLight(0xffeedd);
      directionalLight.position.set(100, 200, -100).normalize();
      scene.add(directionalLight);
      // RENDERER
      webglRenderer = new THREE.WebGLRenderer();
      webglRenderer.setPixelRatio(window.devicePixelRatio);

      webglRenderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);

      webglRenderer.domElement.style.position = "relative";
      container.appendChild(webglRenderer.domElement);
      // calculate objects intersecting the picking ray
      //var intersects = raycaster.intersectObjects( scene.children );

      // TheJim01 - Replacing the loader calls with a BoxGeometry, since we can't access the file.
      //var loader = new THREE.JSONLoader(),
      //callbackKey = function(geometry,materials) {createScene(geometry,materials,  0, 0, 0, 20, "chameleon.jpg")};
      //loader.load("skulld.js", callbackKey);
      createScene(new THREE.BoxGeometry(10, 10, 10), new THREE.MeshPhongMaterial({
        color: "red"
      }), 0, 0, 0, 20, "chameleon.jpg");

      controls = new THREE.OrbitControls(camera, webglRenderer.domElement);
      controls.rotateSpeed = 1.0;
      controls.zoomSpeed = 1.5;
      controls.panSpeed = 0.8;
      controls.noZoom = false;
      controls.noPan = false;
      controls.staticMoving = true;
      controls.dynamicDampingFactor = 0.3;
      controls.keys = [65, 83, 68];
      window.addEventListener('resize', onWindowResize, false);
    }
    $(document).on('mouseup', function(e) {
      console.log("mouse up called");
      isDragging = false;
    });

    function createScene(geometry, materials, x, y, z, scale, tmap) {
      // TheJim01 - Creating a standard mesh because we don't have the original model
      zmesh = new THREE.Mesh(geometry, materials);
      //zmesh = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial(materials));
      //zmesh = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({map: THREE.TextureLoader(tmap)}));
      zmesh.position.set(x, y, z);
      zmesh.scale.set(scale, scale, scale);

      meshes.push(zmesh);
      scene.add(zmesh);
    }

    function onWindowResize() {
      windowHalfX = window.innerWidth / 2;
      windowHalfY = window.innerHeight / 2;
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      controls.handleResize();
      webglRenderer.setSize(window.innerWidth, window.innerHeight);
    }

    function animate() {
      requestAnimationFrame(animate);
      controls.update();
      webglRenderer.render(scene, camera);
    }

    function toRadians(angle) {
      return angle * (Math.PI / 180);
    }

    function toDegrees(angle) {
      return angle * (180 / Math.PI);
    }
  </script>
</body>

</html>