cesium(笔记-5)

运行环境 | cesium 1.58 | webstorm 2018.2.2 | windows 10 pro

记初步实现 cesium 通过鼠标完成模型创建

通过鼠标滑动实时抓取当前坐标与高度,动态刷新到左侧二维缩略图信息框中,用户可通过手动输入或鼠标实时获取坐标点,点击确认添加后,在指定坐标点生成对应模型

案例模型采用3D Tiles 及 GLTF
3D Tiles官方介绍
GLTF 官方介绍

3D Tiles介绍:

3D Tiles 是:

  • Open(开放)
  • Optimized for streaming and rendering(针对流和渲染进行了优化)
  • Designed for 3D(专为3D设计)
  • Interactive(交互式互动)
  • Styleable(设置样式)
  • Adaptable(适应性强)
  • Flexible(灵活)
  • Heterogeneous(异构的
  • Precise(精确)
  • Temporal(时间动态

渲染

3D Tiles是基于状态,从UNLOADING开始,通过一系列的request,完成最初的数据加载过程,结束LOADING状态,进入Pocessing过程,也就是数据解析。数据解析完后进入READY状态,通过selectTile,最终调用Content对应的update方法,构造最终的drawcommand,加入渲染队列。当然,如果有需要释放的Tile,则在unloadTiles中处理。细心的人会发现Pocessing和Ready状态。最终调用的都是update方法。这里解释一下:3D Tiles中主要的数据部分就是glTF,而glTF也是基于状态管理的,无论是glTF的解析还是构造DrawCommand,只是state不同,都是在update方法中完成的。

GLTF介绍:

gltf的核心是一个JSON文件。这个文件描述了3D场景的全部内容。它由场景结构本身的描述组成,由定义场景图的节点层次结构给出。场景中出现的三维对象是使用附着到节点上的网格定义的。材质定义对象的外观。动画描述了随着时间的推移,三维对象是如何转换的(例如,旋转到转换),而蒙皮定义了基于骨架姿势的对象几何体是如何变形的。摄影机描述渲染器的视图配置。

基础结构

  • scene:整个场景的入口点,由node构成图(树)结构(类似OSG的场景组织)组成
  • node:场景层级中的一个节点,可以包含位置变换,可以有子节点。同时,node通过指向mesh、camera、skin来描述node的形变
  • camera:定义渲染场景的视点配置
  • mesh:描述了在场景中出现的几何物体,并通过accessor(访问器)来访问其真实的几何数据,通过material(材质)来确定渲染外观
  • skin:蒙皮描述模型绑定到骨骼上的参数,用来实现骨骼动画,其真实数据也是通过访问器来获取的
  • animation:骨骼动画,描述某个节点怎么随着时间运动
  • accessor:访问器,定义了如何从二进制数据源中获取数据,在mesh、animation、skin中都会用到访问器。其指向buffer和bufferview,在这里面存着真正的几何数据
  • material:材质包含了定义物体模型外观的参数,特别是纹理参数
  • texture:包括采样器和图片,定义如何将纹理映射到模型

对外部数据的引用

二进制数据,如三维对象的几何图形和纹理,通常不包含在JSON文件中。相反,它们存储在专用文件中,JSON部分只包含指向这些文件的链接。这允许二进制数据以非常紧凑的形式存储,并且可以通过Web高效地传输。此外,数据可以直接存储在渲染器中,而不必解析、解码或预处理数据。

实现思路

需要获取坐标点与高度

  • 屏幕坐标

    1
    2
    3
    4
    var handler= new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    handler.setInputAction(function (movement) {
    console.log(movement.position);
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
  • 世界坐标

    1
    2
    3
    4
    5
    var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    handler.setInputAction(function (movement) {
    var position = viewer.scene.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);
    console.log(position);
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
  • 场景坐标

    1
    2
    3
    4
    5
    var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    handler.setInputAction(function (movement) {
    var position = viewer.scene.pickPosition(movement.position);
    console.log(position);
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
  • 地标坐标

    1
    2
    3
    4
    5
    6
    var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    handler.setInputAction(function (movement) {
    var ray=viewer.camera.getPickRay(movement.position);
    var position = viewer.scene.globe.pick(ray, viewer.scene);
    console.log(position);
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

加载模型

1
2
3
4
5
6
7
8
9
var entity = viewer.entities.add({
name: 'model/CesiumMilkTruck/CesiumMilkTruck.glb',
position: position,
orientation: orientation,
model: {
uri: 'model/CesiumMilkTruck/CesiumMilkTruck.glb',
}
});
viewer.trackedEntity = entity;

完整代码实现

JS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
  var viewer = new Cesium.Viewer('cesiumContainer', {
imageryProvider: Cesium.createOpenStreetMapImageryProvider({
url: 'https://a.tile.openstreetmap.org/'
}),
shouldAnimate: false,
infoBox: false,
selectionIndicator: false,
shadows: false,
geocoder: false,
homeButton: false,
sceneModePicker: false,
baseLayerPicker: false,
navigationHelpButton: false,
// animation: false,
// timeline: false,
fullscreenButton: false
});

var scene = viewer.scene;
//
var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
handler.setInputAction(function (movement) {
var cartesian = scene.camera.pickEllipsoid(movement.endPosition, ellipsoid);
var ellipsoid = scene.globe.ellipsoid;
if (cartesian) {
var cartographic = ellipsoid.cartesianToCartographic(cartesian);
var coords = 'lng' + Cesium.Math.toDegrees(cartographic.longitude).toFixed(6) + ', ' + 'lat' + Cesium.Math.toDegrees(cartographic.latitude).toFixed(6) + ',' + 'hig' + Math.ceil(viewer.camera.positionCartographic.height);
console.log("-->" + coords)
$("#val1").val(Cesium.Math.toDegrees(cartographic.longitude).toFixed(6))
$("#val2").val(Cesium.Math.toDegrees(cartographic.latitude).toFixed(6))
$("#val3").val(Math.ceil(viewer.camera.positionCartographic.height))

} else { //
console.log("-->" + ERROR)
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

var params = {
tx: $("#val1").val(),  //模型中心X轴坐标(经度,单位:十进制度)   
ty: $("#val2").val(),    //模型中心Y轴坐标(纬度,单位:十进制度)   
tz: 0,    //模型中心Z轴坐标(高程,单位:米)   
rx: 0,    //X轴(经度)方向旋转角度(单位:度)   
ry: 0,    //Y轴(纬度)方向旋转角度(单位:度)   
rz: 0      //Z轴(高程)方向旋转角度(单位:度)
};

function createModel() {

console.log("------>" + $("#height").val());
//
// viewer.entities.removeAll();

var position = Cesium.Cartesian3.fromDegrees($("#val1").val(), $("#val2").val(), $("#val3").val());
var heading = Cesium.Math.toRadians(135);
var pitch = 0;
var roll = 0;
var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
var orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr);

var entity = viewer.entities.add({
name: 'model/CesiumMilkTruck/CesiumMilkTruck.glb',
position: position,
orientation: orientation,
model: {
uri: 'model/CesiumMilkTruck/CesiumMilkTruck.glb',
}
});
viewer.trackedEntity = entity;


// 3D Tiles

/*viewer.scene.globe.depthTestAgainstTerrain = true;
// var url = "model/daodan/tileset.json";
var url = Cesium.IonResource.fromAssetId(1);
var tileset = new Cesium.Cesium3DTileset({url: url});

var primitive1 = viewer.scene.primitives.add(tileset);

primitive1.readyPromise.then(function (t) {
console.log("====>"+$("#val1").val() + ","+$("#val2").val())
var originalSphere = t.boundingSphere;
var radius = originalSphere.radius;
viewer.zoomTo(t, new Cesium.HeadingPitchRange(0.5, -0.5, radius * 4.0));
//
var mx = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(params.rx));
var my = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(params.ry));
var mz = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(params.rz));
var rotationX = Cesium.Matrix4.fromRotationTranslation(mx);
var rotationY = Cesium.Matrix4.fromRotationTranslation(my);
var rotationZ = Cesium.Matrix4.fromRotationTranslation(mz);
// var position = Cesium.Cartesian3.fromDegrees(params.tx, params.ty, $("#val3").val());
var position = Cesium.Cartesian3.fromDegrees($("#val1").val(), $("#val2").val(), $("#val3").val());

var m = Cesium.Transforms.eastNorthUpToFixedFrame(position);
//
Cesium.Matrix4.multiply(m, rotationX, m);
Cesium.Matrix4.multiply(m, rotationY, m);
Cesium.Matrix4.multiply(m, rotationZ, m);
tileset._root.transform = m;

}).otherwise(function (error) {

var msg = JSON.stringify(error);

console.log("msg ------------->" + msg);
});*/
}

HTML 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
	<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<link href="css/widgets.css" rel="stylesheet"/>
<title>add model</title>

<script src="https://cdn.bootcss.com/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="css/style.css"/>
<link rel="stylesheet" href="bootstrap/css/bootstrap.css"/>
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript" src="bootstrap/js/bootstrap.js"></script>
<script type="text/javascript" src="js/Sandcastle-header.js"></script>
<script type="text/javascript" src="js/require.js"></script>
<script type="text/javascript" src="js/Cesium.js"></script>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>

html, body, #cesiumContainer {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<style>
@import url(css/bucket.css);

#toolbar {
background: rgba(42, 42, 42, 0.8);
padding: 4px;
border-radius: 4px;
}

#toolbar input {
vertical-align: middle;
padding-top: 2px;
padding-bottom: 2px;
}
</style>

<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar">
<!--<div>Height</div>-->
<!--<input type="range" min="-100.0" max="100.0" step="1" data-bind="value: height, valueUpdate: 'input'">-->
<!--<input type="text" size="5" data-bind="value: height">-->
<!--<input value="0" id="height" type="text">-->
<!--<button onclick="createModel()">添加</button>-->


<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body">
<div>
<img src="img/car.jpg" style="height: 100px">
</div>
<hr/>
<!-- Single button -->
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false">
参数 <span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a href="#">经度<input id="val1" type="text" style="color: #000000"/></a></li>
<li><a href="#">纬度<input id="val2" type="text" style="color: #000000"/></a></li>
<li><a href="#">高度<input id="val3" type="text" style="color: #000000"/></a></li>
</ul>
</div>
</div>
</div>
<button onclick="createModel()"><a>确认添加</a></button>

</div>

</body>
</html>

效果图


本文结束感谢您的阅读,本文原创–支持原创
顺便打点赏吧~ 有问题请联系我--strivedeer@163.com