cesium模型爆炸案例

在这里插入图片描述

写了一段小小的着色器代码,关于模型爆炸的,原理就是将不同的片元着色器向着法线的方向移动。虽然有点小简陋,但是加入一个小demo的情景倒也可以看看。

废话不多说,直接上代码。

<script type="module">
        import ExplosiveModel from './src/ExplosiveModel.js'
        Cesium.ExperimentalFeatures.enableModelExperimental = true;
        var initCesium = new InitCesium();
        var viewer = initCesium.initViewer("cesiumContainer", {
            orderIndependentTranslucency: false,
            infoBox: false,
            selectionIndicator: false,
            shouldAnimate: true,
        });
        
        var hpr = new Cesium.HeadingPitchRoll(0, 0, 0);
        var fixedFrameTransform = Cesium.Transforms.localFrameToFixedFrameGenerator(
            "north",
            "west"
        );

        var models = {
            milkTruck:
            "./data/model/house/scene.gltf",
        };


        var explosiveModel = new ExplosiveModel(viewer);
        //创建被爆炸的模型
        explosiveModel.createExplosiveModel({
            id:'s22fs',
            modelUrl:"./data/model/house/scene.gltf",
            x:123.0749919,
            y:44.0503726,
            z:4
        });

        var start = Cesium.JulianDate.fromDate(new Date());
        var stop = Cesium.JulianDate.addSeconds(
            start,
            120,
            new Cesium.JulianDate()
        );
        viewer.clock.startTime = start.clone();
        viewer.clock.stopTime = stop.clone();
        viewer.clock.currentTime = start.clone();
        // viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; //Loop at the end
        viewer.clock.multiplier = 1;
        viewer.clock.shouldAnimate = true;
        viewer.timeline.zoomTo(start, stop);
        var planePosition = Cesium.Cartesian3.fromDegrees(123.0749919,44.0503706,4);
        var planePosition2 = Cesium.Cartesian3.fromDegrees(123.2415, 44.0503706, 2000);
        var position = new Cesium.SampledPositionProperty();
        position.addSample(start, planePosition2);
        position.addSample(stop, planePosition);
        var hpr = new Cesium.HeadingPitchRoll(
            3.1,
            -0.2,
            0.0
        );
        var orientation = Cesium.Transforms.headingPitchRollQuaternion(
            planePosition,
            hpr
        );
        var entity = viewer.entities.add({
            model: {
                uri: "./data/model/Cesium_Air.glb",
                scale: 0.11,
            },
            position: position,
            orientation: orientation,
        });
        viewer.trackedEntity = entity;

        
        var cTime = function (scene, time) {
            if(time.secondsOfDay >= stop.secondsOfDay) {
                explosiveModel.modelExplode(explosiveModel.getById('s22fs'));
                viewer.scene.preUpdate.removeEventListener(cTime);
            }
        }
        console.log(cTime)
        viewer.scene.preUpdate.addEventListener(cTime);

    </script>
const {ModelExperimental,CustomShader,Ellipsoid,Transforms,UniformType,Cartesian3,PrimitiveCollection,HeadingPitchRoll} = Cesium;
export default class ExplosiveModel {
    constructor(viewer) {
        this.viewer = viewer;
        this.modelCollection = new PrimitiveCollection();
        this.models = {};

        this.viewer.scene.primitives.add(this.modelCollection);
    }

    /**
     * 创建一个可爆炸的模型实体
     * @param {*} entityData id,modelUrl,x,y,z,hpr
     */
    createExplosiveModel(entityData) {
        const {id,modelUrl,x,y,z,hpr=new HeadingPitchRoll(0, 0, 0),} = entityData;
        const model = this.modelCollection.add(
            ModelExperimental.fromGltf({
                gltf: modelUrl, // "./CesiumMilkTruck.glb",
                customShader: new CustomShader(this._getCustomShader()),
                modelMatrix: Transforms.headingPitchRollToFixedFrame(
                    Cartesian3.fromDegrees(x,y,z),
                    hpr,
                    Ellipsoid.WGS84,
                    Transforms.localFrameToFixedFrameGenerator("north","west")
                ),
            })
        );
        model.readyPromise.then(function (model) {
            viewer.camera.flyToBoundingSphere(model.boundingSphere, {
                duration: 0.5,
            });
        });
        // this.models.push(model);
        this.models[id] = model;
    }

    modelExplode(primitive) {
        primitive.customShader?.setUniform("u_flag", 0);
        
        const timer = window.setTimeout(() => {
            this.modelExplodeStop(primitive);
            window.clearTimeout(timer);
        }, 600);
    }
    modelExplodeStop(primitive) {
        primitive.customShader?.setUniform("u_flag", 1);
    }

    modelExplodeById(id) {
        const model = this.models[id];
        if(model) {
            model.customShader?.setUniform("u_flag", true);
        }
    }

    getById(id) {
        return this.models[id]
    }

    removeAll() {
        // this.models.forEach(model=>{
        //     model.destroy();
        // });
        this.modelCollection = this.modelCollection && this.modelCollection.destroy();
        this.models = {};
    }

    removeById(id) {
        if(this.models[id]) {
            this.modelCollection.remove(this.models[id]);
            delete this.models[id];
            console.log(this.models);
        }
    }

    _getCustomShader () {
        return {
            uniforms: {
                u_flag: {
                    type: UniformType.INT,
                    value: 2,
                },
                // u_drag: {
                //     type: Cesium.UniformType.VEC2,
                //     value: new Cesium.Cartesian2(0.0, 0.0),
                // },
                u_speed: {
                    type:UniformType.FLOAT,
                    value:3.0
                }
                // czm_frameNumber:{
                //     type: Cesium.UniformType.FLOAT,
                //     value: 1.0
                // },
                
            },
            //positionMC +=(vsInput.attributes.normalMC.x , vsInput.attributes.normalMC.y ,0.02 * u_drag.x *  vsInput.attributes.normalMC.z);
            //positionMC += vec3(a_vertex.x ,a_vertex.y ,a_vertex.z)  * vsInput.attributes.normalMC;
            //positionMC += vsInput.attributes.normalMC  * vsInput.attributes.normalMC;
            vertexShaderText: 
            `
                attribute vec4 position;
                void vertexMain(VertexInput vsInput, inout vec3 positionMC)
                {
                    if(u_flag == 0) {
                        float cycle = u_speed * mod(czm_frameNumber , 100.0);
                        positionMC += vsInput.attributes.normalMC * position.xyz;
                        positionMC += 0.01 * cycle * vsInput.attributes.normalMC;
                    }
                    else if(u_flag == 1) {
                        positionMC += 0.01 * 300.0 * vsInput.attributes.normalMC;
                    }
                    else
                    positionMC += 0.01  * vsInput.attributes.normalMC;
                }`
            ,
            // material.diffuse = vec3(flagColor);
            // fragmentShaderText: `
            // void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
            //     gl_FragColor
                
            // }
            // `
        }
    }
}

时间太久远了,去年写的小demo,有些东西也记不清了,但是可以参考借鉴一下。

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值