基于 WebGL(ThingJS)的室内平面图 2D/3D 导航 DEMO(Part 1)...

2023-11-03 19:51

本文主要是介绍基于 WebGL(ThingJS)的室内平面图 2D/3D 导航 DEMO(Part 1)...,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


前言

利用CampusBuilder来搭建自己的虚拟世界过程有这样一个问题:如何快速聚焦到虚拟场景的某一位置。当然我们可以创建几个按钮对应查找我们需要去的位置(参照物)并聚焦,但是按钮并不是很炫酷也不能很好的反馈给我们一些信息。接下来我们就用平面导航图来解决这一问题。


实现

第一步,使用CampusBuilder搭建模拟场景,CampusBuilder操作简单,分分钟就可以上手。这里为每一个房间都创建一个小球作为视点参照物体并勾选预览时隐藏,这样不会对我们的场景造成影响,也便于我们聚焦到指定房间。注意:要将我们每个房间中的设备框选之后组合在一起,为下一阶段的做准备。


 


第二步,把我们编辑好的场景加载到ThingJS中。


//加载场景代码
var app = new THING.App({// 场景地址"url": "http://www.thingjs.com/./uploads/wechat/S2Vyd2lu/scene/Campus04",
});
//场景相关
//************************************************************************************/
app.on('load', function () {app.camera.flyTo({'position': [36.357131498969785, 61.953024217074265, 69.12160670337104],'target': [-1.3316924326803257, -4.9370371421622625, 33.619521849828544],'time': 2000,});
});



第三步,为平面图创建一块面板,并调整一下面板的位置以及大小。
图片下载地址:
链接:https://pan.baidu.com/s/1gmNjIj2ekbw1rO3MoujHqQ 提取码:i0c1


//面板相关
//************************************************************************************/
var panel = new THING.widget.Panel({closeIcon: false,dragable: false, retractable: true,opacity: 0.9,hasTitle: true,
});
panel.width = 600;
panel.position = [0, 200];
var dataObj = {iframe: ''
};
var iframe = panel.addIframe(dataObj, 'iframe').caption('').setHeight("290px");


第四步,编写iframe页。写完记得将这个页面和图片上传到页面资源,资源 => 页面资源 => 按钮(上传) 。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><style>.total_image {margin : 20px;}.total_image img{cursor: pointer;transition: all 0.6s;width: 50px;}.total_image img:hover{transform: scale(1.5);position:relative;z-index:100;}</style>
</head>
<body>
<div class="total_image" style="width: 500px;height: 280px;background-size: 100% auto"><img class="model_imag" src="发电室1.jpg" style="float: left;display: block;width: 85px;height: 84px" onclick="onClick('PowerGenerationGroup_01','viewPoint_1')" ><img class="model_imag" src="发电室2.jpg" style="float: left;display: block;width: 78px;height: 84px" onclick="onClick('PowerGenerationGroup_02','viewPoint_2')" ><img class="model_imag" src="发电室3.jpg" style="float: left;display: block;width:170px;height: 84px" onclick="onClick('PowerGenerationGroup_03','viewPoint_3')" ><img class="model_imag" src="发电室4.jpg" style="float: left;display: block;width:167px;height: 84px" onclick="onClick('PowerGenerationGroup_04','viewPoint_4')" ><div style="display: block;float: left;width: 100px;height: 145px;background-color:white"><img class="model_imag" src="办公室1.jpg" style="float: left;display: block;width:100px;height: 60px" onclick="onClick('Office','viewPoint_5')" ><img class="model_imag" src="返回.png" style="float: left;display: block;width:100px;height: 80px" onclick="initViewPoint()"></div><img class="model_imag" src="发电室5.jpg" style="float: right;display: block;width:123px" onclick="onClick('PowerGenerationGroup_05','viewPoint_8')" > <img class="model_imag" src="会议室1.jpg" style="float: left;display: block;width: 138px;height: 145px"  alt="" onclick="onClick('BoardRoom_01','viewPoint_6')"><img class="model_imag" src="会议室2.jpg" style="float: left;display: block;width: 138px;height: 145px"  alt="" onclick="onClick('BoardRoom_02','viewPoint_7')" > 
</div><script>function onClick(viewPoint,target){window.parent.onClick(viewPoint,target);}function initViewPoint(){window.parent.initViewPoint();}
</script>
</body>
</html>


第五步,完成onClick()和initViewPoint()方法。

//事件相关
//************************************************************************************/
var currentModule = null;//点击事件
function onClick(targetObj, viewPoint) {currentModule = app.query(targetObj)[0];currentModule.position = [0, 0, 0];currentModule.style.opacity = 1;app.camera.flyTo({'object': app.query(viewPoint)[0],'offset': [0, 13, 7],'time': 1000,complete: function () {currentModule.brothers.style.opacity = 0.3;}});
}
//返回事件
function initViewPoint() {currentModule.brothers.style.opacity = 1;currentModule = null;app.camera.flyTo({'position': [36.357131498969785, 61.953024217074265, 69.12160670337104],'target': [-1.3316924326803257, -4.9370371421622625, 33.619521849828544],'time': 1000,});
}


小结

第一部分我们主要完成了iframe与我们的3D场景的简单交互,这里也没有做什么特效只是做了一个点击事件。这里值得一提的是currentModule这个全局变量,开始我没有创建这个变量只是将我当前点击的物体obj.style.opacity = 1;obj.brothers.style.opacity = 0.3, 但是执行initViewPoint(){app.query(’.Thing’).style.opacity=1}无法将场景的opacity 属性还原(自己可以试一下,或者有解决方案留言)。第二部分我会给iframe页加上鼠标悬停事件让iframe页的img标签和我们场景中的obj一起动起来!


完整代码

可以粘到 ThingJS 网站在线开发环境运行 http://www.thingjs.com/guide/?m=sample


	//加载场景代码
var app = new THING.App({// 场景地址"url": "http://www.thingjs.com/./uploads/wechat/S2Vyd2lu/scene/Campus04",
});
//场景相关
//************************************************************************************/
app.on('load', function () {app.camera.flyTo({'position': [36.357131498969785, 61.953024217074265, 69.12160670337104],'target': [-1.3316924326803257, -4.9370371421622625, 33.619521849828544],'time': 2000,});
});
//面板相关
//************************************************************************************/
var panel = new THING.widget.Panel({closeIcon: false,dragable: false, retractable: true,opacity: 0.9,hasTitle: true,
});
panel.width = 600;
panel.position = [0, 200];
var dataObj = {iframe: '/uploads/wechat/S2Vyd2lu/file/平面图导航/ifram.html'
};
var iframe = panel.addIframe(dataObj, 'iframe').caption('').setHeight("290px");//事件相关
//************************************************************************************/
var currentModule = null;//点击事件
function onClick(targetObj, viewPoint) {currentModule = app.query(targetObj)[0];currentModule.position = [0, 0, 0];currentModule.style.opacity = 1;app.camera.flyTo({'object': app.query(viewPoint)[0],'offset': [0, 13, 7],'time': 1000,complete: function () {currentModule.brothers.style.opacity = 0.3;}});
}
//返回事件
function initViewPoint() {currentModule.brothers.style.opacity = 1;currentModule = null;app.camera.flyTo({'position': [36.357131498969785, 61.953024217074265, 69.12160670337104],'target': [-1.3316924326803257, -4.9370371421622625, 33.619521849828544],'time': 1000,});
}

 

这篇关于基于 WebGL(ThingJS)的室内平面图 2D/3D 导航 DEMO(Part 1)...的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/340496

相关文章

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

MiniGPT-3D, 首个高效的3D点云大语言模型,仅需一张RTX3090显卡,训练一天时间,已开源

项目主页:https://tangyuan96.github.io/minigpt_3d_project_page/ 代码:https://github.com/TangYuan96/MiniGPT-3D 论文:https://arxiv.org/pdf/2405.01413 MiniGPT-3D在多个任务上取得了SoTA,被ACM MM2024接收,只拥有47.8M的可训练参数,在一张RTX

SAM2POINT:以zero-shot且快速的方式将任何 3D 视频分割为视频

摘要 我们介绍 SAM2POINT,这是一种采用 Segment Anything Model 2 (SAM 2) 进行零样本和快速 3D 分割的初步探索。 SAM2POINT 将任何 3D 数据解释为一系列多向视频,并利用 SAM 2 进行 3D 空间分割,无需进一步训练或 2D-3D 投影。 我们的框架支持各种提示类型,包括 3D 点、框和掩模,并且可以泛化到不同的场景,例如 3D 对象、室

Level3 — PART 3 — 自然语言处理与文本分析

目录 自然语言处理概要 分词与词性标注 N-Gram 分词 分词及词性标注的难点 法则式分词法 全切分 FMM和BMM Bi-direction MM 优缺点 统计式分词法 N-Gram概率模型 HMM概率模型 词性标注(Part-of-Speech Tagging) HMM 文本挖掘概要 信息检索(Information Retrieval) 全文扫描 关键词

MySQL record 02 part

查看已建数据库的基本信息: show CREATE DATABASE mydb; 注意,是DATABASE 不是 DATABASEs, 命令成功执行后,回显的信息有: CREATE DATABASE mydb /*!40100 DEFAULT CHARACTER SET utf8mb3 / /!80016 DEFAULT ENCRYPTION=‘N’ / CREATE DATABASE myd

linux 内核提权总结(demo+exp分析) -- 任意读写(四)

hijack_modprobe_path篇 本文转自网络文章,内容均为非盈利,版权归原作者所有。 转载此文章仅为个人收藏,分享知识,如有侵权,马上删除。 原文作者:jmpcall 专栏地址:https://zhuanlan.kanxue.com/user-815036.htm     原理同hijack_prctl, 当用户执行错误格式的elf文件时内核调用call_usermod

linux 内核提权总结(demo+exp分析) -- 任意读写(三)

hijack_prctl篇 本文转自网络文章,内容均为非盈利,版权归原作者所有。 转载此文章仅为个人收藏,分享知识,如有侵权,马上删除。 原文作者:jmpcall 专栏地址:https://zhuanlan.kanxue.com/user-815036.htm   prctl函数: 用户态函数,可用于定制进程参数,非常适合和内核进行交互 用户态执行prctl函数后触发prctl系统

linux 内核提权总结(demo+exp分析) -- 任意读写(二)

hijack_vdso篇 本文转自网络文章,内容均为非盈利,版权归原作者所有。 转载此文章仅为个人收藏,分享知识,如有侵权,马上删除。 原文作者:jmpcall 专栏地址:https://zhuanlan.kanxue.com/user-815036.htm     vdso: 内核实现的一个动态库,存在于内核,然后映射到用户态空间,可由用户态直接调用 内核中的vdso如果被修改

linux 内核提权总结(demo+exp分析) -- 任意读写(一)

cred篇 本文转自网络文章,内容均为非盈利,版权归原作者所有。 转载此文章仅为个人收藏,分享知识,如有侵权,马上删除。 原文作者:jmpcall 专栏地址:https://zhuanlan.kanxue.com/user-815036.htm   每个线程在内核中都对应一个线程结构块thread_infothread_info中存在task_struct类型结构体 struct t

linux 内核提权总结(demo+exp分析) -- ROP(二)

ret2usr CR4篇 本文转自网络文章,内容均为非盈利,版权归原作者所有。 转载此文章仅为个人收藏,分享知识,如有侵权,马上删除。 原文作者:jmpcall 专栏地址:https://zhuanlan.kanxue.com/user-815036.htm   smep: smep是内核的一种保护措施, 使得内核不可执行用户态代码 内核通过CR4寄存器的第20位来控制smep,