Cesium 绘制一个旋转发光的四棱锥

示例动态图

在这里插入图片描述

在原创基础上进行了修改

功能描述:
一、四棱锥的生成
二、根据创建的矩阵(Matrix4)进行做动画自身中心轴旋转操作
三、根据矩阵(Matrix4)中的海拔做动画自身跳动
四、贴地纹理赋值

创建四棱锥的几何思路

1.初始化参数

 this.show = true;
    this._command = undefined;
    this._enuMatrix=undefined;
    this._scaleMatrix=undefined;
    this._localPosition=options.position
    this._createCommand = createCommand;
    this._angle=10;
    this._distance=Cesium.defaultValue(options.distance,1);
    this._setInterval=undefined;
    this._viewer=options.viewer;
    this._speed=Cesium.defaultValue(options.speed,1.0);
    this._color=Cesium.defaultValue(options.color,new Cesium.Color(1.0,0.0,0.0,0.8));
    this._scale=Cesium.defaultValue(options.scale,new Cesium.Cartesian3(10, 10, 15));
    this._texture=undefined;
    //this._imageUrl=buildModuleUrl('Assets/Images/fence.png');
	this._imageUrl="./img/fence.png"
    this._modelMatrix=computeModelMatrix(this);
    this._height=computeHeight(this);
    //debugger
    createTexture(this);

2.然后根据坐标创建矩阵(Matrix4)和四棱锥的海拔

 let enuMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(tetrahedronPrimitive._localPosition);
    let scaleMatrix = Cesium.Matrix4.fromScale(tetrahedronPrimitive._scale);
    let modelMatrix = Cesium.Matrix4.multiply(enuMatrix, scaleMatrix, new Cesium.Matrix4());
    tetrahedronPrimitive._scaleMatrix=scaleMatrix;
    tetrahedronPrimitive._enuMatrix=enuMatrix;
    return modelMatrix;

//海拔更新
let point=Cesium.Cartesian3.fromElements(0,0,tetrahedronPrimitive._distance,new Cesium.Cartesian3());
    let enuPoint = Cesium.Matrix4.multiplyByPoint(tetrahedronPrimitive._enuMatrix, point, new Cesium.Cartesian3());
    let upPositionEC = Cesium.Matrix4.multiplyByPoint(tetrahedronPrimitive._viewer.scene.camera._viewMatrix, enuPoint, new Cesium.Cartesian3());
    let upPositionPC = Cesium.Matrix4.multiplyByPoint(tetrahedronPrimitive._viewer.scene.camera.frustum.projectionMatrix, upPositionEC, new Cesium.Cartesian3());
    return Cesium.Cartesian3.normalize(upPositionPC, new Cesium.Cartesian3()).z;

最后根据图片创建四棱锥的纹理

function createTexture(tetrahedronPrimitive){
    var ss = new Cesium.Resource.createIfNeeded(tetrahedronPrimitive._imageUrl).fetchImage().then(function(image){
            var vTexture;
            var context = tetrahedronPrimitive._viewer.scene.context;
        if (defined(image.internalFormat)) {
            vTexture = new Cesium.Texture({
                context: context,
                pixelFormat: image.internalFormat,
                width: image.naturalWidth,
                height: image.naturalHeight,
                source: {
                    arrayBufferView: image.bufferView
                }
            });
        } else {
            vTexture = new Texture({
                context: context,
                source: image
            });
        }
        tetrahedronPrimitive._texture = vTexture;
        });
}

其中主要构造几何如下,创建倒着的四棱锥,构建顶点数组与索引,同时构建四棱锥的三角面数组与索引

function cereatePositionsAndIndice(){
    var positions = new Float64Array(5 * 3);
    // position 0
    positions[0] = 0.0;
    positions[1] = 1.0;
    positions[2] = 0.0;

    // position 1
    positions[3] = -1.0;
    positions[4] = 0.0;
    positions[5] = 0.0;

    // position 2
    positions[6] = 0.0;
    positions[7] = -1.0;
    positions[8] = 0.0;

    // position 3
    positions[9] = 1.0;
    positions[10] = 0.0;
    positions[11] = 0.0;

    // position 4
    positions[12] = 0.0;
    positions[13] = 0.0;
    positions[14] = -1.0;
    var indices = new Uint16Array(6 * 3);
    // back triangle 
    indices[0] = 4;
    indices[1] = 2;
    indices[2] = 3;

    // left triangle
    indices[3] = 4;
    indices[4] = 3;
    indices[5] = 0;

    // right triangle
    indices[6] = 4;
    indices[7] = 0;
    indices[8] = 1;

    // bottom triangle
    indices[9] = 4;
    indices[10] = 1;
    indices[11] = 2;
    // bottom triangle
    indices[12] = 1;
    indices[13] = 2;
    indices[14] = 3;

    // bottom triangle
    indices[15] = 1;
    indices[16] = 3;
    indices[17] = 0;

    // 1.3 定义纹理数组
    var sts = new Float32Array([
        0.0, 0.0, 1.0, 0.0, 1.0, 1.0,
        0.0, 1.0, 0.5, 0.5,
    ]);
   return {
    indices:indices,
    positions:positions,
    sts:sts
   }
}

如图所示,顶点数组构建
在这里插入图片描述
如图所示,四棱锥的三角面构建
顶层矩形也切割成两个三角面
在这里插入图片描述

完整源码脚本,根据原创转化的
function TetrahedronPrimitive(options){
    this.show = true;
    this._command = undefined;
    this._enuMatrix=undefined;
    this._scaleMatrix=undefined;
    this._localPosition=options.position
    this._createCommand = createCommand;
    this._angle=10;
    this._distance=Cesium.defaultValue(options.distance,1);
    this._setInterval=undefined;
    this._viewer=options.viewer;
    this._speed=Cesium.defaultValue(options.speed,1.0);
    this._color=Cesium.defaultValue(options.color,new Cesium.Color(1.0,0.0,0.0,0.8));
    this._scale=Cesium.defaultValue(options.scale,new Cesium.Cartesian3(10, 10, 15));
    this._texture=undefined;
    //this._imageUrl=buildModuleUrl('Assets/Images/fence.png');
	this._imageUrl="./img/fence.png"
    this._modelMatrix=computeModelMatrix(this);
    this._height=computeHeight(this);
    //debugger
    createTexture(this);
}
TetrahedronPrimitive.prototype.update=function(frameState) {
    if (!this.show) {
        return;
    }
    if (!Cesium.defined(this._command)) {
        this._command = this._createCommand(frameState.context,this);
        this._command.pickId = 'v_pickColor';
    }
    if (Cesium.defined(this._command)) {
        frameState.commandList.push(this._command);
    }
}
TetrahedronPrimitive.prototype.isDestroyed=function() {
    return false;
}
TetrahedronPrimitive.prototype.destroy=function() {
    if (Cesium.defined(this._command)) {
        this._command.shaderProgram = this._command.shaderProgram && this._command.shaderProgram.destroy();
    }
    return destroyObject(this);
}
//开启动画
TetrahedronPrimitive.prototype.startAnimate=function(){
   let that=this;
   this._setInterval=setInterval(animateFunc,5);
    function animateFunc(){
        that._angle=that._angle+0.01;
        Math.sin(that._angle)>0?that._height=0.005:that._height=-0.005;
        let translation =  new Cesium.Cartesian3( 0, 0, that._height );
        Cesium.Matrix4.multiplyByTranslation(that._modelMatrix, translation, that._modelMatrix)
        let rotationZ = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(that._speed)));
        Cesium.Matrix4.multiply(that._modelMatrix, rotationZ, that._modelMatrix);
    }
}
//关闭动画
TetrahedronPrimitive.prototype.closeAnimate=function(){
    clearInterval(this._setInterval);
}
//创建command
function createCommand(context,tetrahedronPrimitive) {
    var translucent = false;
    var closed = true;
    var vs=creaateVertexShader();
    var fs=createFragmentShader();
    // 借用一下Appearance.getDefaultRenderState
    var rawRenderState = Cesium.Appearance.getDefaultRenderState(translucent, closed, undefined);
    var renderState = Cesium.RenderState.fromCache(rawRenderState);
    var vertexShaderSource = new Cesium.ShaderSource({
        sources: [vs]
    });
    var fragmentShaderSource = new Cesium.ShaderSource({
        sources: [fs]
    });
    var uniformMap = {
        color: function() {
            return tetrahedronPrimitive._color;
        },
        myImage: function() {
            if (Cesium.defined(tetrahedronPrimitive._texture)) {
                return tetrahedronPrimitive._texture;
            } else {
                return tetrahedronPrimitive._viewer.scene.context.defaultTexture;
            }
        }
    }
    let attributeLocations = {
        position: 0,
        textureCoordinates:1
    };
    var shaderProgram = Cesium.ShaderProgram.fromCache({
        context: context,
        vertexShaderSource: vertexShaderSource,
        fragmentShaderSource: fragmentShaderSource,
        attributeLocations: attributeLocations
    });
    return new Cesium.DrawCommand({
        vertexArray: createVertexArray(context),
        primitiveType: Cesium.PrimitiveType.TRIANGLES,
        renderState: renderState,
        shaderProgram: shaderProgram,
        uniformMap: uniformMap,
        owner: this,
        pass: Cesium.Pass.TRANSLUCENT,
        modelMatrix: tetrahedronPrimitive._modelMatrix,
    });
}
//创建vertexArray
function createVertexArray(context) {
    let attributeLocations = {
        position: 0,
        textureCoordinates:1
    };
    var positionsAndIndice=cereatePositionsAndIndice();
    var geometry = new Cesium.Geometry({
        attributes: {
            position: new Cesium.GeometryAttribute({
                // 使用double类型的position进行计算
                // componentDatatype : Cesium.ComponentDatatype.DOUBLE,
                componentDatatype: Cesium.ComponentDatatype.FLOAT,
                componentsPerAttribute: 3,
                values: positionsAndIndice.positions
            }),
            textureCoordinates: new Cesium.GeometryAttribute({
                componentDatatype: Cesium.ComponentDatatype.FLOAT,
                componentsPerAttribute: 2,
                values: positionsAndIndice.sts
            }),
        },
        // Workaround Internet Explorer 11.0.8 lack of TRIANGLE_FAN
        indices: positionsAndIndice.indices,
        primitiveType: Cesium.PrimitiveType.TRIANGLES,
        boundingSphere: Cesium.BoundingSphere.fromVertices(positionsAndIndice.positions)
    });
    //计算geometry的法向量
    var geometryNormal= Cesium.GeometryPipeline.computeNormal(geometry);
    var vertexArray = Cesium.VertexArray.fromGeometry({
        context: context,
        geometry: geometryNormal,
        attributeLocations: attributeLocations,
        bufferUsage: Cesium.BufferUsage.STATIC_DRAW,
    });

    return vertexArray;
}
//创建顶点数组与索引
function cereatePositionsAndIndice(){
    var positions = new Float64Array(5 * 3);
    // position 0
    positions[0] = 0.0;
    positions[1] = 1.0;
    positions[2] = 0.0;

    // position 1
    positions[3] = -1.0;
    positions[4] = 0.0;
    positions[5] = 0.0;

    // position 2
    positions[6] = 0.0;
    positions[7] = -1.0;
    positions[8] = 0.0;

    // position 3
    positions[9] = 1.0;
    positions[10] = 0.0;
    positions[11] = 0.0;

    // position 4
    positions[12] = 0.0;
    positions[13] = 0.0;
    positions[14] = -1.0;
    var indices = new Uint16Array(6 * 3);
    // back triangle
    indices[0] = 4;
    indices[1] = 2;
    indices[2] = 3;

    // left triangle
    indices[3] = 4;
    indices[4] = 3;
    indices[5] = 0;

    // right triangle
    indices[6] = 4;
    indices[7] = 0;
    indices[8] = 1;

    // bottom triangle
    indices[9] = 4;
    indices[10] = 1;
    indices[11] = 2;
    // bottom triangle
    indices[12] = 1;
    indices[13] = 2;
    indices[14] = 3;

    // bottom triangle
    indices[15] = 1;
    indices[16] = 3;
    indices[17] = 0;

    // 1.3 定义纹理数组
    var sts = new Float32Array([
        0.0, 0.0, 1.0, 0.0, 1.0, 1.0,
        0.0, 1.0, 0.5, 0.5,
    ]);
   return {
    indices:indices,
    positions:positions,
    sts:sts
   }
}
//创建顶点着色器
function creaateVertexShader(){
    var vertexShader =
    `
    attribute vec3 position;
    attribute vec3 normal;
    attribute vec2 st;
    attribute float batchId;
    varying vec3 v_positionEC;
    varying vec3 v_normalEC;
    varying vec2 v_st;
    varying vec4 v_pickColor;
    void main()
    {
        v_positionEC = (czm_modelView * vec4(position, 1.0)).xyz;       // position in eye coordinates
        v_normalEC = czm_normal * normal;                               // normal in eye coordinates
        v_st = st;
        //v_pickColor = czm_batchTable_pickColor(batchId);
        gl_Position = czm_modelViewProjection * vec4(position, 1.0);
    }
    `;
    return vertexShader;
}
//创建片源着色器
function createFragmentShader(){
    var fragmentShader =
    `
    varying vec3 v_positionEC;
    varying vec3 v_normalEC;
    varying vec2 v_st;
    uniform vec4 color;
    varying vec4 v_pickColor;
    uniform sampler2D myImage;
    void main()
    {
        vec3 positionToEyeEC = -v_positionEC;
        vec3 normalEC = normalize(v_normalEC);
    #ifdef FACE_FORWARD
        normalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);
    #endif
        czm_materialInput materialInput;
        materialInput.normalEC = normalEC;
        materialInput.positionToEyeEC = positionToEyeEC;
        materialInput.st = v_st;
        vec2 st = materialInput.st;
        czm_material material = czm_getDefaultMaterial(materialInput);
        float dt_a11 = fract(czm_frameNumber / 100.0) * 3.14159265 * 2.0;
        float dt_a12 = sin(dt_a11);
        float vst=smoothstep(0.7, 1.0, dt_a12)+0.4;
        vec4 colorImage = texture2D(myImage, vec2(fract(st.s- czm_frameNumber*0.003), st.t));
        material.alpha =mix(0.1,1.0,clamp((1.0-st.t) * color.a,0.0,1.0)) +(1.0-sign(st.t-czm_frameNumber*0.001))*0.2*(1.0-colorImage.r)+0.4 ;
        material.diffuse =(1.0-colorImage.a)*vec3(1.0,0.0,0.0)+colorImage.rgb*vec3(color);
     #ifdef FLAT
        gl_FragColor = vec4(material.diffuse + material.emission, material.alpha);
     #else
        gl_FragColor = czm_phong(normalize(positionToEyeEC), material);
		gl_FragColor.a=0.8;
    #endif
    }
    `;
    return fragmentShader;
}
//创建纹理
function createTexture(tetrahedronPrimitive){
    var ss = new Cesium.Resource.createIfNeeded(tetrahedronPrimitive._imageUrl).fetchImage().then(function(image){
            var vTexture;
            var context = tetrahedronPrimitive._viewer.scene.context;
        if (defined(image.internalFormat)) {
            vTexture = new Cesium.Texture({
                context: context,
                pixelFormat: image.internalFormat,
                width: image.naturalWidth,
                height: image.naturalHeight,
                source: {
                    arrayBufferView: image.bufferView
                }
            });
        } else {
            vTexture = new Texture({
                context: context,
                source: image
            });
        }
        tetrahedronPrimitive._texture = vTexture;
        });
}
//计算矩阵
function computeModelMatrix(tetrahedronPrimitive){
    let enuMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(tetrahedronPrimitive._localPosition);
    let scaleMatrix = Cesium.Matrix4.fromScale(tetrahedronPrimitive._scale);
    let modelMatrix = Cesium.Matrix4.multiply(enuMatrix, scaleMatrix, new Cesium.Matrix4());
    tetrahedronPrimitive._scaleMatrix=scaleMatrix;
    tetrahedronPrimitive._enuMatrix=enuMatrix;
    return modelMatrix;
}
//计算高度
function computeHeight(tetrahedronPrimitive){
    let point=Cesium.Cartesian3.fromElements(0,0,tetrahedronPrimitive._distance,new Cesium.Cartesian3());
    let enuPoint = Cesium.Matrix4.multiplyByPoint(tetrahedronPrimitive._enuMatrix, point, new Cesium.Cartesian3());
    let upPositionEC = Cesium.Matrix4.multiplyByPoint(tetrahedronPrimitive._viewer.scene.camera._viewMatrix, enuPoint, new Cesium.Cartesian3());
    let upPositionPC = Cesium.Matrix4.multiplyByPoint(tetrahedronPrimitive._viewer.scene.camera.frustum.projectionMatrix, upPositionEC, new Cesium.Cartesian3());
    return Cesium.Cartesian3.normalize(upPositionPC, new Cesium.Cartesian3()).z;
}
//export default TetrahedronPrimitive
纹理图片

在这里插入图片描述

调用方式
var positionaa = Cesium.Cartesian3.fromDegrees(114.05438735185308, 22.562561467874392, 100.0);
//加入场景
var tetrahedronPrimitive=new TetrahedronPrimitive({
		viewer:viewer,
		position:positionaa,
		color:Cesium.Color.fromCssColorString('#FF0000')
})
scene.primitives.add(tetrahedronPrimitive);
//开启动画
tetrahedronPrimitive.startAnimate();
//关闭动画
//tetrahedronPrimitive.closeAnimate();

与原创结构上不同,原创是基于底层创建新的原型链的
原创链接
最近发现B站上大神的视频,听了一下,受益匪浅,分享给大家
视频链接
需要资源的
资源下载

注意:存在Cesium版本问题,导致部分着色器代码无法加载
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Darren~52HZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值