我在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);
}
答案 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