Cesium 之实现房屋模型拆解
生活随笔
收集整理的這篇文章主要介紹了
Cesium 之实现房屋模型拆解
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
本文按照mars3d提供的在線例子,自己實現(xiàn)了類似功能。
模型的拆解其實是將模型組裝的各個部分模塊以延遲動畫方式進行位置重置,從而能夠單獨瀏覽,更直觀的看到內(nèi)部結(jié)構(gòu)。
實現(xiàn)思路很簡單
1、模型的加載
使用primitives 加載模型
2、通過modelMatrix控制位置
直接上代碼,可根據(jù)實際需求自行擴展。
JS
/** @Descripttion: * @version: * @Author: xiongz* @Date: 2022-05-12 11:31:46* @LastEditors: Please set LastEditors* @LastEditTime: 2022-05-12 19:37:04*/ /// // 模塊描述:房屋模型移動拆分 /// define(["dojo/_base/declare","dojo/_base/lang",'dojo/_base/html',"dojo/_base/fx",'jimu/BaseWidget', ], function (declare,lang,html,fx,BaseWidget ) {return declare("jimu.widget.ModelSplit", [BaseWidget], {baseClass: "jimu-widget-ModelSplit",name: 'ModelSplit',models: [],point: null,timers: [],floorCount: 6,floorScale: 1,floorHeight: 3, // 不縮放情況下樓層高度point: {lng: 115.91455928461914,lat: 28.665192693562243,height: 0},postCreate: function () {this.inherited(arguments);},destroy: function () {this.inherited(arguments);},startup: function () {this.inherited(arguments);topic.subscribe("runMap3DWidget", lang.hitch(this, function (name) {if (name == this.name) {this.initModel();$(`.${this.baseClass}`).show()}}));topic.subscribe("clearMap3DWidget", lang.hitch(this, function(name){if(name!=this.name){this.clearAll()}}));let that = this;$('.floorWhole >button').on('click', function () {let index = $(this).index();// 全部展開if (index == 0) {that.opeAll(4, 3000, 100)}// 全部合并else if (index == 1) {that.unionAll(4, 3000, 100)}// 全部還原else if (index == 2) {that.resetAll()}})$('.floorSingle >button').on('click', function () {let index = $(this).index();let maxHeight = that.point.height + (that.floorCount + 1) * that.floorScale// 樓層查看that.openFloorModel(maxHeight, index + 1)})$('.modelfile-th .xx').on('click',function(){that.clearAll();})},initModel:function(){let model = null;let floorCount = this.floorCount; // 房屋總樓層數(shù),不含樓頂let floorScale = this.floorScale; // 房屋縮放比例,默認一般1let floorHeight = this.floorHeight; // 每層的高度let point = this.point;for (let i = 0; i <= floorCount; i++) {if (i < floorCount) {// 底樓let height = point.height + i * floorHeight * floorScale;model = this.addModePrimitive({position: [point.lng, point.lat, height],url: './widgets/ModelSplit/data/floor.glb',name: 'fw',scale: floorScale})model.option = {oriHeight: height,scale: floorScale,currentHeight:height}this.models.push(model)} else {// 頂樓let height = point.height + i * floorHeight * floorScale;model = this.addModePrimitive({position: [point.lng, point.lat, height],url: './widgets/ModelSplit/data/top.glb',name: 'fw',scale: floorScale})model.option = {oriHeight: height,scale: floorScale,currentHeight:height}this.models.push(model)}}window.viewer.camera.flyTo({destination : Cesium.Cartesian3.fromDegrees(115.91326536913103, 28.66495725572756, 55.24826616710503,),orientation : {heading : Cesium.Math.toRadians(78.06653423571397),pitch : Cesium.Math.toRadians(-15.156766587402164),roll : 0}});},clearAll:function(){if(this.models.length>0){this.models.forEach(m=>{window.viewer.scene.primitives.remove(m)})}$('.jimu-widget-ModelSplit').hide()},opeAll: function (height, time = 4000, interval = 100) {this.resetAll();let point = this.point; //樓棟位置this.clearFloorTimers()for (let i = 0; i < this.models.length; i++) {let model = this.models[i]let changeRate = Number((i * height * model.option.scale)) * (interval / time)// let alt = i * height * model.option.scale + model.option.oriHeight;if (i != 0) {// model.position = new Cesium.CallbackProperty(function () {// let height = model.option.oriHeight + (i * height * model.option.scale) / time// if (height < alt) {// return Cesium.Cartesian3(model.position[0], model.position[1], height)// } else {// return Cesium.Cartesian3(model.position[0], model.position[1], alt)// }// }, false)let count = 1;let timer = setInterval(function () {let add = model.option.oriHeight + changeRate * (count++)var origin = Cesium.Cartesian3.fromDegrees(point.lng, point.lat, add);var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);model.modelMatrix = modelMatrix;if (count >= (time / interval)) {model.option.currentHeight=add;clearInterval(timer)timer = null;}// console.log(count)}, interval)this.timers.push(timer)}}},unionAll: function (height, time = 4000, interval = 100) {let point = this.point; //樓棟位置this.clearFloorTimers()for (let i = 0; i < this.models.length; i++) {let model = this.models[i];// 如果是初始位置,代表已經(jīng)為合并狀態(tài)。if(model.option.currentHeight==model.option.oriHeight){continue;}let currentHeight = model.option.oriHeight + (i * height * model.option.scale);let changeRate = Number((i * height * model.option.scale)) * (interval / time)model.show = true;let count = 1;let timer = setInterval(function () {let add = currentHeight - changeRate * (count++)var origin = Cesium.Cartesian3.fromDegrees(point.lng, point.lat, add);var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);model.modelMatrix = modelMatrix;if (count >= (time / interval)) {var origin = Cesium.Cartesian3.fromDegrees(point.lng, point.lat, model.option.oriHeight);var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);model.modelMatrix = modelMatrix;model.option.currentHeight=model.option.oriHeightclearInterval(timer)}}, interval)this.timers.push(timer)}},resetAll: function () {this.clearFloorTimers()let point = this.point; //樓棟位置for (let i = 0; i < this.models.length; i++) {let model = this.models[i];var origin = Cesium.Cartesian3.fromDegrees(point.lng, point.lat, model.option.oriHeight);var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);model.option.currentHeight=model.option.oriHeightmodel.modelMatrix = modelMatrix;model.show = true;}},/*** 顯示指定樓層** @param {Number} maxHeight 指定從頂部落下的高度* @param {Number} floorNum 指定顯示的樓層,第1層開始* @param {Number} [time=1000] 樓層下落需要時間,單位:毫秒* @param {Number} [interval=100] 樓層下落觸發(fā)間隔時間,單位:毫秒* @return {void} 無*/openFloorModel: function (maxHeight = 120, floorNum, time = 1000, interval = 100) {this.clearFloorTimers();floorNum--;let point = this.point; //樓棟位置for (let i = floorNum; i < this.models.length; i++) {let model = this.models[i];var origin = Cesium.Cartesian3.fromDegrees(point.lng, point.lat, model.option.oriHeight + maxHeight);var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);model.modelMatrix = modelMatrix;model.show = false;model.option.currentHeight=model.option.oriHeight + maxHeight}for (let j = 0; j <= floorNum; j++) {let model = this.models[j];// 如果是初始位置,代表已經(jīng)為合并狀態(tài)。model.show = true;if(model.option.currentHeight==model.option.oriHeight&&j!=floorNum){continue;}let currentHeight = model.option.oriHeight + maxHeight;let changeRate = maxHeight * (interval / time)let count = 1;let timer = setInterval(function () {let add = currentHeight - changeRate * (count++)var origin = Cesium.Cartesian3.fromDegrees(point.lng, point.lat, add);var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);model.modelMatrix = modelMatrix;if (count >= (time / interval)) {var origin = Cesium.Cartesian3.fromDegrees(point.lng, point.lat, model.option.oriHeight);var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);model.modelMatrix = modelMatrix;model.option.currentHeight=model.option.oriHeightclearInterval(timer)}}, interval)this.timers.push(timer)}},clearFloorTimers: function () {if (this.timers.length > 0) {this.timers.forEach(t => {if (t) {clearInterval(t)}})}this.timers = [];},// 3d模型addModePrimitive: function (option) {var origin = Cesium.Cartesian3.fromDegrees(option.position[0], option.position[1], option.position[2]);var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);var modelPrimitive = null;modelPrimitive = window.viewer.scene.primitives.add(Cesium.Model.fromGltf({url: option.url,modelMatrix: modelMatrix,show: true, // defaultscale: option.scale || 1, // double size// minimumPixelSize : 128, // never smaller than 128 pixelsmaximumScale: 20000, // never larger than 20000 * model size (overrides minimumPixelSize)allowPicking: true,// heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,scene: viewer.scene}));modelPrimitive.name = option.name;modelPrimitive.type = "model"if (option.rotationz) {var mz = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(option.rotationz));var rotationz = Cesium.Matrix4.fromRotationTranslation(mz);//旋轉(zhuǎn)、平移矩陣相乘Cesium.Matrix4.multiply(modelMatrix, rotationz, modelMatrix);modelPrimitive.modelMatrix = modelMatrix}modelPrimitive.readyPromise.then(function (model) {// Play all animations when the model is ready to rendermodel.activeAnimations.addAll({speedup: 0.5,loop: Cesium.ModelAnimationLoop.REPEAT});});return modelPrimitive;}}); });html
<div><div class="model-Split"><div class="modelfile-th"><!--<i class="i"></i>--><span class="tsls">房屋拆解</span><span class="xx"><i class="layui-icon">ဆ</i></span></div><div class="modelfile-td"><div class="infoview"><div class="floorWhole">整體控制:<button class="btn btn-primary">展開</button><button class="btn btn-primary">合并</button><button class="btn btn-primary">還原</button></div><div class="floorSingle">顯示指定:<button class="btn btn-primary">一樓</button><button class="btn btn-primary">二樓</button><button class="btn btn-primary">三樓</button><button class="btn btn-primary">四樓</button><button class="btn btn-primary">五樓</button><button class="btn btn-primary">六樓</button><button class="btn btn-primary">頂樓</button></div></div></div></div> </div>結(jié)果展示:
?
https://live.csdn.net/v/210549
總結(jié)
以上是生活随笔為你收集整理的Cesium 之实现房屋模型拆解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Cisco Packet Tracer思
- 下一篇: 如何解决BIOS自动更新,不断循环更新,