全景图 其实是一种广角图,它的原理是等距圆柱投影。说白了就是将一个球体上的所有的点,全副投影到一个圆柱体的侧面下来,圆柱侧面开展图上蕴含了球体上所有的像素点。
哪里能看到全景图? 这种新鲜的展示形式现在曾经被各行各业所利用。不仅可能实现身临其境的成果,更能嵌入各种利用性能。
例如咱们熟知的百度地图、高德地图、谷歌地图的街景模式,游览网站的虚构旅行模块,看房软件的全景图浏览等。遇到找不到的修建或者中央,关上街景模式 + 导航指引,能够完满解决路痴的苦楚。
全景图像素材的获取有两种形式:一是采纳专门全景设施,如全景相机或者带有鱼眼镜头或者广角镜头的相机;二是利用一般相机拍摄部分图像,而后通过拼接造成全景图。
当初明确了全景图素材的获取形式,那么咱们要做的就是创立全景图,怎么办?能够利用 ThingJS 创立全景图,还能够实现全景图与数字孪生可视化园区模型联动、巡游性能,实现第一人称在数字孪生可视化场景中行走的成果。
点击高空上的图标,全景图播放器中的图片追随数字孪生可视化场景中君子的静止门路扭转。点击全景图播放器中的热点,数字孪生可视化场景中君子追随热点切换静止。
1. 加载全景图插件,设置全景图数据。
2. 创立全景图播放器,设置初始视角。
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);
}
})
运行后果: