煤块掉落动画(自由落体运动)

这里的重点是模型运动位置和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;
            }
        });
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值