这里的重点是模型运动位置和time关联,由于场景运行过程中一直在刷新,默认帧率为60fps(表示1秒刷新60次屏幕,可能会受到场景运行数据量大等问题帧率减小,先按默认来计算,后续可以将帧率写成动态的)。所以根据自由落体公式:s =v * t + 0.5 * g * Math.pow ( t , 2 ) 这里的参数t,换算成每一帧的时间为1/60。所以代入计算即可正确模拟物体掉落了。
注意:这里模型不是一直生成的,而是写一个判断条件,当煤块掉落到达指定条件,煤块自动变成原始位置。注意过程中煤块材质共用、结构共用。
效果:
核心代码:
/**
* 煤块采掘动画
* @param {Object} model 发射父对象
* @param {THREE.Vector3} seedPoint 发射点偏移位置
* @param {Number} dir 发射方向,正方向为-1,反方向为1
*/
cmAnim(model, seedPoint, dir) {
const map = new THREE.TextureLoader().load(
"/threeJS/textures/meikuai.png"
);
map.encoding = THREE.sRGBEncoding;
var rock = new THREE.BoxGeometry(1, 1, 1);
var rockMaterial = new THREE.MeshBasicMaterial({
map: map,
transparent: true,
side: THREE.DoubleSide
});
var rockMesh = new THREE.Mesh(rock, rockMaterial);
model.updateWorldMatrix();
const group = new THREE.Group();
for (let i = 0; i < 150; ++i) {
let tempRock = rockMesh.clone();
let size = Math.random() * 0.2 + 0.1;
tempRock.scale.set(size, size, size);
tempRock.userData = {
vx: 0,
vy: Math.random() * 0.5,
vz: 0,
x: seedPoint.x,
y: seedPoint.y + Math.random(),
z: Math.random(),
time: 0,
};
tempRock.renderOrder = 1;
group.add(tempRock);
}
model.add(group);
let mat = new THREE.Matrix4();
mat.extractRotation(model.matrixWorld);
mat.invert();
group.matrixWorld.multiply(mat);
let a = new THREE.Vector3();
group.matrixWorld.decompose(a, group.quaternion, a);
// this.scene.add(group);
// 自由落体公式 s = 0.5*g*t*t;
const g = -9.8; // 重力加速度
const minY = -1; // 最低高度
this.renderEntities.push(() => {
if (!this.cmModel.open) return;
for (let i = 0; i < group.children.length; ++i) {
let info = group.children[i].userData;
if (info.y > minY) {
info.x += info.vx * info.time;
info.y += info.vy * info.time + 0.5 * g * Math.pow(info.time, 2);
info.z += info.vz * info.time;
info.time += 1 / 60; // 每一秒60帧,所以这里的每一帧的时间是1/60.
} else {
group.children[i].userData = {
vx: Math.random() * 0.7 * dir,
vy: -Math.random() * 0.5,
vz: -Math.random(),
x: seedPoint.x + Math.random(),
y: seedPoint.y + Math.random(),
z: Math.random(),
time: 0,
};
}
group.children[i].position.x = info.x;
group.children[i].position.y = info.y;
group.children[i].position.z = info.z;
}
});
}