Cesium中的3D模型Model

319 阅读3分钟

3D模型格式有两种:

gltf

基于JSON的文本文件,可使用文本编辑器轻松编辑,通常会引用外部文件,例如纹理贴图、二进制网格数据等;

一个glTF模型可包括以下三部分内容:

  • JSON格式的文件(.gltf),其中包含完整的场景描述,并通过场景结点引用网格进行定义 。包括:节点层次结构、材质(定义了3D对象的外观)、相机(定义义了渲染程序的视锥体设置 )、mesh(网格)、动画(定义了3D对象的变换操作,比如选择、平移操作)、蒙皮(定义了3D对象如何进行骨骼变换)等;
  • .bin包含几何和动画数据以及其他基于缓冲区的数据的二进制文件;
  • 图像文件(.jpg,.png)的纹理。

glb

二进制格式,通常文件较小且自包含所有资源,但不容易编辑。

entity加载模型

var position = Cesium.Cartesian3.fromDegrees(-120.05, 44, 0);
var heading = Cesium.Math.toRadians(45);
var pitch = 0;
var roll = 0;
var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
var orientation = Cesium.Transforms.headingPitchRollQuaternion(
    position,
    hpr
);
var model_entity = viewer.entities.add({
    name: "gltf模型",
    position: position,
    // 默认情况下,模型是直立的并面向东。
    // 通过 Quaternion 为 Entity.orientation 属性指定值来控制模型的方向,控制模型的航向,俯仰和横滚。
    orientation: orientation,
    model: {
        show: true,
        uri: "./data/models/DracoCompressed/CesiumMilkTruck.gltf",
        scale: 1.0, // 缩放比例
        minimumPixelSize: 128, // 最小像素大小
        maximumScale: 20000, // 模型的最大比例尺大小。 minimumPixelSize的上限
        incrementallyLoadTextures: true, // 加载模型后纹理是否可以继续流入
        runAnimations: true, // 是否应启动模型中指定的glTF动画
        clampAnimations: true, // 指定glTF动画是否应在没有关键帧的持续时间内保持最后一个姿势

        // 指定模型是否投射或接收来自光源的阴影 type:ShadowMode
        // DISABLED 对象不投射或接收阴影;ENABLED 对象投射并接收阴影;CAST_ONLY  对象仅投射阴影;RECEIVE_ONLY  对象仅接收阴影
        shadows: Cesium.ShadowMode.ENABLED,
        heightReference: Cesium.HeightReference.NONE,
    },
});
// viewer.trackedEntity = entity; // 相机保持在实体上

primitive加载模型

var origin = Cesium.Cartesian3.fromDegrees(-120, 44.0, 0);
// 创建一个本地的东北向上坐标系,其原点为经度-120度,纬度44.0度。
// 可以随时更改模型的modelMatrix属性以移动或旋转模型。
var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);
var model = viewer.scene.primitives.add(
    Cesium.Model.fromGltf({
        url: "./data/models/DracoCompressed/CesiumMilkTruck.gltf",
        modelMatrix: modelMatrix,
        minimumPixelSize: 128,
        maximumScale: 20000,
    })
);
model.readyPromise.then(function (model) {
    // Play all animations when the model is ready to render
    model.activeAnimations.addAll();
});

primitive

primitive主要由两部分组成:Geometry【几何体】和Appearance【着色器】

for (let lon = -180.0; lon < 180.0; lon += 5.0) {
    for (let lat = -85.0; lat < 85.0; lat += 5.0) {
        instances.push(
            new Cesium.GeometryInstance({
                geometry: new Cesium.RectangleGeometry({
                    rectangle: Cesium.Rectangle.fromDegrees(
                        lon,
                        lat,
                        lon + 5.0,
                        lat + 5.0
                    ),
                    vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
                }),
                attributes: {
                    color: Cesium.ColorGeometryInstanceAttribute.fromColor(
                        Cesium.Color.fromRandom({ alpha: 0.5 })
                    ),
                },
            })
        );
    }
}

this.viewer.scene.primitives.add(
    new Cesium.Primitive({
        geometryInstances: instances,
        appearance: new Cesium.PerInstanceColorAppearance({
            translucent: false,
            closed: true,
        }),
    })
);

entity与primitive区别

  1. entity偏向数据,primitive偏向图形
  2. entity用法简单,primitive用法复杂
  3. primitive更底层,加载效率高 我们会有这样的疑问:entity已经封装的如此完美,调用如此便捷,为何还要primitive接口呢?区别就是加载效率。primitive更接近webgl底层,没有entity各种各样的附加属性,因此在加载时效率会更高。