全景圖
實際上是一種廣角圖,它的原理是等距圓柱投影。說白了就是將一個球體上的全部的點,所有投影到一個圓柱體的側面上去,圓柱側面展開圖上包含了球體上全部的像素點。
哪裏能看到全景圖? 這種新穎的展示方式現在已經被各行各業所應用。不只可以實現身臨其境的效果,更能嵌入各類應用功能。
例如咱們熟知的百度地圖、高德地圖、谷歌地圖的街景模式,旅遊網站的虛擬旅行模塊,看房軟件的全景圖瀏覽等。遇到找不到的建築或者地方,打開街景模式+導航指引,能夠完美解決路癡的痛苦。
全景圖像素材的獲取有兩種方式:一是採用專門全景設備,如全景相機或者帶有魚眼鏡頭或者廣角鏡頭的相機;二是利用普通相機拍攝局部圖像,而後通過拼接造成全景圖。
如今明白了全景圖素材的獲取方式,那麼咱們要作的就是建立全景圖,怎麼辦?能夠利用
ThingJS
建立全景圖,還能夠實現全景圖與數字孿生可視化園區模型聯動、巡遊功能,實現第一人稱在數字孿生可視化場景中行走的效果。
點擊地面上的圖標,全景圖播放器中的圖片跟隨數字孿生可視化場景中小人的運動路徑改變。點擊全景圖播放器中的熱點,數字孿生可視化場景中小人跟隨熱點切換運動。
function createPlayer() {
THING.PanoManager.createPlayer(panoData, {
fullscreen: false, // 是否全屏
location: "right-center", // 懸浮框所在位置
offsetX: 0, // 相對於location的X軸偏移
offsetY: 0 // 相對於location的Y軸偏移
}, {
panoID: panoData.config.panos[0].panoID, // 初始打開的全景圖
h: 180, // 打開全景圖的初始視角h
v: 0 // 打開全景圖的初始視角v
}, null, function() {
createTourButton();
createPoints();
});
// 全景圖播放器中全景圖切換事件
app.on(THING.PanoEvent.PanoChange, function(event) {
var panoID = event.panoID; // 當前打開的全景圖ID
var panoObj = app.query("[panoID=" + panoID + "]")[0]; // 當前打開的全景圖ID
if (isPoint && panoObj) {
var panos = app.query("[panoObj=1]");
moveToNext(panoObj.position);
}
curPanoConfig = event.pano;
if (!carModel) return;
reComputePosition(curPanoConfig.position, carModel.position, carModel.angles);
});
}
3.數字孿生可視化園區模型與全景圖聯動,數字孿生可視化園區建立模型後全景圖也會加載模型,移動模型全景圖內的模型位置也對應改變。
function createModel() {
// 建立Thing
carModel = app.create({
type: 'Thing',
name: 'car',
url: modelUrl, // 模型地址
position: [-25, 0, 30],
angles: [0, 90, 0], // 旋轉
complete: function(ev) {
ev.object.style.renderOrder = 1;
// 添加到全景圖中
var pano3DObjProperties =
THING.PanoManager.compute3DObjectProperties(panoData.config.panos[0].position.position, ev.object.position, ev.object.angles);
THING.PanoManager.create3DObject("pano3DObj", modelUrl, false, pano3DObjProperties);
}
});
carModel.draggable = true; // 設置模型可拖拽
carModel.on('drag', function(ev) {
if (!ev.picked) return;
var pickPos = ev.pickedPosition; // 獲取當前拾取座標
ev.object.position = pickPos; // 設置模型位置
reComputePosition(curPanoConfig.position.position, ev.object.position, ev.object.angles);
});
}
4.根據全景圖數據在場景中建立點和路徑線,控制數字孿生可視化人物模型移動,開啓、暫停巡遊。
function createRoute() {
var line = app.query("panoLine");
if (line[0]) line[0].destroy();
var line2 = app.create({
type: 'RouteLine',
name: "panoLine",
points: points,
image: 'https://www.thingjs.com/static/images/line01.png' // 線路中的紋理資源
});
// 啓用 UV 動畫
line2.scrollUV = true;
line2.style.renderOrder = 9;
}
/**
* 建立人物模型
*/
function createPersonModel() {
peopleModel = app.create({
type: 'Thing',
url: 'https://model.3dmomoda.cn/models/0bcba8ca78734b64a3dae3eb699a913c/0/gltf/',
position: [-10.4, 0, 27.9],
complete: function() {
peopleModel.playAnimation({ name: '_defaultAnim_', loop: true });
}
});
peopleModel.rotateY(-90.0);
}
/**
* 控制人物移動
*/
function moveToNext(p) {
peopleModel.playAnimation({ name: '跑步', loop: true });
peopleModel.style.opacity = 1.0;
peopleModel.style.outlineColor = "#FF0000";
peopleModel.moveTo({
"position": p,
"time": 1500,
"orientToPath": true,
"lerp": false,
"complete": function() {
peopleModel.playAnimation({ name: '_defaultAnim_', loop: true });
}
});
}
/**
* 計算全景圖中模型位置
*/
function reComputePosition(panoPosition, modelPosition, modelAngles) {
console.log(panoPosition);
console.log(modelPosition);
var pano3DObjProperties = THING.PanoManager.compute3DObjectProperties(panoPosition, modelPosition, modelAngles);
console.log(pano3DObjProperties);
THING.PanoManager.set3DObjectProperties("pano3DObj", pano3DObjProperties);
}
})