2012-09-28 75 views
3

我創建了一個管狀幾何,數據的點數是從JSON格式的外部JavaScript文件加載的200點。請找到下面的代碼。three.js - 放大/縮小完整的管幾何

<!DOCTYPE html> 
<html lang="en"> 
    <head> 
     <title>3d Model using HTML5 and three.js</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 { 
       font-family: Monospace; 
       background-color: #f0f0f0; 
       margin: 0px; 
       overflow: hidden; 
      } 
     </style> 
    </head> 
    <body>   
     <input type="button" value="plot" onClick="return plotPath();" />   
     <script src="three.min.js" type="text/javascript"></script> 
     <script src="Curve.js" type="text/javascript"></script> 
     <script src="TubeGeometry.js" type="text/javascript"></script>    
     <script src="Stats.js" type="text/javascript"></script> 
     <script src="Detector.js" type="text/javascript"></script>  
     <script src="path.js" type="text/javascript"></script> 

     <script> 

     // variables 
     var container, stats; 

     var camera, scene, renderer, controls, stats; 

     var text, plane, tube, tubeMesh, parent; 

     var targetRotation = 0; 
     var targetRotationOnMouseDown = 0; 

     var mouseX = 0; 
     var mouseXOnMouseDown = 0; 

     var windowHalfX = window.innerWidth/2; 
     var windowHalfY = window.innerHeight/2; 

     var radius = 600; 
     var theta = 0; 
     var PI2 = Math.PI * 2; 

     function plotPath() 
     {           
      var obj = getPath(); 
      var segments = 50; 
      var closed = false; 
      var debug = true; 
      var radiusSegments = 12; 
      var tube; 
      var points = []; 
      var x=0,y=0,z=0;      

      for(var i=0; i<obj.path.length; i++) 
      {        
       console.log(obj.path[i].point); 
       points.push(obj.path[i].point); 
       extrudePath = new THREE.SplineCurve3(points); 
       extrudePath.dynamic = true; 

       tube = new THREE.TubeGeometry(extrudePath, segments, 2, radiusSegments, closed, debug); 
       tube.dynamic = true; 

       tubeMesh = new THREE.Mesh(tube ,new THREE.MeshBasicMaterial({ 
        color: 0x000000, side: THREE.DoubleSide, 
        opacity: 0.5, transparent: true, wireframe: true})); 
       tubeMesh.__dirtyVertices = true; 
       tubeMesh.dynamic = true; 

       parent = new THREE.Object3D(); 
       parent.position.y = 100; 

       if (tube.debug) tubeMesh.add(tube.debug); 
       parent.add(tubeMesh);         
      } 
      scene.add(tubeMesh); 
      scene.add(parent);      

      animate();       
     } 

     init();        

     function init(){ 

      // container 
      container = document.createElement('div'); 
      document.body.appendChild(container);     

      // renderer   
      renderer = new THREE.WebGLRenderer({ antialias: true }); 
      renderer.setClearColorHex(0xEEEEEE, 1.0);    
      renderer.setSize(window.innerWidth, window.innerHeight); 
      renderer.clear(); 
      container.appendChild(renderer.domElement);     

      // camera   
      camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 1, 10000); 
      camera.position.set(-100,75,75);      

      // scene    
      scene = new THREE.Scene(); 
      camera.lookAt(scene.position); 

      // light    
      scene.add(new THREE.AmbientLight(0x404040)); 
      light = new THREE.DirectionalLight(0xffffff); 
      light.position.set(0, 1, 0); 
      scene.add(light); 

      // CONTROLS 
      controls = new THREE.TrackballControls(camera);    

      // Grid 
      geometry = new THREE.Geometry(); 
      geometry.vertices.push(new THREE.Vector3(- 500, 0, 0)); 
      geometry.vertices.push(new THREE.Vector3(500, 0, 0)); 

      for (var i = 0; i <= 20; i ++) { 

       line = new THREE.Line(geometry, new THREE.LineBasicMaterial({ color: 0x000000, opacity: 0.2 })); 
       line.position.z = (i * 50) - 500; 
       scene.add(line); 

       line = new THREE.Line(geometry, new THREE.LineBasicMaterial({ color: 0x000000, opacity: 0.2 })); 
       line.position.x = (i * 50) - 500; 
       line.rotation.y = 90 * Math.PI/180; 
       scene.add(line); 
      }     

      // projector 
      projector = new THREE.Projector(); 

      plotPath(); 

      // stats 
      stats = new Stats(); 
      stats.domElement.style.position = 'absolute'; 
      stats.domElement.style.top = '0px'; 
      container.appendChild(stats.domElement); 

      document.addEventListener('mousedown', onDocumentMouseDown, false); 
      document.addEventListener('mouseover', onDocumentMouseOver, false); 
      document.addEventListener('touchstart', onDocumentTouchStart, false); 
      document.addEventListener('touchmove', onDocumentTouchMove, false); 
      window.addEventListener('DOMMouseScroll', mousewheel, false); 
      window.addEventListener('mousewheel', mousewheel, false); 
      window.addEventListener('resize', onWindowResize, false); 
     } 

     function mousewheel(event) { 

      var fovMAX = 160; 
      var fovMIN = 1; 

      camera.fov -= event.wheelDeltaY * 0.05; 
      camera.fov = Math.max(Math.min(camera.fov, fovMAX), fovMIN); 
      camera.projectionMatrix = new THREE.Matrix4().makePerspective(camera.fov, window.innerWidth/window.innerHeight, camera.near, camera.far); 

     } 

     function onWindowResize() {   
      camera.left = window.innerWidth/- 2; 
      camera.right = window.innerWidth/2; 
      camera.top = window.innerHeight/2; 
      camera.bottom = window.innerHeight/- 2; 
      camera.aspect = window.innerWidth/window.innerHeight;   

      renderer.setSize(window.innerWidth, window.innerHeight); 
     } 


     function onDocumentMouseDown(event) { 
      event.preventDefault(); 

      document.addEventListener('mousemove', onDocumentMouseMove, false); 
      document.addEventListener('mouseup', onDocumentMouseUp, false); 
      document.addEventListener('mouseout', onDocumentMouseOut, false); 
      mouseXOnMouseDown = event.clientX - windowHalfX; 
      targetRotationOnMouseDown = targetRotation;  
     } 

     function onDocumentMouseMove(event) { 
      mouseX = event.clientX - windowHalfX; 
      targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.02; 
     } 

     function onDocumentMouseUp(event) { 
      document.removeEventListener('mousemove', onDocumentMouseMove, false); 
      document.removeEventListener('mouseup', onDocumentMouseUp, false); 
      document.removeEventListener('mouseout', onDocumentMouseOut, false); 
     } 

     function onDocumentMouseOut(event) { 
      document.removeEventListener('mousemove', onDocumentMouseMove, false); 
      document.removeEventListener('mouseup', onDocumentMouseUp, false); 
      document.removeEventListener('mouseout', onDocumentMouseOut, false); 
     } 

     function onDocumentMouseOver(event) { 
      document.removeEventListener('mousemove', onDocumentMouseMove, false); 
      document.removeEventListener('mouseup', onDocumentMouseUp, false); 
      document.removeEventListener('mouseout', onDocumentMouseOut, false); 
     } 

     function onDocumentTouchStart(event) { 
      if (event.touches.length === 1) { 
       event.preventDefault(); 
       mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX; 
       targetRotationOnMouseDown = targetRotation; 
      } 
     } 

     function onDocumentTouchMove(event) { 
      if (event.touches.length === 1) { 
       event.preventDefault(); 
       mouseX = event.touches[ 0 ].pageX - windowHalfX; 
       targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.05; 
      } 
     } 

     function animate() { 
      requestAnimationFrame(animate, renderer.domElement); 
      render(); 
      update(); 
     } 

     function update(){ 
      controls.update();   
     } 

     function toCameraCoords(position) { 
       return camera.matrixWorldInverse.multiplyVector3(position.clone()); 
      } 

     function render() {     
      tubeMesh.rotation.y += (targetRotation - tubeMesh.rotation.y) * 0.15;      
      camera.lookAt(scene.position); 
      camera.updateMatrixWorld(); 
      renderer.render(scene, camera); 
     } 
     </script>   
    </body> 
</html> 

當我使用鼠標滾輪進行放大時,相機將在管的起始點放大。如何使管的幾何圖形可以完全縮放,換句話說,管的任何部分都可以縮放?

+0

暫時我通過使用'THREE.RollControls'實現了這一點。 – Valay

回答

1
document.body.addEventListener('mousewheel', mousewheel, false); 
document.body.addEventListener('DOMMouseScroll', mousewheel, false); // firefox 


function mousewheel(e) {  
    var d = ((typeof e.wheelDelta != "undefined")?(-e.wheelDelta):e.detail); 
    d = 100 * ((d>0)?1:-1); 

    var cPos = camera.position; 
    if (isNaN(cPos.x) || isNaN(cPos.y) || isNaN(cPos.y)) 
     return; 

    var r = cPos.x*cPos.x + cPos.y*cPos.y; 
    var sqr = Math.sqrt(r); 
    var sqrZ = Math.sqrt(cPos.z*cPos.z + r); 


    var nx = cPos.x + ((r==0)?0:(d * cPos.x/sqr)); 
    var ny = cPos.y + ((r==0)?0:(d * cPos.y/sqr)); 
    var nz = cPos.z + ((sqrZ==0)?0:(d * cPos.z/sqrZ)); 

    if (isNaN(nx) || isNaN(ny) || isNaN(nz)) 
     return; 

    cPos.x = nx; 
    cPos.y = ny; 
    cPos.z = nz; 
} 

或者更簡單院校佈局結構調整僅相機:

var mousewheel = function (e) { 
    var d = ((typeof e.wheelDelta != "undefined")?(-e.wheelDelta):e.detail); 
    d = 100 * ((d>0)?1:-1);  
    var cPos = camera.position; 
    if (isNaN(cPos.x) || isNaN(cPos.y) || isNaN(cPos.y)) return; 

     // Your zomm limitation 
     // For X axe you can add anothers limits for Y/Z axes 
     if (cPos.x > _YOUR_ZOOM_MIN_X_ || cPos.x < _YOUR_ZOOM_MAX_X_){ 
      return ; 
     } 

    mb = d>0 ? 1.1 : 0.9; 
    cPos.x = cPos.x * mb; 
    cPos.y = cPos.y * mb; 
    cPos.z = cPos.z * mb; 
} 
+0

非常感謝解決方案。它的工作正常。如何限制此事件處理程序中的放大/縮小距離/因子? - @ foxdanni – Valay

+0

想一想當您的相機處於(0,0,0)時會發生什麼情況。這個解決方案不好。 – Boundless

4

與任何傳統的現實生活中的攝像頭,可以通過調用setLens方法改變THREE.PerspectiveCamera的焦距(變焦)。我覺得這種方式非常直觀,比移動相機放大/縮小要簡單得多。

這裏是three.js所的方法文檔:

/** 
* Uses Focal Length (in mm) to estimate and set FOV 
* 35mm (fullframe) camera is used if frame size is not specified; 
* Formula based on http://www.bobatkins.com/photography/technical/field_of_view.html 
*/ 
THREE.PerspectiveCamera.prototype.setLens = function (focalLength, frameHeight) 
... 

這裏是一個例子用法:

var focalLength = 25.734; // equivalent to FOV=50 
$('#scene').mousewheel(function (event, delta, deltaX, deltaY) { 
    event.preventDefault(); 

    focalLength += deltaY; 
    camera.setLens(focalLength); 
}); 

方法jQuery.fn.mousewheel由Mousewheel Plugin提供。

+0

focalLength的默認值是多少? –

+1

@DanielBahmani,默認值是「25.734」,您可以從三個j中的視野(FOV)的默認值中推導出它的值爲50. setLens函數通過以下簡單公式來更新FOV:FOV = 2 arctan(x /(2f ));請參閱源代碼以獲得更多信息:https://github.com/mrdoob/three.js/blob/af21991fc7c4e1d35d6a93031707273d937af0f9/src/cameras/PerspectiveCamera.js#L34 – Serg

+1

很方便的回答,謝謝。然而,'mouswheel'應該是'mousewheel' – DomTomCat