分享

君子性非异也,善假于物也

 pengphie 2016-12-21

君子性非异也,善假于物也 - Threejs 引入TrackballControls 查看场景

太阳火神的美丽人生 (http://blog.csdn.net/opengl_es)

本文遵循“署名-非商业用途-保持一致”创作公用协议

转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOSAndroidHTML5、Arduino、pcDuino否则,出自本博客的文章拒绝转载或再转载,谢谢合作。


以下为 html 源文件中引入 TrackballControls 库的关键代码,其中 camera 和 renderer 需要对 Threejs 有所了解方可理解:

[javascript] view plain copy
print?
  1. <script>  
  2.     var controls;  
  3.     controls = new THREE.TrackballControls( camera, renderer.domElement );  
  4.       
  5.     function animate() {  
  6.         requestAnimationFrame( animate, renderer.domElement );  
  7.         controls.update();  
  8.         renderer.render( scene, camera );  
  9.     }  
  10. </script>  

以下代码归原作者所有,但在以下所署两网址未找到与此一致的最新代码,而有一些类似的可用代码,可以参考一下。

上面代码中引用的 js/controls/TrackballControls.js 代码原文,可拷贝可新建 TrackballControls.js 引入,并按上面方式使用即可:

[javascript] view plain copy
print?
  1. /** 
  2.  * @author Eberhard Graether / http:/// 
  3.  * @author Mark Lundin  / http:// 
  4.  */  
  5.   
  6. THREE.TrackballControls = function ( object, domElement ) {  
  7.   
  8.     var _this = this;  
  9.     var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };  
  10.   
  11.     this.object = object;  
  12.     this.domElement = ( domElement !== undefined ) ? domElement : document;  
  13.   
  14.     // API  
  15.   
  16.     this.enabled = true;  
  17.   
  18.     this.screen = { left: 0, top: 0, width: 0, height: 0 };  
  19.   
  20.     this.rotateSpeed = 1.0;  
  21.     this.zoomSpeed = 1.2;  
  22.     this.panSpeed = 0.3;  
  23.   
  24.     this.noRotate = false;  
  25.     this.noZoom = false;  
  26.     this.noPan = false;  
  27.     this.noRoll = false;  
  28.   
  29.     this.staticMoving = false;  
  30.     this.dynamicDampingFactor = 0.2;  
  31.   
  32.     this.minDistance = 0;  
  33.     this.maxDistance = Infinity;  
  34.   
  35.     this.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ];  
  36.   
  37.     // internals  
  38.   
  39.     this.target = new THREE.Vector3();  
  40.   
  41.     var EPS = 0.000001;  
  42.   
  43.     var lastPosition = new THREE.Vector3();  
  44.   
  45.     var _state = STATE.NONE,  
  46.     _prevState = STATE.NONE,  
  47.   
  48.     _eye = new THREE.Vector3(),  
  49.   
  50.     _rotateStart = new THREE.Vector3(),  
  51.     _rotateEnd = new THREE.Vector3(),  
  52.   
  53.     _zoomStart = new THREE.Vector2(),  
  54.     _zoomEnd = new THREE.Vector2(),  
  55.   
  56.     _touchZoomDistanceStart = 0,  
  57.     _touchZoomDistanceEnd = 0,  
  58.   
  59.     _panStart = new THREE.Vector2(),  
  60.     _panEnd = new THREE.Vector2();  
  61.   
  62.     // for reset  
  63.   
  64.     this.target0 = this.target.clone();  
  65.     this.position0 = this.object.position.clone();  
  66.     this.up0 = this.object.up.clone();  
  67.   
  68.     // events  
  69.   
  70.     var changeEvent = { type: 'change' };  
  71.     var startEvent = { type: 'start'};  
  72.     var endEvent = { type: 'end'};  
  73.   
  74.   
  75.     // methods  
  76.   
  77.     this.handleResize = function () {  
  78.   
  79.         if ( this.domElement === document ) {  
  80.   
  81.             this.screen.left = 0;  
  82.             this.screen.top = 0;  
  83.             this.screen.width = window.innerWidth;  
  84.             this.screen.height = window.innerHeight;  
  85.   
  86.         } else {  
  87.   
  88.             var box = this.domElement.getBoundingClientRect();  
  89.             // adjustments come from similar code in the jquery offset() function  
  90.             var d = this.domElement.ownerDocument.documentElement;  
  91.             this.screen.left = box.left + window.pageXOffset - d.clientLeft;  
  92.             this.screen.top = box.top + window.pageYOffset - d.clientTop;  
  93.             this.screen.width = box.width;  
  94.             this.screen.height = box.height;  
  95.   
  96.         }  
  97.   
  98.     };  
  99.   
  100.     this.handleEvent = function ( event ) {  
  101.   
  102.         if ( typeof this[ event.type ] == 'function' ) {  
  103.   
  104.             this[ event.type ]( event );  
  105.   
  106.         }  
  107.   
  108.     };  
  109.   
  110.     var getMouseOnScreen = ( function () {  
  111.   
  112.         var vector = new THREE.Vector2();  
  113.   
  114.         return function ( pageX, pageY ) {  
  115.   
  116.             vector.set(  
  117.                 ( pageX - _this.screen.left ) / _this.screen.width,  
  118.                 ( pageY - _this.screen.top ) / _this.screen.height  
  119.             );  
  120.   
  121.             return vector;  
  122.   
  123.         };  
  124.   
  125.     }() );  
  126.   
  127.     var getMouseProjectionOnBall = ( function () {  
  128.   
  129.         var vector = new THREE.Vector3();  
  130.         var objectUp = new THREE.Vector3();  
  131.         var mouseOnBall = new THREE.Vector3();  
  132.   
  133.         return function ( pageX, pageY ) {  
  134.   
  135.             mouseOnBall.set(  
  136.                 ( pageX - _this.screen.width * 0.5 - _this.screen.left ) / (_this.screen.width*.5),  
  137.                 ( _this.screen.height * 0.5 + _this.screen.top - pageY ) / (_this.screen.height*.5),  
  138.                 0.0  
  139.             );  
  140.   
  141.             var length = mouseOnBall.length();  
  142.   
  143.             if ( _this.noRoll ) {  
  144.   
  145.                 if ( length < Math.SQRT1_2 ) {  
  146.   
  147.                     mouseOnBall.z = Math.sqrt( 1.0 - length*length );  
  148.   
  149.                 } else {  
  150.   
  151.                     mouseOnBall.z = .5 / length;  
  152.                       
  153.                 }  
  154.   
  155.             } else if ( length > 1.0 ) {  
  156.   
  157.                 mouseOnBall.normalize();  
  158.   
  159.             } else {  
  160.   
  161.                 mouseOnBall.z = Math.sqrt( 1.0 - length * length );  
  162.   
  163.             }  
  164.   
  165.             _eye.copy( _this.object.position ).sub( _this.target );  
  166.   
  167.             vector.copy( _this.object.up ).setLength( mouseOnBall.y )  
  168.             vector.add( objectUp.copy( _this.object.up ).cross( _eye ).setLength( mouseOnBall.x ) );  
  169.             vector.add( _eye.setLength( mouseOnBall.z ) );  
  170.   
  171.             return vector;  
  172.   
  173.         };  
  174.   
  175.     }() );  
  176.   
  177.     this.rotateCamera = (function(){  
  178.   
  179.         var axis = new THREE.Vector3(),  
  180.             quaternion = new THREE.Quaternion();  
  181.   
  182.   
  183.         return function () {  
  184.   
  185.             var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() );  
  186.   
  187.             if ( angle ) {  
  188.   
  189.                 axis.crossVectors( _rotateStart, _rotateEnd ).normalize();  
  190.   
  191.                 angle *= _this.rotateSpeed;  
  192.   
  193.                 quaternion.setFromAxisAngle( axis, -angle );  
  194.   
  195.                 _eye.applyQuaternion( quaternion );  
  196.                 _this.object.up.applyQuaternion( quaternion );  
  197.   
  198.                 _rotateEnd.applyQuaternion( quaternion );  
  199.   
  200.                 if ( _this.staticMoving ) {  
  201.   
  202.                     _rotateStart.copy( _rotateEnd );  
  203.   
  204.                 } else {  
  205.   
  206.                     quaternion.setFromAxisAngle( axis, angle * ( _this.dynamicDampingFactor - 1.0 ) );  
  207.                     _rotateStart.applyQuaternion( quaternion );  
  208.   
  209.                 }  
  210.   
  211.             }  
  212.         }  
  213.   
  214.     }());  
  215.   
  216.     this.zoomCamera = function () {  
  217.   
  218.         if ( _state === STATE.TOUCH_ZOOM_PAN ) {  
  219.   
  220.             var factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;  
  221.             _touchZoomDistanceStart = _touchZoomDistanceEnd;  
  222.             _eye.multiplyScalar( factor );  
  223.   
  224.         } else {  
  225.   
  226.             var factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed;  
  227.   
  228.             if ( factor !== 1.0 && factor > 0.0 ) {  
  229.   
  230.                 _eye.multiplyScalar( factor );  
  231.   
  232.                 if ( _this.staticMoving ) {  
  233.   
  234.                     _zoomStart.copy( _zoomEnd );  
  235.   
  236.                 } else {  
  237.   
  238.                     _zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;  
  239.   
  240.                 }  
  241.   
  242.             }  
  243.   
  244.         }  
  245.   
  246.     };  
  247.   
  248.     this.panCamera = (function(){  
  249.   
  250.         var mouseChange = new THREE.Vector2(),  
  251.             objectUp = new THREE.Vector3(),  
  252.             pan = new THREE.Vector3();  
  253.   
  254.         return function () {  
  255.   
  256.             mouseChange.copy( _panEnd ).sub( _panStart );  
  257.   
  258.             if ( mouseChange.lengthSq() ) {  
  259.   
  260.                 mouseChange.multiplyScalar( _eye.length() * _this.panSpeed );  
  261.   
  262.                 pan.copy( _eye ).cross( _this.object.up ).setLength( mouseChange.x );  
  263.                 pan.add( objectUp.copy( _this.object.up ).setLength( mouseChange.y ) );  
  264.   
  265.                 _this.object.position.add( pan );  
  266.                 _this.target.add( pan );  
  267.   
  268.                 if ( _this.staticMoving ) {  
  269.   
  270.                     _panStart.copy( _panEnd );  
  271.   
  272.                 } else {  
  273.   
  274.                     _panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) );  
  275.   
  276.                 }  
  277.   
  278.             }  
  279.         }  
  280.   
  281.     }());  
  282.   
  283.     this.checkDistances = function () {  
  284.   
  285.         if ( !_this.noZoom || !_this.noPan ) {  
  286.   
  287.             if ( _eye.lengthSq() > _this.maxDistance * _this.maxDistance ) {  
  288.   
  289.                 _this.object.position.addVectors( _this.target, _eye.setLength( _this.maxDistance ) );  
  290.   
  291.             }  
  292.   
  293.             if ( _eye.lengthSq() < _this.minDistance * _this.minDistance ) {  
  294.   
  295.                 _this.object.position.addVectors( _this.target, _eye.setLength( _this.minDistance ) );  
  296.   
  297.             }  
  298.   
  299.         }  
  300.   
  301.     };  
  302.   
  303.     this.update = function () {  
  304.   
  305.         _eye.subVectors( _this.object.position, _this.target );  
  306.   
  307.         if ( !_this.noRotate ) {  
  308.   
  309.             _this.rotateCamera();  
  310.   
  311.         }  
  312.   
  313.         if ( !_this.noZoom ) {  
  314.   
  315.             _this.zoomCamera();  
  316.   
  317.         }  
  318.   
  319.         if ( !_this.noPan ) {  
  320.   
  321.             _this.panCamera();  
  322.   
  323.         }  
  324.   
  325.         _this.object.position.addVectors( _this.target, _eye );  
  326.   
  327.         _this.checkDistances();  
  328.   
  329.         _this.object.lookAt( _this.target );  
  330.   
  331.         if ( lastPosition.distanceToSquared( _this.object.position ) > EPS ) {  
  332.   
  333.             _this.dispatchEvent( changeEvent );  
  334.   
  335.             lastPosition.copy( _this.object.position );  
  336.   
  337.         }  
  338.   
  339.     };  
  340.   
  341.     this.reset = function () {  
  342.   
  343.         _state = STATE.NONE;  
  344.         _prevState = STATE.NONE;  
  345.   
  346.         _this.target.copy( _this.target0 );  
  347.         _this.object.position.copy( _this.position0 );  
  348.         _this.object.up.copy( _this.up0 );  
  349.   
  350.         _eye.subVectors( _this.object.position, _this.target );  
  351.   
  352.         _this.object.lookAt( _this.target );  
  353.   
  354.         _this.dispatchEvent( changeEvent );  
  355.   
  356.         lastPosition.copy( _this.object.position );  
  357.   
  358.     };  
  359.   
  360.     // listeners  
  361.   
  362.     function keydown( event ) {  
  363.   
  364.         if ( _this.enabled === false ) return;  
  365.   
  366.         window.removeEventListener( 'keydown', keydown );  
  367.   
  368.         _prevState = _state;  
  369.   
  370.         if ( _state !== STATE.NONE ) {  
  371.   
  372.             return;  
  373.   
  374.         } else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && !_this.noRotate ) {  
  375.   
  376.             _state = STATE.ROTATE;  
  377.   
  378.         } else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && !_this.noZoom ) {  
  379.   
  380.             _state = STATE.ZOOM;  
  381.   
  382.         } else if ( event.keyCode === _this.keys[ STATE.PAN ] && !_this.noPan ) {  
  383.   
  384.             _state = STATE.PAN;  
  385.   
  386.         }  
  387.   
  388.     }  
  389.   
  390.     function keyup( event ) {  
  391.   
  392.         if ( _this.enabled === false ) return;  
  393.   
  394.         _state = _prevState;  
  395.   
  396.         window.addEventListener( 'keydown', keydown, false );  
  397.   
  398.     }  
  399.   
  400.     function mousedown( event ) {  
  401.   
  402.         if ( _this.enabled === false ) return;  
  403.   
  404.         event.preventDefault();  
  405.         event.stopPropagation();  
  406.   
  407.         if ( _state === STATE.NONE ) {  
  408.   
  409.             _state = event.button;  
  410.   
  411.         }  
  412.   
  413.         if ( _state === STATE.ROTATE && !_this.noRotate ) {  
  414.   
  415.             _rotateStart.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );  
  416.             _rotateEnd.copy( _rotateStart );  
  417.   
  418.         } else if ( _state === STATE.ZOOM && !_this.noZoom ) {  
  419.   
  420.             _zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );  
  421.             _zoomEnd.copy(_zoomStart);  
  422.   
  423.         } else if ( _state === STATE.PAN && !_this.noPan ) {  
  424.   
  425.             _panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );  
  426.             _panEnd.copy(_panStart)  
  427.   
  428.         }  
  429.   
  430.         document.addEventListener( 'mousemove', mousemove, false );  
  431.         document.addEventListener( 'mouseup', mouseup, false );  
  432.   
  433.         _this.dispatchEvent( startEvent );  
  434.   
  435.     }  
  436.   
  437.     function mousemove( event ) {  
  438.   
  439.         if ( _this.enabled === false ) return;  
  440.   
  441.         event.preventDefault();  
  442.         event.stopPropagation();  
  443.   
  444.         if ( _state === STATE.ROTATE && !_this.noRotate ) {  
  445.   
  446.             _rotateEnd.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );  
  447.   
  448.         } else if ( _state === STATE.ZOOM && !_this.noZoom ) {  
  449.   
  450.             _zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );  
  451.   
  452.         } else if ( _state === STATE.PAN && !_this.noPan ) {  
  453.   
  454.             _panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );  
  455.   
  456.         }  
  457.   
  458.     }  
  459.   
  460.     function mouseup( event ) {  
  461.   
  462.         if ( _this.enabled === false ) return;  
  463.   
  464.         event.preventDefault();  
  465.         event.stopPropagation();  
  466.   
  467.         _state = STATE.NONE;  
  468.   
  469.         document.removeEventListener( 'mousemove', mousemove );  
  470.         document.removeEventListener( 'mouseup', mouseup );  
  471.         _this.dispatchEvent( endEvent );  
  472.   
  473.     }  
  474.   
  475.     function mousewheel( event ) {  
  476.   
  477.         if ( _this.enabled === false ) return;  
  478.   
  479.         event.preventDefault();  
  480.         event.stopPropagation();  
  481.   
  482.         var delta = 0;  
  483.   
  484.         if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9  
  485.   
  486.             delta = event.wheelDelta / 40;  
  487.   
  488.         } else if ( event.detail ) { // Firefox  
  489.   
  490.             delta = - event.detail / 3;  
  491.   
  492.         }  
  493.   
  494.         _zoomStart.y += delta * 0.01;  
  495.         _this.dispatchEvent( startEvent );  
  496.         _this.dispatchEvent( endEvent );  
  497.   
  498.     }  
  499.   
  500.     function touchstart( event ) {  
  501.   
  502.         if ( _this.enabled === false ) return;  
  503.   
  504.         switch ( event.touches.length ) {  
  505.   
  506.             case 1:  
  507.                 _state = STATE.TOUCH_ROTATE;  
  508.                 _rotateStart.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );  
  509.                 _rotateEnd.copy( _rotateStart );  
  510.                 break;  
  511.   
  512.             case 2:  
  513.                 _state = STATE.TOUCH_ZOOM_PAN;  
  514.                 var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;  
  515.                 var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;  
  516.                 _touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );  
  517.   
  518.                 var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;  
  519.                 var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;  
  520.                 _panStart.copy( getMouseOnScreen( x, y ) );  
  521.                 _panEnd.copy( _panStart );  
  522.                 break;  
  523.   
  524.             default:  
  525.                 _state = STATE.NONE;  
  526.   
  527.         }  
  528.         _this.dispatchEvent( startEvent );  
  529.   
  530.   
  531.     }  
  532.   
  533.     function touchmove( event ) {  
  534.   
  535.         if ( _this.enabled === false ) return;  
  536.   
  537.         event.preventDefault();  
  538.         event.stopPropagation();  
  539.   
  540.         switch ( event.touches.length ) {  
  541.   
  542.             case 1:  
  543.                 _rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );  
  544.                 break;  
  545.   
  546.             case 2:  
  547.                 var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;  
  548.                 var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;  
  549.                 _touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );  
  550.   
  551.                 var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;  
  552.                 var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;  
  553.                 _panEnd.copy( getMouseOnScreen( x, y ) );  
  554.                 break;  
  555.   
  556.             default:  
  557.                 _state = STATE.NONE;  
  558.   
  559.         }  
  560.   
  561.     }  
  562.   
  563.     function touchend( event ) {  
  564.   
  565.         if ( _this.enabled === false ) return;  
  566.   
  567.         switch ( event.touches.length ) {  
  568.   
  569.             case 1:  
  570.                 _rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );  
  571.                 _rotateStart.copy( _rotateEnd );  
  572.                 break;  
  573.   
  574.             case 2:  
  575.                 _touchZoomDistanceStart = _touchZoomDistanceEnd = 0;  
  576.   
  577.                 var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;  
  578.                 var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;  
  579.                 _panEnd.copy( getMouseOnScreen( x, y ) );  
  580.                 _panStart.copy( _panEnd );  
  581.                 break;  
  582.   
  583.         }  
  584.   
  585.         _state = STATE.NONE;  
  586.         _this.dispatchEvent( endEvent );  
  587.   
  588.     }  
  589.   
  590.     this.domElement.addEventListener( 'contextmenu'function ( event ) { event.preventDefault(); }, false );  
  591.   
  592.     this.domElement.addEventListener( 'mousedown', mousedown, false );  
  593.   
  594.     this.domElement.addEventListener( 'mousewheel', mousewheel, false );  
  595.     this.domElement.addEventListener( 'DOMMouseScroll', mousewheel, false ); // firefox  
  596.   
  597.     this.domElement.addEventListener( 'touchstart', touchstart, false );  
  598.     this.domElement.addEventListener( 'touchend', touchend, false );  
  599.     this.domElement.addEventListener( 'touchmove', touchmove, false );  
  600.   
  601.     window.addEventListener( 'keydown', keydown, false );  
  602.     window.addEventListener( 'keyup', keyup, false );  
  603.   
  604.     this.handleResize();  
  605.   
  606.     // force an update at start  
  607.     this.update();  
  608.   
  609. };  
  610.   
  611. THREE.TrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype );  


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多