CESIUM例子学习(十二)——3D Tiles Styling

3D Tiles Styling,这应该是一个使用率最高的例子了吧,因为觉得它的使用场景实现是太多了。它是可以根据Cesium3DTileFeature属性来进行个性化渲染的功能,比如分级渲染,距离渲染、条件显示。这些功能的实现都很简单,根据项目需要,创建一个相应的Cesium3DTileStyle属性,并赋值给Cesium3DTileset即可完成。但前提条件是,你的3D Tiles的属性字段中得有需要字段与值。如何判断是否有相应字段的方法是,在加载完成3dtiles之后,绑定一个点击事件,利用getProperty方法,查看是否有。代码如下:

function addListener () {
    let scene = viewer.scene
    var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    handler.setInputAction(function (click) {
        // setColor()
        var pickedFeature = viewer.scene.pick(click.position)
        console.log("pickedFeature=", pickedFeature)
        if (pickedFeature) {
            // selectFeature(pickedFeature)
            getAllProperty(pickedFeature)
        }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
function getAllProperty (feature) {
    var propertyNames = feature.getPropertyNames()
    var length = propertyNames.length
    for (var i = 0; i < length; ++i) {
        var propertyName = propertyNames[i]
        console.log(propertyName + ': ' + feature.getProperty(propertyName))
    }
}

然后就可以在控制台查看属性了,如下图:

我只是测试练习,所以渲染效果就根据这些字段来。需要注意的是代码中属性字段的名称是严格区分大小写的

一、分级渲染

测试中的分级渲染是根据建筑的高度,渲染成不同的颜色。代码如下:

var tileset
function add3dtiles (url) {
    tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
        url: url
    }))
    tileset.readyPromise.then((tileset) => {
       //后面相应的效果代码都是放这里。
         setColorByHeight()
        viewer.flyTo(tileset)
    })
}
function setColorByHeight () {
    tileset.style = new Cesium.Cesium3DTileStyle({
        color: {
            conditions: [
                ["${height} >= 300", "rgba(45, 0, 75, 0.5)"],
                ["${height} >= 200", "rgb(102, 71, 151)"],
                ["${height} >= 100", "rgb(170, 162, 204)"],
                ["${height} >= 50", "rgb(224, 226, 238)"],
                ["${height} >= 25", "rgb(252, 230, 200)"],
                ["${height} >= 10", "rgb(248, 176, 87)"],
                ["${height} >= 5", "rgb(198, 106, 11)"],
                ["true", "rgb(127, 59, 8)"],
            ],
        },
    });
}

还没有能力去看原码,但setColorByHeight函数中创建分级渲染的方法很清楚,"${height}就是获取Cesium3DTileFeature中height属性的值,如果该直大于等300,则赋值该Cesium3DTileFeature颜色为rgba(45, 0, 75,0.5)。其中rgba应该是GLSL中创建颜色的函数。最后一个是["true", "rgb(127, 59, 8)"],表达的意思是上面都设置完了,剩下的都用rgb(127, 59, 8)这个颜色。实现的效果如下图:

二、按距离渲染

按距离渲染是指,Cesium3DTileFeature离某个点距离当作渲染条件进行的渲染。代码如下:

function colorByDistance () {
    tileset.style = new Cesium.Cesium3DTileStyle({
        defines: {
            distance:
                "distance(vec2(${longitude},${latitude}), vec2(-1.291777521, 0.7105706624))",
        },
        color: {
            conditions: [
                ["${distance} > 0.0012", "color('red')"],
                [
                    "${distance} > 0.0008",
                    "mix(color('yellow'), color('red'), (${distance} - 0.008) / 0.0004)",
                ],
                [
                    "${distance} > 0.0004",
                    "mix(color('green'), color('yellow'), (${distance} - 0.0004) / 0.0004)",
                ],
                ["${distance} < 0.00001", "color('white')"],
                [
                    "true",
                    "mix(color('blue'), color('green'), ${distance} / 0.0004)",
                ],
            ],
        },
    });
}

创建Cesium3DTileStyle的代码中可以看到,分成两部份。defines和color,从实现的效果来看,其实就是在defines中定义了一个叫distance的字段,但是字段的值是由其实它字段参与计算来的。计算的表达式是:

 "distance(vec2(${longitude},${latitude}), vec2(-1.291777521, 0.7105706624))"

意思应该是:它调用了一个GLSL的内置函数distance,用原有属性的经纬度来计算它离vec2(-1.291777521, 0.7105706624)这个点的距离,distance的值,值得注意的是:vec2(-1.291777521, 0.7105706624)是弧度,而实例原码是:

 "distance(vec2(radians(${Longitude}), radians(${Latitude})), vec2(-1.291777521, 0.7105706624))"

即调用了GLSL的radians函数,把经纬度转成弧度,但是我的属性数据本来就是弧度,所以不需要再转换

。而在color的计算中,上面定义的distance就与原有的属性一样使用,其中mix是GLSL的内置函数。实现的效果如下图:

三、按条件显示

按条件显示是设置Cesium3DTileStyle可选属性show的显示条件即可,代码如下:

function hideByHeight () {
    tileset.style = new Cesium.Cesium3DTileStyle({
        show: "${height} > 200",
    });
}

代码的意思是只显示height属性大于200的Cesium3DTileFeature进行渲染。

四、点击交互

测试是点击某个Cesium3DTileFeature时,改变Cesium3DTileFeature的颜色。代码如下:

function addListener () {
    var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    handler.setInputAction(function (click) {
        // setColor()
        var pickedFeature = viewer.scene.pick(click.position)
        console.log("pickedFeature=", pickedFeature)
        if (pickedFeature) {
            // selectFeature(pickedFeature)
            // getAllProperty(pickedFeature)
        }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
function selectFeature (feature) {
    var selectbuilding = feature.getProperty('id');
    var s = "${id} ===" + selectbuilding
    console.log("s=", s)
    var selectcontent = s;
    var transparentStyle = new Cesium.Cesium3DTileStyle({
        color: {
            conditions: [
                [selectcontent, "rgb(255,255,0)"],
                ["${height} >= 300", "rgba(45, 0, 75, 0.5)"],
                ["${height} >= 200", "rgb(102, 71, 151)"],
                ["${height} >= 100", "rgb(170, 162, 204)"],
                ["${height} >= 50", "rgb(224, 226, 238)"],
                ["${height} >= 25", "rgb(252, 230, 200)"],
                ["${height} >= 10", "rgb(248, 176, 87)"],
                ["${height} >= 5", "rgb(198, 106, 11)"],
                ["true", "rgb(127, 59, 8)"],true表示剩余的显示的对象
            ]
        },
    });
    tileset.style = transparentStyle
}

实现效果如下图:

好的,针对你的问题,我可以给你一些指导。首先,你需要明确加载3D Tiles的目的是什么。如果你只需要显示一个小范围的地理区域,那么局部加载就是一个非常好的选择,它可以帮助你提高应用程序的性能。 在Cesium中,你可以使用Tileset类加载3D TilesTileset类提供了一些方法,能够帮助你控制加载和显示3D Tiles的细节。下面是一个示例代码,演示如何加载并调整3D Tiles: ```javascript var viewer = new Cesium.Viewer('cesiumContainer'); var tileset = new Cesium.Cesium3DTileset({ url : 'path/to/your/tileset' }); viewer.scene.primitives.add(tileset); // 通过设置Tileset的transform属性,调整3D Tiles的位置和方向 tileset.readyPromise.then(function(tileset) { var boundingSphere = tileset.boundingSphere; var cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center); var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0); var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 10.0); var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3()); tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation); }); // 通过设置Tileset的maximumScreenSpaceError属性,控制3D Tiles的细节级别 tileset.maximumScreenSpaceError = 8; ``` 在这个示例中,我们首先创建了一个Cesium的Viewer实例,并将其作为容器显示在HTML页面中。然后,我们创建了一个Tileset实例,并将其添加到场景中。接下来,我们设置了Tileset的transform属性,将3D Tiles调整到我们想要的位置和方向。最后,我们设置了Tileset的maximumScreenSpaceError属性,控制3D Tiles的细节级别。 希望这个示例能够帮助你加载并调整3D Tiles。如果你还有其他的问题,请随时问我。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值