温馨提示:本文翻译自stackoverflow.com,查看原文请点击:javascript - Threejs how to make The Camera Shake
javascript three.js

javascript - Threejs如何使相机震动

发布于 2020-04-08 12:11:57

我无法弄清楚这个问题,我已经在网上搜索了几个小时,如果可以的话,他们找不到任何可以做的事情,所以请让我知道我希望这是可能的,我发现这是一个摘要,所以我该怎么做有可能,更重要的是,有人可以告诉我如何少做些什么,以及怎么做,因为我不知道ps,我需要能够从编辑器中做到这一点

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

	<body>

		<div id="container"></div>

		<div id="info">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/105/three.min.js"></script>

    <input type="button" onClick="shake()" value="click me"></input>
		<script>
    


			////////////////////////////
      ///   INITIALIZATION
      ////////////////////////////
      
      
      var screenShake = ScreenShake();
      
      
      // Create an empty scene
      var scene = new THREE.Scene();
      scene.background = new THREE.Color(0x9fff89);

      // Create a basic perspective camera
      var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
      camera.position.set(0,0,50);
      camera.lookAt(0,0,0);

      // Create a renderer with Antialiasing
      var renderer = new THREE.WebGLRenderer({antialias:true});

      // Configure renderer size
      renderer.setSize( window.innerWidth, window.innerHeight );

      // Append Renderer to DOM
      document.body.appendChild( renderer.domElement );
      
      
      
      
      
      ////////////////////////
      ///  MESHES CREATION
      ////////////////////////
      
      var ball = new THREE.Mesh(new THREE.SphereBufferGeometry(4, 16, 16),
      													new THREE.MeshNormalMaterial);
      scene.add(ball)
      
      for (let i=0 ; i<30 ; i++) {
      	makeMesh();
      };
      
      function makeMesh() {
      	var mesh = new THREE.Mesh(new THREE.BoxBufferGeometry(5, 5, 5),
      													new THREE.MeshNormalMaterial);
        mesh.position.set(rand(), rand(), rand());
                                
      	scene.add(mesh);
        function rand() {return (Math.random()-0.5)*60}
      }
      
      
      
      
      
      
      ////////////////////////
      ///  SCREEN SHAKE
      ////////////////////////
      
      function ScreenShake() {

        return {

          // When a function outside ScreenShake handle the camera, it should
          // always check that ScreenShake.enabled is false before.
          enabled: false,

          _timestampStart: undefined,

          _timestampEnd: undefined,

          _startPoint: undefined,

          _endPoint: undefined,


          // update(camera) must be called in the loop function of the renderer,
          // it will repositioned the camera according to the requested shaking.
          update: function update(camera) {
            if ( this.enabled == true ) {
              const now = Date.now();
              if ( this._timestampEnd > now ) {
                let interval = (Date.now() - this._timestampStart) / 
                  (this._timestampEnd - this._timestampStart) ;
                this.computePosition( camera, interval );
              } else {
                camera.position.copy(this._startPoint);
                this.enabled = false;
              };
            };
          },


          // This initialize the values of the shaking.
          // vecToAdd param is the offset of the camera position at the climax of its wave.
          shake: function shake(camera, vecToAdd, milliseconds) {
            this.enabled = true ;
            this._timestampStart = Date.now();
            this._timestampEnd = this._timestampStart + milliseconds;
            this._startPoint = new THREE.Vector3().copy(camera.position);
            this._endPoint = new THREE.Vector3().addVectors( camera.position, vecToAdd );
          },


          computePosition: function computePosition(camera, interval) {

            // This creates the wavy movement of the camera along the interval.
            // The first bloc call this.getQuadra() with a positive indice between
            // 0 and 1, then the second call it again with a negative indice between
            // 0 and -1, etc. Variable position will get the sign of the indice, and
            // get wavy.
            if (interval < 0.4) {
              var position = this.getQuadra( interval / 0.4 );
            } else if (interval < 0.7) {
              var position = this.getQuadra( (interval-0.4) / 0.3 ) * -0.6;
            } else if (interval < 0.9) {
              var position = this.getQuadra( (interval-0.7) / 0.2 ) * 0.3;
            } else {
              var position = this.getQuadra( (interval-0.9) / 0.1 ) * -0.1;
            }

            // Here the camera is positioned according to the wavy 'position' variable.
            camera.position.lerpVectors( this._startPoint, this._endPoint, position );
          },

          // This is a quadratic function that return 0 at first, then return 0.5 when t=0.5,
          // then return 0 when t=1 ;
          getQuadra: function getQuadra(t) {
            return 9.436896e-16 + (4*t) - (4*(t*t)) ;
          }

        };

      };
      
      
      
      
      
      
      //////////////////////
      ////  EVENT
      //////////////////////
      
      function shake() {
      	screenShake.shake( camera, new THREE.Vector3(0.5, -1, 1.5), 250 );
      }
      
      
      


			//////////////////////
      ////  LOOP
      //////////////////////

      loop()

			function loop() {
      
      if (ball.position.z < 45) {
      	ball.position.z += 0.5 ;
      } else {
      	ball.position.z = 0;
        screenShake.shake( camera, new THREE.Vector3(0, 0, 2.5), 250 );
      };
      	
      
      	screenShake.update(camera);

				requestAnimationFrame( loop );
        renderer.render( scene, camera );
			}

		</script>

	</body>
</html>

查看更多

提问者
ArticScript
被浏览
69
Thomas Hesse 2020-02-01 11:18

这部分对您提出的问题至关重要。相机vecToAdd可能会根据晃动(x, y, z)我对其进行了调整,使其在z方向上的抖动程度降低了(可能是0.25px)。

      //////////////////////
      ////  LOOP
      //////////////////////

      loop()

      function loop() {

        if (ball.position.z < 45) {
          ball.position.z += 0.5;
        } else {
          ball.position.z = 0;
          screenShake.shake(camera, new THREE.Vector3(0, 0, 0.25), 250);
        };


        screenShake.update(camera);

        requestAnimationFrame(loop);
        renderer.render(scene, camera);
      }