四面体顶点动画实现位移和旋转。
import * as Cesium from 'cesium';// Fragment Shader for Tetrahedron
const fs = `
in vec3 v_positionEC;
in vec3 v_normalEC;
in vec2 v_st;
uniform vec4 color;
uniform float alpha;void main() {vec3 positionToEyeEC = -v_positionEC;vec3 normalEC = normalize(v_normalEC);#ifdef FACE_FORWARDnormalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);#endifczm_materialInput materialInput;materialInput.normalEC = normalEC;materialInput.positionToEyeEC = positionToEyeEC;materialInput.st = v_st;vec2 st = materialInput.st;czm_material material = czm_getDefaultMaterial(materialInput);material.alpha = alpha;material.diffuse = color.rgb * 1.5;#ifdef FLATout_FragColor = vec4(material.diffuse + material.emission, material.alpha);#elseout_FragColor = czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC);#endif
}
`;// Vertex Shader for Tetrahedron
const vs = `
in vec3 position;
in vec3 normal;
in vec2 st;
in float batchId;
out vec3 v_positionEC;
out vec3 v_normalEC;
out vec2 v_st;
uniform float moveMaxHeight;mat4 rotationAroundZ(float angle)
{float s = sin(angle);float c = cos(angle);return mat4(c, -s, 0.0, 0.0,s, c, 0.0, 0.0,0.0, 0.0, 1.0, 0.0,0.0, 0.0, 0.0, 1.0);
}mat4 translationMatrix (float z) {return mat4(1.0, 0.0, 0.0, 0.0,0.0, 1.0, 0.0, 0.0,0.0, 0.0, 1.0, 0.,0.0, 0.0, z, 1.0);
}void main() {// 提取z轴缩放因子float scaleZ = length(czm_model[2].xyz);float uTime = czm_frameNumber * 0.04;float offsetZ = sin(uTime) * moveMaxHeight / 2.;mat4 translationMatrix = translationMatrix(1.0/scaleZ * offsetZ);mat4 rotationMatrix = rotationAroundZ(uTime);vec4 vertex = translationMatrix * rotationMatrix * vec4(position, 1.0);vec4 mvVertex = czm_modelView * vertex;gl_Position = czm_projection * mvVertex;v_positionEC = mvVertex.xyz;v_normalEC = czm_normal * normal;v_st = st;
}
`;export class TetrahedronPrimitive {constructor(options) {this.position = options.position;this.width = options.width || 1;this.height = options.height || 1;this.depth = options.depth || 1;this._modelMatrix = null;this._dirty = true;this.drawCommand = null;this.moveMaxHeight = 0;}// Model matrix getter with lazy computationget modelMatrix() {if (this._dirty) {const fixedFrameTransform = Cesium.Transforms.localFrameToFixedFrameGenerator('east', 'north');const mat4 = fixedFrameTransform(this.position);const scale = Cesium.Matrix4.fromScale(new Cesium.Cartesian3(this.width, this.width, this.depth));this._modelMatrix = Cesium.Matrix4.multiply(mat4, scale, new Cesium.Matrix4());this._dirty = false;}return this._modelMatrix;}// Method to generate positions, texture coordinates, and indicesgenerateGeometryData() {const positions = new Float64Array([0, 1, 0, -1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, -1]);const indices = new Uint16Array([4, 2, 3, 4, 3, 0, 4, 0, 1, 4, 1, 2, 1, 2, 3, 1, 3, 0]);const textureCoordinates = new Float32Array([0, 0, 1, 0, 1, 1, 0, 1, 0.5, 0.5]);return {positions,indices,textureCoordinates};}// Method to create vertex arraycreateVertexArray(context) {const geometryData = this.generateGeometryData();const geometry = new Cesium.Geometry({attributes: {position: new Cesium.GeometryAttribute({componentDatatype: Cesium.ComponentDatatype.FLOAT,componentsPerAttribute: 3,values: geometryData.positions}),textureCoordinates: new Cesium.GeometryAttribute({componentDatatype: Cesium.ComponentDatatype.FLOAT,componentsPerAttribute: 2,values: geometryData.textureCoordinates})},indices: geometryData.indices,primitiveType: Cesium.PrimitiveType.TRIANGLES,boundingSphere: Cesium.BoundingSphere.fromVertices(geometryData.positions)});const geometryWithNormals = Cesium.GeometryPipeline.computeNormal(geometry);return Cesium.VertexArray.fromGeometry({context,geometry: geometryWithNormals,attributeLocations: {position: 0,textureCoordinates: 1},bufferUsage: Cesium.BufferUsage.STATIC_DRAW});}// Method to create a draw commandcreateDrawCommand(context) {const vertexArray = this.createVertexArray(context);const attributeLocations = {position: 0,textureCoordinates: 1};const shaderProgram = Cesium.ShaderProgram.fromCache({context,attributeLocations,vertexShaderSource: vs,fragmentShaderSource: fs,});const uniformMap = {color: () => Cesium.Color.GREEN,alpha: () => 1.0,moveMaxHeight: () => this.moveMaxHeight,};const renderState = Cesium.RenderState.fromCache({cull: {enabled: false,face: Cesium.CullFace.BACK},depthTest: {enabled: true}});this.drawCommand = new Cesium.DrawCommand({modelMatrix: this.modelMatrix,vertexArray,shaderProgram,renderState,uniformMap,pass: Cesium.Pass.OPAQUE});}// Update method to push the draw command into the frame stateupdate(frameState) {// Ensure the drawCommand is created if it hasn't been alreadyif (!this.drawCommand) {this.createDrawCommand(frameState.context);}// Add the draw command to the frame state for renderingframeState.commandList.push(this.drawCommand);}// Method to check if the primitive is destroyedisDestroyed() {return false;}
}