Three.js教程之编辑关键帧并解析播放 实现源码

3 篇文章 0 订阅
该博客介绍了如何使用Three.js库和FBXLoader加载3D模型,并创建帧动画。通过设置光源、坐标轴、地面纹理以及两个网格模型(Box和Sphere)的动画,展示了如何进行3D场景的构建和动画控制。同时,文章还提供了关键帧数据的编辑和混合器的使用方法,以实现模型的位置、颜色和尺寸变化的动态效果。
摘要由CSDN通过智能技术生成

如下,相关路径自己设置即可
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <title>three.js webgl - FBX loader</title>
    <meta charset="utf-8">
</head>

<body>
<script type="module">
    import * as THREE from '../three.js-dev/build/three.module.js';
    import {OrbitControls} from '../three.js-dev/examples/jsm/controls/OrbitControls.js';

    let camera, scene, renderer;

    const clock = new THREE.Clock();

    let mixer;

    init();
    render();

    function init() {

        const container = document.createElement('div');
        document.body.appendChild(container);

        camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);
        camera.position.set(100, 200, 300);

        scene = new THREE.Scene();


        const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444);
        hemiLight.position.set(0, 200, 0);
        scene.add(hemiLight);

        const dirLight = new THREE.DirectionalLight(0xffffff);
        dirLight.position.set(0, 200, 100);
        dirLight.castShadow = true;
        dirLight.shadow.camera.top = 180;
        dirLight.shadow.camera.bottom = -100;
        dirLight.shadow.camera.left = -120;
        dirLight.shadow.camera.right = 120;
        scene.add(dirLight);
        //创建坐标轴
        const axisHelper = new THREE.AxisHelper(100);
        scene.add(axisHelper)

        // ground
        const loader = new THREE.TextureLoader();
        const texture = loader.load(
            '../three.js-dev/examples/textures/hardwood2_diffuse.jpg'
        );
        texture.wrapS = THREE.RepeatWrapping;
        texture.wrapT = THREE.RepeatWrapping;
        texture.magFilter = THREE.NearestFilter;
        const repeats = 10;
        texture.repeat.set(repeats, repeats);

        const mesh = new THREE.Mesh(new THREE.PlaneGeometry(2000, 2000), new THREE.MeshPhongMaterial({
            map: texture,
            color: 0x999999,
            depthWrite: false
        }));
        mesh.rotation.x = -Math.PI / 2;
        mesh.receiveShadow = true;
        scene.add(mesh);


        // model
        /**
         * 创建两个网格模型并设置一个父对象group
         */
            //创建两个网格模型mesh1、mesh2
        var geometry = new THREE.BoxGeometry(50, 10, 10);
        const sphereGeo = new THREE.SphereGeometry(20, 20, 20);
        var material = new THREE.MeshLambertMaterial({color: 0x0000ff});

        var group = new THREE.Group();
        var mesh1 = new THREE.Mesh(geometry, material);
        var mesh2 = new THREE.Mesh(sphereGeo, material);


        //把mesh1型插入到组group中,mesh1作为group的子对象
        group.add(mesh1);
        //把mesh2型插入到组group中,mesh2作为group的子对象
        group.add(mesh2);
        //把group插入到场景中作为场景子对象
        scene.add(group);

        /**
         * 创建两个网格模型并设置一个父对象group
         */
        mesh1.name = "Box"; //网格模型1命名
        mesh2.name = "Sphere"; //网格模型2命名
        group.add(mesh1); //网格模型添加到组中
        group.add(mesh2); //网格模型添加到组中

        /**
         * 编辑group子对象网格模型mesh1和mesh2的帧动画数据
         */
            // 创建名为Box对象的关键帧数据
        var times = [0, 10]; //关键帧时间数组,离散的时间点序列
        var values = [0, 0, 0, 150, 0, 0]; //与时间点对应的值组成的数组
        // 创建位置关键帧对象:0时刻对应位置0, 0, 0   10时刻对应位置150, 0, 0
        var posTrack = new THREE.KeyframeTrack('Box.position', times, values);
        // 创建颜色关键帧对象:10时刻对应颜色1, 0, 0   20时刻对应颜色0, 0, 1
        var colorKF = new THREE.KeyframeTrack('Box.material.color', [10, 20], [1, 0, 0, 0, 0, 1]);
        // 创建名为Sphere对象的关键帧数据  从0~20时间段,尺寸scale缩放3倍
        var scaleTrack = new THREE.KeyframeTrack('Sphere.scale', [0, 20], [1, 1, 1, 3, 3, 3]);

        // duration决定了默认的播放时间,一般取所有帧动画的最大时间
        // duration偏小,帧动画数据无法播放完,偏大,播放完帧动画会继续空播放
        var duration = 20;
        // 多个帧动画作为元素创建一个剪辑clip对象,命名"default",持续时间20
        var clip = new THREE.AnimationClip("default", duration, [posTrack, colorKF, scaleTrack]);

        /**
         * 播放编辑好的关键帧数据
         */
        // group作为混合器的参数,可以播放group中所有子对象的帧动画
        mixer = new THREE.AnimationMixer(group);
        // 剪辑clip作为参数,通过混合器clipAction方法返回一个操作对象AnimationAction
        var AnimationAction = mixer.clipAction(clip);
        //通过操作Action设置播放方式
        AnimationAction.timeScale = 20;//默认1,可以调节播放速度
        // AnimationAction.loop = THREE.LoopOnce; //不循环播放
        AnimationAction.play();//开始播放

        renderer = new THREE.WebGLRenderer({antialias: true});
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.shadowMap.enabled = true;
        container.appendChild(renderer.domElement);

        const controls = new OrbitControls(camera, renderer.domElement);
        controls.target.set(0, 100, 0);
        controls.update();


    }

    function render() {
        renderer.render(scene, camera); //执行渲染操作
        requestAnimationFrame(render); //请求再次执行渲染函数render,渲染下一帧

        //clock.getDelta()方法获得两帧的时间间隔
        // 更新混合器相关的时间
        mixer.update(clock.getDelta());
    }

</script>

</body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值