threeJS将对象从A点移动到B点

时间:2017-12-09 22:35:42

标签: javascript angular three.js webgl

我在SO上看到了一些问题,但我仍然不知道怎么做这样的简单动画。

基本上我只是想把对象从A点移动到b点,我已经做了一些工作,我应用了翻译但是对象不停地移动,我需要我的场景来制作动画。

目前我有这段代码:

import { Component, ViewChild, ElementRef, OnInit } from '@angular/core';
import * as THREE from 'three';
import * as dama from "./dama.json";


const VIEW = {
  angle: 45,
  aspect: screen.width / screen.height,
  near: 0.1,
  far: 1000
}

const matrix = {
  numberPieces: 15,
  brownField: [
    // first row
    {x: -5.95, y: 10, z: 3.95},
    {x: -2.75, y: 10, z: 3.95},
    {x: 0.45, y: 10, z: 3.95},
    {x: 3.6, y: 10, z: 3.95},
    {x: 6.8, y: 10, z: 3.95},
    //second row
    {x: -7.5, y: 10, z: 5.55},
    {x: -4.35, y: 10, z: 5.55},
    {x: -1.15, y: 10, z: 5.55},
    {x: 2, y: 10, z: 5.55},
    {x: 5.15, y: 10, z: 5.55},
    //third row
    {x: -5.95, y: 10, z: 7.15},
    {x: -2.75, y: 10, z: 7.15},
    {x: 0.45, y: 10, z: 7.15},
    {x: 3.6, y: 10, z: 7.15},
    {x: 6.8, y: 10, z: 7.15}

  ],
  blackField: 
  [
    // first row
    {x: -5.95, y: 10, z: -7.2},
    {x: -2.75, y: 10, z: -7.2},
    {x: 0.45, y: 10, z: -7.2},
    {x: 3.6, y: 10, z: -7.2},
    {x: 6.8, y: 10, z: -7.2},
    //second row
    {x: -7.5, y: 10, z: -5.6},
    {x: -4.35, y: 10, z: -5.6},
    {x: -1.15, y: 10, z: -5.6},
    {x: 2, y: 10, z: -5.6},
    {x: 5.15, y: 10, z: -5.6},
    //third row
    {x: -5.95, y: 10, z: -4},
    {x: -2.75, y: 10, z: -4},
    {x: 0.45, y: 10, z: -4},
    {x: 3.6, y: 10, z: -4},
    {x: 6.8, y: 10, z: -4},
  ]
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  private container: HTMLElement;

  @ViewChild('container') elementRef: ElementRef;
  private scene: THREE.Scene;
  private camera: THREE.PerspectiveCamera;
  private renderer: THREE.WebGLRenderer;

  private cube: THREE.Mesh;

  ngOnInit() {
    this.container = this.elementRef.nativeElement;

    this.init();
  }

  init() {
    let screen = {
      width: window.innerWidth,
      height: window.innerHeight,
      color: 0xffffff
    }

    this.scene = new THREE.Scene();
    this.renderer = new THREE.WebGLRenderer();
    this.renderer.setClearColor(0x000000, 1);

    this.renderer.setSize(screen.width, screen.height);
    this.container.appendChild(this.renderer.domElement);
    this.initCamera()
    this.initLights();
    var gameBoard = null;

    const sceneCtx = this.scene;
    const boardLoader = new THREE.JSONLoader();

    /**
     * Here we load the game board
     */
    boardLoader.load("assets/dama.json", (geometry, materials) => {
      gameBoard = new THREE.Mesh(geometry, materials);
      sceneCtx.add(gameBoard);
    });

    this.initPieces();

    this.render();
  }

  render() {

    let self: AppComponent = this;

    (function render() {
      requestAnimationFrame(render);
      self.renderer.render(self.scene, self.camera);
      self.renderer.setClearColor(0xffffff, 1);

      self.animate();
    }());

  }

  onResize(event) {
    this.renderer.setSize(window.innerWidth, window.innerHeight);
  }

  animate() {
    let piece = this.scene.getObjectByName("black-1");

    piece.translateZ(0.1);
  }

  initPieces() {
    const blackPieceLoader = new THREE.JSONLoader();
    const brownPieceLoader = new THREE.JSONLoader();

    const ctx = this;
    let brownPiece = null;
    let blackPiece = null;

    // we load here all the black pieces
    blackPieceLoader.load("assets/black.json", (geometry, materials) => {
      for(let i = 0; i < matrix.numberPieces;i++) {
        blackPiece = new THREE.Mesh(geometry, materials);
        blackPiece.position.set(matrix.blackField[i].x, matrix.blackField[i].y, matrix.blackField[i].z);
        blackPiece.name = "black" + "-" + i;
        ctx.scene.add(blackPiece);
      }
    });

    // we load here all the brown pieces
    brownPieceLoader.load("assets/brown.json", (geometry, materials) => {
      for(let i = 0; i < matrix.numberPieces;i++) {
        brownPiece = new THREE.Mesh(geometry, materials);
        brownPiece.position.set(matrix.brownField[i].x, matrix.brownField[i].y, matrix.brownField[i].z);
        brownPiece.name = "brown" + "-" + i;
        ctx.scene.add(brownPiece);
      }
    });
  }

  initLights() {
    var light = new THREE.AmbientLight(0xffffff);
    this.scene.add(light);
  }

  initCamera() {
    this.camera = new THREE.PerspectiveCamera(VIEW.angle, VIEW.aspect, VIEW.near, VIEW.far);    
    this.scene.add(this.camera);
    this.scene.add(new THREE.AxisHelper(20));
    this.camera.position.set(0, 35, 0);
    this.camera.lookAt(new THREE.Vector3(0, 0, 0));
  }

}

在动画内部我想将单个对象从a点移动到B点,为了测试点b可以是任何东西,A点是当我创建他时,我指向一个名字的对象的当前位置for loop:

重要部分

  animate() {
    let piece = this.scene.getObjectByName("black-1");

    piece.translateZ(0.1);
  }

1 个答案:

答案 0 :(得分:7)

您可以使用线性插值将某些内容从A移动到B.通用公式为:

p = a + (b - a) * t

其中t的范围是[0.0,1.0]。您可以将其应用于需要设置动画的每个轴(x,y,z)。

例如,

t可以绑定到建议的时间,因为在浏览器环境中无法保证恒定的帧速率,或者对于非实时渲染非常有用的帧。

t绑定时间

您可以通过以下方式计算t

var startTime;
var duration = 2000;              // milliseconds

function loop(currentTime) {
  if (!startTime) startTime = currentTime;
  var t = (currentTime - startTime) / duration;
  // use t here, optionally clamp and/or add conditions
  requestAnimationFrame(loop);    // provides current high-res time as argument
}

t绑定到框架

对于每帧方法,您可以像这样计算t

var fps = 60;
var duration = 2.0;               // seconds
var step = 1 / (duration * fps);  // t-step per frame
var t = 0;

... loop here
t += step;

当然,您可以在t之前运行lerp(),然后再将其传递给lerp,以便更顺畅地显示过渡。

var scene, renderer, cam, mesh; // linear interpolation function function lerp(a, b, t) {return a + (b - a) * t} var t = 0, dt = 0.02, // t (dt delta for demo) a = {x: -2, y: -1, z: -1}, // start position b = {x: 1.5, y: 0.5, z: 0.7}; // end position function loop() { var newX = lerp(a.x, b.x, ease(t)); // interpolate between a and b where var newY = lerp(a.y, b.y, ease(t)); // t is first passed through a easing var newZ = lerp(a.z, b.z, ease(t)); // function in this example. mesh.position.set(newX, newY, newZ); // set new position t += dt; if (t <= 0 || t >=1) dt = -dt; // ping-pong for demo renderer.render(scene, cam); requestAnimationFrame(loop) } // example easing function (quadInOut, see link above) function ease(t) { return t<0.5 ? 2*t*t : -1+(4-2*t)*t} // setup scene scene = new THREE.Scene(); renderer = new THREE.WebGLRenderer(); cam = new THREE.PerspectiveCamera(40, innerWidth / innerHeight, 1, 50); mesh = new THREE.Mesh(new THREE.BoxBufferGeometry(), new THREE.MeshBasicMaterial()); renderer.setPixelRatio(devicePixelRatio); renderer.setSize(innerWidth, innerHeight); cam.position.z = 5; document.body.appendChild(renderer.domElement); scene.add(mesh); loop();

的基本示例

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.min.js"></script>
Image