Cesium 模型编辑 Cesium平移, 旋转 坐标轴旋转轴

轴的创建参考的 坐标轴创建 参考的这个, 感谢大哥分享

上图! 效果

1. 创建轴

  1. 父对象
export default class Axis {
     
    /**
     * 实体
     * @type {Cesium.Primitive}
     */
    primitive = null

    /**
     * 选中状态
     * @type {boolean}
     */
    selected = false

    /**
     * 轴的颜色
     * @type {Cesium.Color}
     * @private
     */
    _color = null

    /**
     * 平移
     * @param moveVector{Cesium.Cartesian3} 移动距离
     * @param unit
     * @param moveLength
     */
    translation(moveVector, unit, moveLength){
     
        Cesium.Matrix4.multiplyByTranslation(
            this.primitive.modelMatrix,
            Cesium.Cartesian3.multiplyByScalar(unit, moveLength, new Cesium.Cartesian3()),
            this.primitive.modelMatrix
        )
    }

    /**
     * 旋转轴
     * @param {Cesium.Matrix4} rotation
     */
    rotationAxis(rotation){
     
        Cesium.Matrix4.multiply(
            this.primitive.modelMatrix,
            rotation,
            this.primitive.modelMatrix,
        )
    }

    /**
     * 旋转
     * @param rotationX{Cesium.Matrix4} 旋转角度
     */
    rotation (rotationX) {
     
        this.instance = []
        if (this.primitive.geometryInstances.constructor === Array) {
     
            this.instance = this.primitive.geometryInstances
        } else {
     
            this.instance = [this.primitive.geometryInstances]
        }
        for (let i = 0; i < this.instance.length; i++) {
     
            Cesium.Matrix4.multiply(
                this.instance[i].modelMatrix,
                rotationX,
                this.instance[i].modelMatrix
            )
        }
    }

    // 复位颜色
    rest () {
     
        this.selected = false
        this.primitive.appearance.material.uniforms.color = this._color
    }

    // 选中
    select () {
     
        this.selected = true
        this.primitive.appearance.material.uniforms.color = Cesium.Color.WHITE
    }

    /**
     * 是否是当前轴
     * @param id
     * @return {boolean}
     */
    is (id) {
     
        return !!this.primitive._instanceIds.find(item => item === id)
    }
}

  1. 平移轴
import Axis from './Axis'

export default class ArrowPolyline extends Axis {
     

    /**
     * 方向
     * @type {Cesium.Cartesian3}
     */
    direction = null

    /**
     * 哪个轴
     * @type {Cartesian3}
     */
    unit = null

    /**
     * 箭头线
     */
    constructor(option = {
     }) {
     
        super()
        this._color = option.color || Cesium.Color.RED;
        this._width = option.width || 3;
        this._headWidth = option.headWidth || 2 * this._width;
        this._length = option.length || 300
        this._headLength = option.headLength || 10
        this._inverse = option.inverse || false
        this.position = option.position
        this.direction = option.direction
        this.unit = option.unit
        const id = option.id
        //这里用的是圆锥几何对象,当topRadius和bottomRadius相同时,它就是一个圆柱
        const line = Cesium.CylinderGeometry.createGeometry(new Cesium.CylinderGeometry({
     
            length: this._length,
            topRadius: this._width,
            bottomRadius: this._width
        }));
        const arrow = Cesium.CylinderGeometry.createGeometry(new Cesium.CylinderGeometry({
     
            length: this._headLength,
            topRadius: 0,
            bottomRadius: this._headWidth
        }));
        let offset = (this._length + this._headLength) / 2
        if (this._inverse) {
     
            offset = -offset
        }

        this.translate(arrow, [0, 0, offset]);
        const modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(this.position)
        this.primitive = new Cesium.Primitive({
     
            modelMatrix: modelMatrix,
            geometryInstances: [new Cesium.GeometryInstance(
                {
     
                    id: id + '-line',
                    geometry: line,
                }
            ),
            new Cesium.GeometryInstance({
     
                id: id + '-arrow',
                geometry: arrow,
            })],
            appearance: new Cesium.MaterialAppearance({
     
                material: Cesium.Material.fromType('Color', {
      color: this._color })
            }),
            asynchronous: false
        });
    }

    /**
     * 按上面的方法画出的箭头在线的中间,我们需要把它平移到线的一端
     */
    translate (geometry, offset) {
     
        const scratchOffset = new Cesium.Cartesian3();
        if (Array.isArray(offset)) {
     
            scratchOffset.x = offset[0];
            scratchOffset.y = offset[1];
            scratchOffset.z = offset[2];
        } else {
     
            Cesium.Cartesian3.clone(offset, scratchOffset);
        }

        for (let i = 0; i < geometry.attributes.position.values.length; i += 3) {
     
            geometry.attributes.position.values[i] += scratchOffset.x;
            geometry.attributes.position.values[i + 1] += scratchOffset.y;
            geometry.attributes.position.values[i + 2] += scratchOffset.z;
        }
    }
}

  1. 旋转轴
import Axis from './Axis'

export default class AxisSphere extends Axis {
     

    id = ''

    /**
     * 轴位置
     * @type {[]}
     */
    position = []

    /**
     * 方向
     * @type {Cesium.Cartesian3}
     */
    direction = null

    /**
     * 轴的角度
     * @type {number}
     */
    angle = 0

    /**
     * 构造一个旋转轴
     * @param id{string} id
     * @param radius{number} 半径
     * @param position{Cesium.Cartesian3} 位置
     * @param color{Cesium.Color} 颜色
     */
    constructor (id, radius, position, color) {
     
        super()
        this.id = id
        this._color = color
        this._calculation(radius, position)
        this._createAxisSphere(id, position, color)
    }

    /**
     * 创建圆环轴
     * @param id{string} id
     * @param matrix{Cesium.Cartesian3} 位置
     * @param color{Cesium.Color} 颜色
     * @private
     */
    _createAxisSphere(id, position, color) {
     
        const matrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
        const geometry = new Cesium.PolylineGeometry({
     
            positions: this.position,
            width: 10
        });
        const instance = new Cesium.GeometryInstance({
     
            geometry: geometry,
            id: id,
            attributes: {
     
                color: Cesium.ColorGeometryInstanceAttribute.fromColor(color)
            }
        });
        this.primitive = new Cesium.Primitive({
     
            geometryInstances: instance,
            appearance: new Cesium.PolylineColorAppearance({
     
                translucent: false
            }),
            modelMatrix: matrix
        });
    }

    /**
     * 计算轴圆弧位置
     * @param radius{number}
     */
    _calculation (radius, position) {
     
        for (let i = 0; i <= 360; i += 3) {
     
            const sin = Math.sin(Cesium.Math.toRadians(i));
            const cos = Math.cos(Cesium.Math.toRadians(i));
            const x = radius * cos;
            const y = radius * sin;
            this.position.push(new Cesium.Cartesian3(x, y, 0));
        }
    }

    /**
     * 更新轴的角度
     * @param angle
     */
    updateAngle(angle) {
     
        this.angle += angle
        if(this.angle >= 360 || this.angle <= 360) {
     
            this.angle = 0
        }
    }

    /**
     * 选中
     */
    select () {
     
        this.selected = true
    }

    // 复位颜色
    rest () {
     
        this.selected = false
    }
}

2. 功能控制

  1. 难点主要是两个, 旋转时轴怎么计算角度, 这里采用 向量向平面投影, 然后计算角度, 上代码块
export const rayPlaneIntersection = (ray, cameraDirection, pickPoint, result = new Cesium.Cartesian3()) => {
     
    if (!pickPoint) {
     
        throw new Error("cuowu")
        return
    }
    // 获取相机到左键按下时的向量长度
    const number = Cesium.Cartesian3.dot(cameraDirection, pickPoint);
    // cameraDirection 在拾取到的位置的投影
    const number1 = Cesium.Cartesian3.dot(cameraDirection, ray.origin);
    const number2 = Cesium.Cartesian3.dot(cameraDirection, ray.direction);
    const t = (number - number1) / number2
    return Cesium.Cartesian3.add(ray.origin, Cesium.Cartesian3.multiplyByScalar(ray.direction, t, result), result)
}
  1. 旋转以后, 怎么获得角度方向, 这里采用叉积, 然后计算平面法线的法向量和叉积结果的向量角度
        let cartesian3 = this.viewer.baseViewer.scene.pickPosition(e.message.startPosition)
        Cesium.Cartesian3.subtract(cartesian3, this.position, cartesian3)
        const vtStart = projectOnPlane(cartesian3, axis.direction)

        cartesian3 = this.viewer.baseViewer.scene.pickPosition(e.message.endPosition)
        Cesium.Cartesian3.subtract(cartesian3, this.position, cartesian3)
        const vtEnd = projectOnPlane(cartesian3, axis.direction)

        const cartesian = Cesium.Cartesian3.cross(vtStart, vtEnd, new Cesium.Cartesian3())

        const angle = Cesium.Math.toDegrees(Cesium.Cartesian3.angleBetween(cartesian, axis.direction))
        // 利用叉乘性质判断方向
        let rotateAngleInRadians = Cesium.Cartesian3.angleBetween(vtEnd, vtStart)
        if (angle > 1) {
     
            rotateAngleInRadians = -rotateAngleInRadians
        }

上整个控制器代码 有用的话 点个赞哦 里面的viewer 是我自己封装的对象, eventManager 你需要自己处理

import ArrowPolyline from '../model/ArrowPolyline'
import EventConstant from '../constant/EventConstant'
import {
      cartesian3ToQuaternion, normalizingQuaternion, projectOnPlane, rayPlaneIntersection } from './math'
import AxisSphere from '../model/AxisSphere'
import CesiumUtils from '../utils/CesiumUtils'

export default class TranslationController {
     

    /**
     * 视图
     * @type {Viewer}
     */
    viewer = null

    /**
     * 模型
     * @type {Cesium.Model}
     */
    model = null

    /**
     * 模型位置
     * @type {Cesium.Cartesian3}
     */
    position = null

    /**
     * z轴
     * @type {ArrowPolyline}
     */
    axisZ = null

    /**
     * x轴
     * @type {ArrowPolyline}
     */
    axisX = null

    /**
     * y轴
     * @type {ArrowPolyline}
     */
    axisY = null

    /**
     * 操作杆集合
     * @type {Cesium.PrimitiveCollection}
     */
    primitives = null

    /**
     * 从摄像头发出与视窗上一点相交的射线
     */
    pickRay = new Cesium.Ray()

    /**
     * 拾取到的位置
     * @type {Cesium.Cartesian3}
     */
    pickPoint = null

    /**
     * 当前操作轴
     * @type {ArrowPolyline}
     */
    axis = null

    /**
     * Z旋转轴
     * @type {AxisSphere}
     */
    axisSphereZ = null

    /**
     * X旋转轴
     * @type {AxisSphere}
     */
    axisSphereX = null

    /**
     * Y旋转轴
     * @type {AxisSphere}
     */
    axisSphereY = null

    /**
     * 辅助球
     * @type {Cesium.Primitive}
     */
    auxiliaryBall = null

    constructor (viewer, model) {
     
        this.viewer = viewer
        this.model = model
        this.position = Cesium.Matrix4.getTranslation(
            model.modelMatrix,
            new Cesium.Cartesian3()
        )
        this.primitives = new Cesium.PrimitiveCollection()
        this.viewer.baseViewer.scene.primitives.add(this.primitives)

        // 创建平移轴
        this._createRod()
        // 旋转平移轴
        this._rotationRod()
        // 添加平移轴
        this._addRod()

        // 创建旋转轴
        this._createSphereAxis()
        // 旋转旋转轴
        this._rotationSphereAxis()
        // 添加旋转轴
        this._addSphereAxis()
        // 添加辅助球
        this.addAuxiliaryBall(6, Cesium.Color.RED.withAlpha(0.2))

        // 添加监听器
        this._addListener()
    }

    // 添加监听器
    _addListener () {
     
        this.viewer.eventManager.addEventListener(EventConstant.LEFT_DOWN, this._clickListener)
        this.viewer.eventManager.addEventListener(EventConstant.LEFT_UP, this._clickUpListener)
        this.viewer.eventManager.addEventListener(EventConstant.MOUSE_MOVE, this._moveListener)
    }

    // 清除操纵杆, 监听器
    destroy () {
     
        this.primitives.removeAll()
        this.viewer.baseViewer.scene.primitives.remove(this.primitives)
        this._removeListener()
    }

    // 移除监听器
    _removeListener () {
     
        this.viewer.eventManager.removeEventListener(EventConstant.LEFT_DOWN, this._clickListener)
        this.viewer.eventManager.removeEventListener(EventConstant.LEFT_UP, this._clickUpListener)
        this.viewer.eventManager.removeEventListener(EventConstant.MOUSE_MOVE, this._moveListener)
    }

    // 创建操作杆
    _createRod () {
     
        const boundingShpere = this.model.boundingSphere
        const radius = boundingShpere.radius
        const options = {
     
            width: radius / 15,
            headWidth: radius / 6,
            length: radius * 5,//坐标轴的长度应该视模型的直径而定
            headLength: radius / 3,
            position: this.position
        }
        // 向上的向量
        const vectorNormalUp = new Cesium.Cartesian3()
        const vZ = new Cesium.Cartesian3(0, 0, 1)
        Cesium.Cartesian3.normalize(this.position.clone(), vectorNormalUp)

        // 向右的向量
        const vectorNormalRight = new Cesium.Cartesian3()
        // 由z轴向上 地表向上两个向量叉乘, 则可以得出, 向右的向量
        Cesium.Cartesian3.cross(vZ, vectorNormalUp, vectorNormalRight)

        // 向前的向量
        const vectorNormalFront = new Cesium.Cartesian3()
        Cesium.Cartesian3.cross(vectorNormalRight, vectorNormalUp, vectorNormalFront)
        Cesium.Cartesian3.multiplyByScalar(vectorNormalFront, -1, vectorNormalFront)

        this.axisX = new ArrowPolyline({
     
            id: 'axisX',
            color: Cesium.Color.GREEN,
            direction: vectorNormalRight,
            unit: Cesium.Cartesian3.UNIT_X,
            ...options
        })
        this.axisZ = new ArrowPolyline({
     
            id: 'axisZ',
            color: Cesium.Color.RED,
            direction: vectorNormalUp,
            unit: Cesium.Cartesian3.UNIT_Z,
            ...options
        })
        this.axisY = new ArrowPolyline({
     
            id: 'axisY',
            color: Cesium.Color.BLUE,
            direction: vectorNormalFront,
            unit: Cesium.Cartesian3.UNIT_Y,
            ...options
        })
    }

    // 添加操作杆
    _addRod () {
     
        this.primitives.add(this.axisZ.primitive)
        this.primitives.add(this.axisX.primitive)
        this.primitives.add(this.axisY.primitive)
    }

    // 初始化操作杆
    _rotationRod () {
     
        const mx = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(90))
        const rotationX = Cesium.Matrix4.fromRotationTranslation(mx)
        this.axisX.rotation(rotationX)
        const my = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(90))
        const rotationY = Cesium.Matrix4.fromRotationTranslation(my)
        this.axisY.rotation(rotationY)
    }

    // 点击监听
    _clickListener = (e) => {
     
        if (this.translationAxisIsSelected() || this.rotationAxisIsSelected()) {
     
            this.viewer.baseViewer.scene.screenSpaceCameraController.enableRotate = false
            this.pickPoint = this.viewer.baseViewer.scene.pickPosition(e.message.position)
        }
    }

    /**
     * 平移轴被选中
     * @return {boolean}
     */
    translationAxisIsSelected () {
     
        return this.axisX.selected || this.axisY.selected || this.axisZ.selected
    }

    /**
     * 旋转轴被选中
     * @return {boolean}
     */
    rotationAxisIsSelected () {
     
        return this.axisSphereZ.selected || this.axisSphereX.selected || this.axisSphereY.selected
    }

    _clickUpListener = () => {
     
        this.pickPoint = null
        this.axis = null
        this.viewer.baseViewer.scene.screenSpaceCameraController.enableRotate = true
        this.auxiliaryBall.show = false
    }
    // 移动监听
    _moveListener = (e) => {
     
        const pick = this.viewer.baseViewer.scene.pick(e.message.endPosition)
        if (!this.viewer.eventManager.press) {
     
            this._resetMaterial()
        } else if (this.axis && this.viewer.eventManager.press) {
     
            this.translationAxisIsSelected() && this._precessTranslation(e, this.axis)
            this.rotationAxisIsSelected() && this._precessRotation(e, this.axis)
            return
        }
        if (pick && pick.id) {
     
            this._resetMaterial()
            let axis = null
            if (this.axisX.is(pick.id)) {
     
                axis = this.axisX
            } else if (this.axisY.is(pick.id)) {
     
                axis = this.axisY
            } else if (this.axisZ.is(pick.id)) {
     
                axis = this.axisZ
            } else if (this.axisSphereX.is(pick.id)){
     
                axis = this.axisSphereX
            } else if (this.axisSphereY.is(pick.id)){
     
                axis = this.axisSphereY
            } else if(this.axisSphereZ.is(pick.id)) {
     
                axis = this.axisSphereZ
            }
            if (axis) {
     
                this.axis = axis
                this.axis.select()
                if(this.rotationAxisIsSelected()) {
     
                    this.auxiliaryBall.show = true
                }
            }
        }
    }

    /**
     * 处理平移
     * @param e
     * @param axis{AxisSphere}
     * @private
     */
    _precessRotation (e, axis) {
     
        this.auxiliaryBall.show = true
        if (!this.pickPoint) return

        let cartesian3 = this.viewer.baseViewer.scene.pickPosition(e.message.startPosition)
        Cesium.Cartesian3.subtract(cartesian3, this.position, cartesian3)
        const vtStart = projectOnPlane(cartesian3, axis.direction)

        cartesian3 = this.viewer.baseViewer.scene.pickPosition(e.message.endPosition)
        Cesium.Cartesian3.subtract(cartesian3, this.position, cartesian3)
        const vtEnd = projectOnPlane(cartesian3, axis.direction)

        const cartesian = Cesium.Cartesian3.cross(vtStart, vtEnd, new Cesium.Cartesian3())

        const angle = Cesium.Math.toDegrees(Cesium.Cartesian3.angleBetween(cartesian, axis.direction))
        // 利用叉乘性质判断方向
        let rotateAngleInRadians = Cesium.Cartesian3.angleBetween(vtEnd, vtStart)
        if (angle > 1) {
     
            rotateAngleInRadians = -rotateAngleInRadians
        }


        let mx = null
        if (axis.id === 'axisSphereX') {
     
            mx = Cesium.Matrix3.fromRotationX(rotateAngleInRadians)
        } else if (axis.id === 'axisSphereY') {
     
            mx = Cesium.Matrix3.fromRotationY(rotateAngleInRadians)
        }else if (axis.id === 'axisSphereZ') {
     
            mx = Cesium.Matrix3.fromRotationZ(rotateAngleInRadians)
        }
        const rotationX = Cesium.Matrix4.fromRotationTranslation(mx)
        this.rotation(rotationX, axis, rotateAngleInRadians)
    }

    /**
     *
     * @param rotationX{Cesium.Matrix4} 旋轉角度
     * @param axis{AxisSphere}
     * @param rotateAngleInRadians
     */
    rotation (rotationX, axis, rotateAngleInRadians) {
     
        this.axisSphereX.rotationAxis(rotationX)
        this.axisSphereY.rotationAxis(rotationX)
        this.axisSphereZ.rotationAxis(rotationX)
        this.axisX.rotationAxis(rotationX)
        this.axisY.rotationAxis(rotationX)
        this.axisZ.rotationAxis(rotationX)
        this.rotateVectorByAxisForAngle(this.axisX.direction, axis.direction, rotateAngleInRadians)
        this.rotateVectorByAxisForAngle(this.axisY.direction, axis.direction, rotateAngleInRadians)
        this.rotateVectorByAxisForAngle(this.axisZ.direction, axis.direction, rotateAngleInRadians)
        Cesium.Matrix4.multiply(
            this.model.modelMatrix,
            rotationX,
            this.model.modelMatrix
        )
        const number = Cesium.Math.toDegrees(rotateAngleInRadians)
        axis.updateAngle(number)
    }

    /**
     * 处理选中
     * @param e{
     {message: {startPosition: Cesium.Cartesian2, endPosition: Cesium.Cartesian2}}}
     * @param axis{ArrowPolyline}
     * @private
     */
    _precessTranslation (e, axis) {
     
        this.auxiliaryBall.show = false
        if (!this.pickPoint) return
        this.viewer.baseViewer.camera.getPickRay(e.message.startPosition, this.pickRay)
        const startPosition = rayPlaneIntersection(this.pickRay, this.viewer.baseViewer.camera.direction, this.pickPoint)
        this.viewer.baseViewer.camera.getPickRay(e.message.endPosition, this.pickRay)
        const endPosition = rayPlaneIntersection(this.pickRay, this.viewer.baseViewer.camera.direction, this.pickPoint)
        const moveVector = new Cesium.Cartesian3()
        Cesium.Cartesian3.subtract(endPosition, startPosition, moveVector)
        const moveLength = Cesium.Cartesian3.dot(axis.direction, moveVector)
        this.translation(moveVector, axis.unit, moveLength)
    }

    /**
     * 平移
     * @param moveVector
     * @param unit
     * @param moveLength
     */
    translation (moveVector, unit, moveLength) {
     
        this.axisX.translation(moveVector, unit, moveLength)
        this.axisY.translation(moveVector, unit, moveLength)
        this.axisZ.translation(moveVector, unit, moveLength)
        this.axisSphereX.translation(moveVector, unit, moveLength)
        this.axisSphereY.translation(moveVector, unit, moveLength)
        this.axisSphereZ.translation(moveVector, unit, moveLength)

        const matrix4 = this.model.modelMatrix.clone(new Cesium.Matrix4())
        Cesium.Matrix4.multiplyByTranslation(
            this.model.modelMatrix,
            Cesium.Cartesian3.multiplyByScalar(unit, moveLength, new Cesium.Cartesian3()),
            this.model.modelMatrix
        )
        Cesium.Matrix4.getTranslation(this.model.modelMatrix, this.position)

        Cesium.Matrix4.subtract(this.model.modelMatrix, matrix4, matrix4)
        const cartesian3 = Cesium.Matrix4.getTranslation(matrix4, new Cesium.Cartesian3())
        Cesium.Matrix4.multiplyByTranslation(
            this.auxiliaryBall.modelMatrix,
            cartesian3,
            this.auxiliaryBall.modelMatrix
        )
    }

    // 复位所有的材质
    _resetMaterial () {
     
        this.axisX.rest()
        this.axisY.rest()
        this.axisZ.rest()
        this.axisSphereY.rest()
        this.axisSphereZ.rest()
        this.axisSphereX.rest()
        this.auxiliaryBall.show = false
    }

    // 创建 旋转轴
    _createSphereAxis () {
     
        const radius = this.model.boundingSphere.radius * 2
        this.axisSphereZ = new AxisSphere('axisSphereZ', radius, this.position, Cesium.Color.RED)
        this.axisSphereX = new AxisSphere('axisSphereX', radius, this.position, Cesium.Color.GREEN)
        this.axisSphereY = new AxisSphere('axisSphereY', radius, this.position, Cesium.Color.BLUE)
        this.axisSphereZ.direction = this.axisZ.direction
        this.axisSphereX.direction = this.axisX.direction
        this.axisSphereY.direction = this.axisY.direction
    }

    // 旋转 旋转轴
    _rotationSphereAxis () {
     
        const mx = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(90))
        const rotationX = Cesium.Matrix4.fromRotationTranslation(mx)
        this.axisSphereX.rotation(rotationX)
        const my = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(90))
        const rotationY = Cesium.Matrix4.fromRotationTranslation(my)
        this.axisSphereY.rotation(rotationY)
    }

    // 添加旋转轴
    _addSphereAxis () {
     
        this.primitives.add(this.axisSphereZ.primitive)
        this.primitives.add(this.axisSphereY.primitive)
        this.primitives.add(this.axisSphereX.primitive)
    }

    /**
     * 添加辅助球, 用于辅助位置拾取
     * @param {number} radius
     * @param {Cesium.Color} color
     */
    addAuxiliaryBall (radius, color){
     
        const cartesian3 = CesiumUtils.extended(this.position, - radius)
        const modelMatrix = Cesium.Matrix4.multiplyByTranslation(
            Cesium.Transforms.eastNorthUpToFixedFrame(cartesian3),
            new Cesium.Cartesian3(0.0, 0.0, radius),
            new Cesium.Matrix4()
        );

        const sphereGeometry = new Cesium.SphereGeometry({
     
            vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
            radius: radius,
        });
        const sphereInstance = new Cesium.GeometryInstance({
     
            id: 'auxiliaryBall',
            geometry: sphereGeometry,
            modelMatrix: modelMatrix,
            attributes: {
     
                color: Cesium.ColorGeometryInstanceAttribute.fromColor(
                    color
                ),
            },
        });

        this.auxiliaryBall = this.primitives.add(
            new Cesium.Primitive({
     
                geometryInstances: sphereInstance,
                appearance: new Cesium.PerInstanceColorAppearance({
     
                    translucent: true,
                    closed: true,
                }),
            })
        )
        this.auxiliaryBall.show = false
    }

    /**
     * 通过轴旋转角度
     * @param vector
     * @param axis
     * @param angle
     */
    rotateVectorByAxisForAngle(vector, axis, angle){
     
        const rotateQuaternion = normalizingQuaternion(Cesium.Quaternion.fromAxisAngle(axis, angle, new Cesium.Quaternion()))
        const quaternion = cartesian3ToQuaternion(vector)
        Cesium.Quaternion.multiply(
            Cesium.Quaternion.multiply(
                rotateQuaternion,
                quaternion,
                quaternion
            ),
            Cesium.Quaternion.inverse(rotateQuaternion, new Cesium.Quaternion()),
            quaternion
        )
        vector.x = quaternion.x
        vector.y = quaternion.y
        vector.z = quaternion.z
        return quaternion
    }
}

最后几个用到的数学函数

export const projectOnPlane = (vp, vn) => {
     
    const vt = new Cesium.Cartesian3()
    const multi = new Cesium.Cartesian3()
    const divide = new Cesium.Cartesian3()
    const cartesian3 = Cesium.Cartesian3.multiplyByScalar(vn, Cesium.Cartesian3.dot(vp, vn), multi);
    Cesium.Cartesian3.divideByScalar(
        cartesian3,
        Cesium.Cartesian3.dot(vn, vn),
        divide
    )
    Cesium.Cartesian3.subtract(vp, divide, vt)
    return vt
}

export const rayPlaneIntersection = (ray, cameraDirection, pickPoint, result = new Cesium.Cartesian3()) => {
     
    if (!pickPoint) {
     
        throw new Error("cuowu")
        return
    }
    const number = Cesium.Cartesian3.dot(cameraDirection, pickPoint);
    const number1 = Cesium.Cartesian3.dot(cameraDirection, ray.origin);
    const number2 = Cesium.Cartesian3.dot(cameraDirection, ray.direction);
    const t = (number - number1) / number2
    return Cesium.Cartesian3.add(ray.origin, Cesium.Cartesian3.multiplyByScalar(ray.direction, t, result), result)
}
export const cartesian3ToQuaternion = (cartesian3) => {
     
    return new Cesium.Quaternion(
        cartesian3.x,
        cartesian3.y,
        cartesian3.z,
        0
    )
}

export const normalizingQuaternion = (quaternion) => {
     
    // Normalize( q ) = q/ |q| = q / (x*x + y*y + z*z + w*w)
    return Cesium.Quaternion.divideByScalar(
        quaternion,
        moduloQuaternion(quaternion),
        quaternion
    )
}

你可能感兴趣的:(Cesium,3d,javascript,es6)