本发明涉及一种基于GLTF的轻量化模型在浏览器展示及操作的方法,涉及三维模型在浏览器展示领域,特别是GLTF格式模型在Chrome、Firefox等浏览器中展示。通过三维模型到GLTF的快速转换方案,用户可以直接在页面上对GLTF格式的模型进行展示查看,并能够对模型节点进行展开,同时支持对模型进行测量、标注、剖切、爆炸、旋转、平移、放大、缩小、复位、重新加载等操作,在一些情况下用户不必打开MCAD工具查看三维模型,极大提高模型查看展示效率。
基于GLTF的轻量化模型在浏览器展示及操作的方法
技术领域
[0001] 本发明涉及一种基于GLTF的轻量化模型在浏览器展示及操作的方法,属于GLTF数据格式的解析的技术领域。
背景技术
[0002] GLTF格式基于JSON格式进行构造,该格式描述了一个3D场景,包含对该3D场景描述的场景图scene,其中场景中独立的3D对象通过网格三角面片mesh的形式进行定义,另外在gltf中还定义了3D对象所使用的材质信息material,texture节点用来定义sampler对象和image图片对象,accessor是一个访问任意数据的抽象数据源。
发明内容
[0003] 为了解决上述技术问题,本发明提供一种基于GLTF的轻量化模型在浏览器展示及操作的方法,其具体技术方案如下:
[0004] 一种基于GLTF的轻量化模型在浏览器展示及操作的方法,包括以下步骤:
[0005] 步骤1:选择文件或者压缩文件,判断文件或者压缩文件的模型格式,选择的文件或者压缩文件中不包含后缀名为GLTF的文件时,弹出错误提醒,选择的文件或者压缩文件中包含后缀名为GLTF的文件时,在浏览器页面加载选择的模型并展示;
[0006] 步骤2:对选择的文件或者压缩文件进行解析,若加载文件为压缩包,则先进行解压,将得到的文件转换成blob格式数据,分别初始化GLTFLoader、 DRACOLoader 、KTX2Loader,对blob格式数据通过loader的load方法加载,获取到模型的Scene场景信息进行展示;
[0007] 通过对得到展示模型的数据结构提取,得到模型树状结构节点,从而进行模型结构树展示,并能够展开折叠结构树,支持对节点进行搜索及定位;
[0008] 步骤3:根据模型的位置,对模型进行测量操作,包括点到点距离,点到直线距离,点到平面距离,并按照测量结果在页面显示;
[0009] 点点测量根据鼠标点击依次在模型拾取模型两点startPoint和endPoint信息并获取所拾取点的三维坐标Vector信息,通过distanceTo方法计算两点之间距离,创建Label在页面进行展示;
[0010] 点到直线测量根据鼠标点击分别拾取模型第一个点startPoint,拾取直线时需首先判断所拾取为线段并显示该线段,默认线段线框为隐藏,并获取startPoint到line上的投影点,通过distanceTo计算点到直线上投影的距离,创建Label在页面进行展示;
[0011] 点到平面测量根据鼠标点击分别拾取模型第一个点startPoint,拾取直线时需首先判断所拾取为平面并显示该平面,默认平面线框为隐藏,并获取startPoint到plane上的投影点,通过distanceTo计算点到直线上投影的距离,创建Label在页面进行展示;
[0012] 步骤4:在页面上能直接对模型进行标注操作,包括文本标注,序号标注,零件号标注,并能对已做标注内容进行修改、删除与保存操作;
[0013] 点击页面模型,在模型中根据深度算法拾取点击的点,以拾取点为起始创建引线,终点创建文本,采用THREE.Sprite精灵文本组件初始化文本,通过sprite的position方法设置文本位置,Sprite是一个永远朝向相机的平面,创建出的文本框正对屏幕;编辑文本框时先获取文本框Sprite对象,获取其值,修改该值即可;删除文本框时通过Sprite对象remove方法删除已创建的文本组件;
[0014] 步骤5:在页面能对模型六个方向进行剖切,并支持反向剖切,同时进行多个方向的剖切;
[0015] 根据模型尺寸,计算并绘制外边框最大包络体box3,计算包络体中心点center,拖动长方形包络体某一个面按照向量vector对面进行移动,移动过处通过计算隐藏模型,并支持多面同时拖动对模型剖切;
[0016] 步骤6:根据模型在CAD中视图,在浏览器页面能直接展示轻量化模型六视图,包括正视图、左视图、右视图、后视图、俯视图和仰视图;
[0017] 通过场景中心点,及模型中心点,改变相机位置,来达到显示模型不同视图效果,如正视图时设置相机位置如下:
[0018] $mv.camera.position.set(center.x ‑ $mv.model.position.x, center.y ‑ $mv.model.position.y, center.z ‑ $mv.model.position.z + size * scale * distance);
[0019] 步骤7:根据模型在PLM中属性信息及PMI标注信息,在浏览器页面分别展示;
[0020] 通过JSON文件获取PMI标注信息在模型上的位置即为标注信息的起点为位置,标注文本通过JSON中相关信息创建SVG图片文档,通过SVGLoader加载SVG图片,使标注信息在页面进行展示。
[0021] 进一步的,在查看过程中,如需查看其它模型,能直接在页面加载其它模型并重新显示。
[0022] 进一步的,所述GLTF模型中包括了gltf、bin、jpg、png、json五种类型的文件,启动时选中gltf后缀文件,bin、jpg、png、json文件自动加载。
[0023] 进一步的,在浏览器中能够按照名称对节点进行搜索,节点与模型能进行交互,选中节点,对应模型会高亮显示,当选中模型时,对应的结构树节点高亮显示。
[0024] 进一步的,所述浏览器界面上有测量按钮、标注按钮、爆炸按钮、剖切按钮、视图按钮和属性按钮,
[0025] 通过测量按钮,进行步骤3,
[0026] 通过标注按钮,进行步骤4,
[0027] 通过剖切按钮,进行步骤5,
[0028] 通过视图按钮,进行步骤6,
[0029] 通过爆炸按钮,对模型进行爆炸与复原操作,
[0030] 通过属性按钮,查看当前加载模型属性信息。
[0031] 进一步的,通过重新加载可复原按钮模型可重新加载或者复原居中。
[0032] 本发明的有益效果是:
[0033] 本发明能够在浏览器上查看展示三维模型,并且不需安装插件,大大降低模型查看成本,极大提高加载模型速率,并能够对模型进行部分操作,可应用于模型审批、透明工厂等各个领域,极大提高工作效率。
附图说明
[0034] 图1是本发明的轻量化模型数据展示流程示意图,
[0035] 图2是本发明的轻量化模型展示页面范例,
[0036] 图3是本发明的总体功能架构。
具体实施方式
[0037] 现在结合附图对本发明作进一步详细的说明。这些附图均为简化的示意图,仅以示意方式说明本发明的基本结构,因此其仅显示与本发明有关的构成。
[0038] 如图1所示,本发明的基于GLTF的轻量化模型在浏览器展示的方法,包括以下步骤:
[0039] 步骤1:输入URL进入模型展示页面,展示默认加载模型。
[0040] 步骤2:点击加载模型按钮,选择GLTF模型(如果选择的文件不为GLTF格式则弹出报错信息),传入模型路径的参数path,调用模型加载方法。
[0041] load模型程序代码:
[0042] $mv.loader.load(url, gltf => {
[0043] const scene = gltf.scene || gltf.scenes[0];
[0044] if (scene.children.length<= 0) {
[0045] // 模型为空,页面发送提示
[0046] document.getElementById('NoModel').click();
[0047] }
[0048] let box3 = new THREE.Box3().expandByObject(scene);
[0049] let center = box3.getCenter(new THREE.Vector3());
[0050] $mv.model = scene;
[0051] $mv.inSideModel = scene;
[0052] // 统一处理模型加载后续处理程序
[0053] traverseModel($mv);
[0054] $mv.scene.add($mv.model);
[0055] // centerModel($mv);
[0056] setCameraPosition($mv);
[0057] // 旋转模型
[0058] // $mv.Rotation.start();
[0059] $mv.isModelLoaded = true;
[0060] loading && loading['rendered'] && loading['rendered']();
[0061] if (!loading || (loading &&enableLoading)) {
[0062] Vue.hideLoading();
[0063] }
[0064] });
[0065] 步骤3:点击左侧结构树按钮,解析模型结构树节点json信息,并展示。
[0066] 解析模型结构树程序代码:
[0067] let setTree = {
[0068] traverse: function (node) {
[0069] if (node.type === 'Group' || node.type === "Object3D") {[0070] let icon = '';
[0071] if (node.type === 'Object3D') {
[0072] icon = '1';
[0073] } else if (node.type === 'Group') {
[0074] icon = '2';
[0075] }
[0076] let parentUUID = '';
[0077] if (node.parent) {
[0078] parentUUID = node.parent.uuid;
[0079] }
[0080] let newNode = {
[0081] uuid: node.uuid,
[0082] name: node.userData.name,
[0083] icon,
[0084] parent: {
[0085] uuid: parentUUID,
[0086] },
[0087] visible: true,
[0088] children: [],
[0089] };
[0090] $mv.treeDefaultChecked.push(newNode.uuid);
[0091] $mv.listNode[node.uuid] = node;
[0092] if (node.parent) {
[0093] if (dictObject3D[node.parent.uuid]) {[0094] dictObject3D[node.parent.uuid].children.push(newNode);
[0095] }
[0096] }
[0097] dictObject3D[newNode.uuid] = newNode;
[0098] $mv.LineSegmentsArray[node.uuid] = [];
[0099] if ($mv.Object3DArray === null) {
[0100] $mv.Object3DArray = newNode;
[0101] }
[0102] } else if (node.type === 'LineSegments') {
[0103] this.setLineSegmentsToParentNode(node.parent.parent.uuid, node);
[0104] }
[0105] }
[0106] }
[0107] 如图2所示,本发明的基于GLTF的轻量化模型在浏览器操作的方法,包括以下步骤:
[0108] 步骤1:点击测量按钮,对模型进行相关测量。
[0109] 测量核心代码:
[0110] let sphere = createdPoint(intersects[0].point);
[0111] pointsArray.push(sphere);
[0112] Group.add(sphere);
[0113] if (pointsArray.length>= 2) {
[0114] let positions = [pointsArray[0].position.x,pointsArray[0].position.y,pointsArray[0].position.z, pointsArray[1].position.x,pointsArray[1].position.y,pointsArray[1].position.z];
[0115] let line = createdLineSegments(pointsArray[0].position, pointsArray[1].position, 'helperLine');
[0116] conststartPoint = new THREE.Vector3().copy(pointsArray[0].position);
[0117] constendPoint = new THREE.Vector3().copy(pointsArray[1].position);
[0118] let distance = startPoint.distanceTo(endPoint);
[0119] Group.add(line);
[0120] let x = (startPoint.x + endPoint.x) / 2;
[0121] let y = (startPoint.y + endPoint.y) / 2;
[0122] let z = (startPoint.z + endPoint.z) / 2;
[0123] let textContent = `${(distance * 1000).toFixed(2)}mm`;
[0124] let Label = createdLabel([x, y, z], textContent);
[0125] Group.add(Label);
[0126] pointsArray = [];
[0127] }
[0128] 步骤2:点击标注按钮,对模型进行相关标注操作。
[0129] 标注核心代码:
[0130] let sprite = new THREE.Sprite(spriteMaterial);
[0131] sprite.text = text;
[0132] console.log(text);
[0133] sprite.group = group;
[0134] sprite.startPos = startPos;
[0135] sprite.endPos = endPos;
[0136] sprite.line = line;
[0137] $mv.sprites.push(sprite);
[0138] sprite.scale.set(0, 0, 0);
[0139] console.log(line.type);
[0140] group.add(line); // 添加
[0141] sprite.position.copy(endPos); // 设置sprite的位置
[0142] sprite.NumberSig = NumberSig;
[0143] sprite.modelSig = modelSig;
[0144] sprite.dot = dot;
[0145] sprite.renderOrder = $mv.sprites.length;
[0146] sprite.user = user;
[0147] sprite.date = date;
[0148] sprite.visible = editable false : true;
[0149] if (id) sprite.groupID = id;
[0150] group.add(sprite);
[0151] 步骤3:点击爆炸按钮,对模型进行爆炸与还原操作。
[0152] 爆炸核心代码:
[0153] function expandModel(nodes, deep) {
[0154] deepCount++;
[0155] let children = [];
[0156] nodes.forEach(node => {
[0157] if ('Group' === node.type || 'Object3D' === node.type) {
[0158] modelChildren.push(node);
[0159] if (node.position.x === 0 &&
[0160] node.position.y === 0 &&
[0161] node.position.z === 0) {
[0162] zeroObject3D.push(node);
[0163] }
[0164] modelChildrenSrcPosition.push(node.position.clone());
[0165] modelChildrenCenterPosition.push(new THREE.Box3().expandByObject(node).getCenter(new THREE.Vector3()));
[0166] }
[0167] if (node.children&&node.children.length> 0) {[0168] node.children.forEach(child => {
[0169] children.push(child);
[0170] });
[0171] }
[0172] });
[0173] if (children.length> 0) {
[0174] expandModel(children, deep);
[0175] }
[0176] }
[0177] 步骤4:点击剖切按钮,对模型进行剖切操作。
[0178] 剖切核心代码:
[0179] initClipBox() {
[0180] const box3 = utils_getBox(this.obj, this.obj);
[0181] var center = new THREE.Vector3();
[0182] box3.getCenter(center);
[0183] var p = new THREE.Vector3(
[0184] this.obj.position.x,
[0185] this.obj.position.y,
[0186] this.obj.position.z
[0187] );
[0188] vardisVector = p.sub(center);
[0189] this.low = box3.min;
[0190] this.high = box3.max;
[0191] this.halfDisVector = new THREE.Vector3(
[0192] disVector.x / 2,
[0193] disVector.y / 2,
[0194] disVector.z / 2
[0195] );
[0196] this.low_init.copy(this.low);
[0197] this.high_init.copy(this.high);
[0198] this.group = new Group();
[0199] this.initPlanes();
[0200] this.initVertices();
[0201] this.initFaces();
[0202] this.faces.forEach((face) => {
[0203] face.material.transparent = true;
[0204] face.material.opacity = 0.3;
[0205] });
[0206] console.log(this.faces);
[0207] this.initLines();
[0208] this.scene.add(this.group);
[0209] }
[0210] 步骤5:点击视图按钮,对模型进行视图展示。
[0211] 视图核心代码:
[0212] $mv.camera.position.set(center.x ‑ $mv.model.position.x, center.y ‑ $mv.model.position.y, center.z ‑ $mv.model.position.z + size * scale * distance)。
[0213] 依据本发明的理想实施例为启示,通过上述的说明内容,相关工作人员完全可以在不偏离本项发明技术思想的范围内,进行多样的变更以及修改。