init: 广西机电数字孪生看板项目首次入库

This commit is contained in:
XingCheng3
2026-06-08 16:03:19 +08:00
commit 5301a44c17
294 changed files with 84592 additions and 0 deletions

23
src/App.vue Normal file
View File

@@ -0,0 +1,23 @@
<template>
<div id="app">
<keep-alive>
<router-view v-if="this.$route.meta.keepAlive"/>
</keep-alive>
<router-view v-if="!this.$route.meta.keepAlive"/>
</div>
</template>
<style>
#app {
font-family: MiSans Bold, serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
}
.el-dialog__wrapper {
pointer-events: none;
}
.el-dialog {
pointer-events: auto;
}
</style>

View File

@@ -0,0 +1,31 @@
import request from '@/utils/request'
import state from '@/store'
import router from '@/router'
// 初始化日历
export function initClendar(year, month) {
return request({
url: '',
method: 'post',
data: {
UserID: state.state.user.id,
ModularID: router.currentRoute.path,
type: '1',
name: '车间生产管理工艺_基础表_工作日历_获得状态',
param: '工作年=' + year + '&工作月=' + month
}
})
}
// 修改工作状态
export function changeState(time, code) {
return request({
url: '',
method: 'post',
data: {
UserID: state.state.user.id,
ModularID: router.currentRoute.path,
type: '2',
name: '车间生产管理工艺_基础表_工作日历_设置状态',
param: '工作日期=' + time + '&工作日状态=' + code
}
})
}

View File

@@ -0,0 +1,70 @@
@font-face {
font-family: MiSans Demibold;
src: url("MiSans-Demibold.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}
@font-face {
font-family: MiSans Bold;
src: url("MiSans-Bold.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}
@font-face {
font-family: MiSans ExtraLight;
src: url("MiSans-ExtraLight.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}
@font-face {
font-family: MiSans Heavy;
src: url("MiSans-Heavy.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}
@font-face {
font-family: MiSans Light;
src: url("MiSans-Light.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}
@font-face {
font-family: MiSans Medium;
src: url("MiSans-Medium.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}
@font-face {
font-family: MiSans Normal;
src: url("MiSans-Normal.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}
@font-face {
font-family: MiSans Regular;
src: url("MiSans-Regular.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}
@font-face {
font-family: MiSans Semibold;
src: url("MiSans-Semibold.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}
@font-face {
font-family: MiSans Thin;
src: url("MiSans-Thin.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}

BIN
src/assets/gray.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/assets/green.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
src/assets/green.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
src/assets/image/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
src/assets/image/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 KiB

BIN
src/assets/image/3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
src/assets/image/GQlogo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

BIN
src/assets/image/MSlogo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
src/assets/image/MT.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
src/assets/image/OP1010.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 MiB

BIN
src/assets/image/OP1010.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

BIN
src/assets/image/OP1020.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

BIN
src/assets/image/OP1030.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

BIN
src/assets/image/OP6010.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

BIN
src/assets/image/OP6010.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

BIN
src/assets/image/OP6020.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 765 KiB

BIN
src/assets/image/OP6030.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 KiB

BIN
src/assets/image/OP6040.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 KiB

BIN
src/assets/image/OP6050.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 KiB

BIN
src/assets/image/OP6060.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 KiB

BIN
src/assets/image/OP6070.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 KiB

BIN
src/assets/image/OP6080.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 KiB

BIN
src/assets/image/OP6090.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 KiB

BIN
src/assets/image/OP6100.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 KiB

BIN
src/assets/image/OP6110.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 439 KiB

BIN
src/assets/image/OP6120.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 KiB

BIN
src/assets/image/OP6130.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 KiB

BIN
src/assets/image/OP6140.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 KiB

BIN
src/assets/image/OP6150.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 KiB

BIN
src/assets/image/OP6160.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 KiB

BIN
src/assets/image/OP6170.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 KiB

BIN
src/assets/image/OP6180.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 651 KiB

BIN
src/assets/image/OP6190.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 769 KiB

BIN
src/assets/image/OP6200.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 KiB

BIN
src/assets/image/OP6210.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 KiB

BIN
src/assets/image/TZ.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
src/assets/image/TZlogo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
src/assets/image/WCLOGO.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
src/assets/image/bg.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 KiB

BIN
src/assets/image/call.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
src/assets/image/left1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

BIN
src/assets/image/left2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
src/assets/image/left3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
src/assets/image/left4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
src/assets/image/left5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/assets/image/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
src/assets/image/logo1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
src/assets/image/logo2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
src/assets/image/reset.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
src/assets/image/s1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
src/assets/image/s2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
src/assets/jy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

BIN
src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
src/assets/purple.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
src/assets/red.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
src/assets/red.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
src/assets/sad.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
src/assets/smile.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
src/assets/usual.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
src/assets/yellow.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
src/assets/yellow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
src/assets/哭脸.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,155 @@
class VRButton {
static createButton(renderer, options) {
if (options) {
console.error('THREE.VRButton: The "options" parameter has been removed. Please set the reference space type via renderer.xr.setReferenceSpaceType() instead.')
}
const button = document.createElement('button')
function showEnterVR(/* device*/) {
let currentSession = null
async function onSessionStarted(session) {
session.addEventListener('end', onSessionEnded)
await renderer.xr.setSession(session)
button.textContent = 'EXIT VR'
currentSession = session
}
function onSessionEnded(/* event*/) {
currentSession.removeEventListener('end', onSessionEnded)
button.textContent = 'ENTER VR'
currentSession = null
}
//
button.style.display = ''
button.style.cursor = 'pointer'
button.style.left = 'calc(50% - 50px)'
button.style.width = '100px'
button.textContent = 'ENTER VR'
button.onmouseenter = function() {
button.style.opacity = '1.0'
}
button.onmouseleave = function() {
button.style.opacity = '0.5'
}
button.onclick = function() {
if (currentSession === null) {
// WebXR's requestReferenceSpace only works if the corresponding feature
// was requested at session creation time. For simplicity, just ask for
// the interesting ones as optional features, but be aware that the
// requestReferenceSpace call will fail if it turns out to be unavailable.
// ('local' is always available for immersive sessions and doesn't need to
// be requested separately.)
const sessionInit = { optionalFeatures: ['local-floor', 'bounded-floor', 'hand-tracking', 'layers'] }
navigator.xr.requestSession('immersive-vr', sessionInit).then(onSessionStarted)
} else {
currentSession.end()
}
}
}
function disableButton() {
button.style.display = ''
button.style.cursor = 'auto'
button.style.left = 'calc(50% - 75px)'
button.style.width = '150px'
button.onmouseenter = null
button.onmouseleave = null
button.onclick = null
}
function showWebXRNotFound() {
disableButton()
button.textContent = 'VR NOT SUPPORTED'
}
function showVRNotAllowed(exception) {
disableButton()
console.warn('Exception when trying to call xr.isSessionSupported', exception)
button.textContent = 'VR NOT ALLOWED'
}
function stylizeElement(element) {
element.style.position = 'absolute'
element.style.bottom = '20px'
element.style.padding = '12px 6px'
element.style.border = '1px solid #fff'
element.style.borderRadius = '4px'
element.style.background = 'rgba(0,0,0,0.1)'
element.style.color = '#fff'
element.style.font = 'normal 13px sans-serif'
element.style.textAlign = 'center'
element.style.opacity = '0.5'
element.style.outline = 'none'
element.style.zIndex = '999'
}
if ('xr' in navigator) {
button.id = 'VRButton'
button.style.display = 'none'
stylizeElement(button)
navigator.xr.isSessionSupported('immersive-vr').then(function(supported) {
supported ? showEnterVR() : showWebXRNotFound()
if (supported && VRButton.xrSessionIsGranted) {
button.click()
}
}).catch(showVRNotAllowed)
return button
} else {
const message = document.createElement('a')
if (window.isSecureContext === false) {
message.href = document.location.href.replace(/^http:/, 'https:')
message.innerHTML = 'WEBXR NEEDS HTTPS' // TODO Improve message
} else {
message.href = 'https://immersiveweb.dev/'
message.innerHTML = 'WEBXR NOT AVAILABLE'
}
message.style.left = 'calc(50% - 90px)'
message.style.width = '180px'
message.style.textDecoration = 'none'
stylizeElement(message)
return message
}
}
static xrSessionIsGranted = false;
static registerSessionGrantedListener() {
if ('xr' in navigator) {
navigator.xr.addEventListener('sessiongranted', () => {
VRButton.xrSessionIsGranted = true
})
}
}
}
VRButton.registerSessionGrantedListener()
export { VRButton }

View File

@@ -0,0 +1,327 @@
<template>
<div style="pointer-events: none">
<el-dialog title="修改配置文件" :visible.sync="dialogFormVisible" width="1000px" class="myDia" :modal="false" :close-on-press-escape="false" v-el-drag-dialog>
<el-collapse v-model="activeNames">
<el-collapse-item title="通讯配置" name="1">
<el-row class="row-Show">
<span class="title-show">标题</span>
<el-input size="mini" style="width: 300px" v-model="configInfo['title']"></el-input>
<span class="title-show">工位和协议</span>
<el-input size="mini" style="width: 120px" v-model="configInfo['webSocketOpName']"></el-input>
<el-input size="mini" style="width: 180px" v-model="configInfo['webSocketBSport']"></el-input>
</el-row>
<el-row class="row-Show">
<span class="title-show">通讯类型</span>
<el-radio-group size="mini" v-model="configInfo['connectType']">
<el-radio :label="1">WebSocket</el-radio>
<el-radio :label="2">MQTT</el-radio>
<el-radio :label="3">其他</el-radio>
</el-radio-group>
</el-row>
<el-row class="row-Show">
<span class="title-show">Socket_IP&Port</span>
<el-input size="mini" style="width: 300px" v-model="configInfo['webSocketIp']"></el-input>
<span class="title-show">MQTT_IP&Port</span>
<el-input size="mini" style="width: 200px" v-model="configInfo['MQTTHost']"></el-input>
<el-input size="mini" style="width: 100px" v-model="configInfo['MQTTPort']"></el-input>
</el-row>
<el-row class="row-Show">
<span class="title-show">数据服务器</span>
<el-input size="mini" style="width: 300px" v-model="configInfo['dataBaseURL']"></el-input>
<span class="title-show">node服务</span>
<el-input size="mini" style="width: 300px" v-model="configInfo['NodeRootIp']"></el-input>
</el-row>
</el-collapse-item>
<el-collapse-item name="2">
<template slot="title">
机器人/设备配置
<el-button size="mini" type="warning" style="margin-left: 10px" @click.stop.prevent="dialogFormVisible = false">重置配置文件</el-button>
<el-button size="mini" type="primary" style="margin-left: 10px" @click.stop.prevent="exportConfig">导出配置文件</el-button>
{{ currentUUid }}
</template>
<el-col :span="6">
<el-table
:data="tableDataRobot"
:highlight-current-row="false"
element-loading-text="数据加载中"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.2)"
style="width: 100%"
max-height="300"
border
size="mini"
class="my-table-show"
@cell-dblclick="showEdit"
@row-click="rowClick">
<el-table-column type="index" label=" " align="center" width="40"/>
<!-- <el-table-column align="center" label="name">-->
<!-- <template slot-scope="scope">-->
<!-- {{ scope.row.name }}-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column align="center" label="机器人模型id">
<template slot-scope="scope">
<el-input v-if="scope.row.edit" size="mini" v-model="scope.row.uuid"></el-input>
<span v-else>{{ scope.row.uuid }}</span>
</template>
</el-table-column>
<el-table-column align="center" width="50px" label="操作">
<template slot-scope="scope">
<el-button size="mini" type="text" style="color: #00893d" @click="applyRobotConfig(scope.row)">应用</el-button>
<br>
<el-button size="mini" type="text" style="color: red">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-col>
<el-col :span="18">
<el-table
:data="RobotChildrenData"
:highlight-current-row="false"
element-loading-text="数据加载中"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.2)"
style="width: 100%"
max-height="300"
border
size="mini">
<el-table-column type="index" label=" " align="center" width="50"/>
<!-- <el-table-column align="center" label="关节名字">-->
<!-- <template slot-scope="scope">-->
<!-- {{ scope.row.name }}-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column align="center" label="关节ID" width="150">
<template slot-scope="scope">
<el-input size="mini" v-model="scope.row.ModelId "></el-input>
</template>
</el-table-column>
<el-table-column align="center" label="type" width="110">
<template slot-scope="scope">
<el-select v-model="scope.row.type" size="mini">
<el-option
v-for="item in robotJointType"
:key="item.value"
:label="item.label"
:value="item.value"/>
</el-select>
</template>
</el-table-column>
<el-table-column align="center" label="axis" width="80">
<template slot-scope="scope">
<el-select v-model="scope.row.axis" size="mini">
<el-option
v-for="item in robotJointAxis"
:key="item.value"
:label="item.label"
:value="item.value"/>
</el-select>
</template>
</el-table-column>
<el-table-column align="center" label="flip" width="80">
<template slot-scope="scope">
<el-select v-model="scope.row.flip" size="mini">
<el-option
v-for="item in robotJointFlip"
:key="item.value"
:label="item.label"
:value="item.value"/>
</el-select>
</template>
</el-table-column>
<el-table-column align="center" label="delta" width="80">
<template slot-scope="scope">
<el-input size="mini" v-model="scope.row.delta "></el-input>
</template>
</el-table-column>
<el-table-column align="center" label="multiple" width="120">
<template slot-scope="scope">
<el-input size="mini" v-model="scope.row.multiple "></el-input>
</template>
</el-table-column>
<el-table-column align="center" width="50px" label="操作">
<template slot-scope="scope">
<el-button size="mini" type="text" style="color: #00893d" @click="applyRobotConfig(scope.row, scope.$index)">应用</el-button>
</template>
</el-table-column>
</el-table>
</el-col>
</el-collapse-item>
</el-collapse>
</el-dialog>
</div>
</template>
<script>
import Mousetrap from './js/mousetrap.js'
import axios from 'axios'
export default {
name: 'ConfigVue',
data() {
return {
currentUUid: '',
activeNames: '2',
configInfo: {},
tableDataRobot: [],
tableDataRobotChildren: {},
RobotChildrenData: [],
dialogFormVisible: false,
robotJointType: [
{
label: 'position',
value: 'position'
},
{
label: 'rotation',
value: 'rotation'
}
],
robotJointFlip: [
{
label: 1,
value: 1
},
{
label: -1,
value: -1
}
],
robotJointAxis: [
{
label: 'x',
value: 'x'
},
{
label: 'y',
value: 'y'
},
{
label: 'z',
value: 'z'
}
],
form: {
name: '',
region: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: ''
},
formLabelWidth: '120px'
}
},
mounted() {
this.getConfig().then(res => {
this.configInfo = res
console.log(res)
this.solveRobotInfoFirst()
})
const scope = this
Mousetrap.bind('ctrl+c', function() {
scope.solveConfig()
return false
})
},
methods: {
solveConfig() {
console.log('ctrl + c')
this.dialogFormVisible = !this.dialogFormVisible
},
getConfig() {
return new Promise((resolve, reject) => {
axios.get('./DMT_WEB/config/config.json').then(res => {
const configData = res.data
resolve(configData)
}).catch(err => {
reject(err)
})
})
},
solveRobotInfoFirst() {
this.tableDataRobot = []
this.tableDataRobotChildren = {}
for (const argumentsKey in this.configInfo.robotList) {
this.tableDataRobot.push({
name: '',
uuid: argumentsKey,
edit: false
})
this.tableDataRobotChildren[argumentsKey] = []
for (let i = 0; i < this.configInfo.robotList[argumentsKey].length; i++) {
this.tableDataRobotChildren[argumentsKey].push(this.configInfo.robotList[argumentsKey][i])
}
}
},
showEdit(row) {
row.edit = !row.edit
},
rowClick(row) {
this.currentUUid = row.uuid
this.RobotChildrenData = this.tableDataRobotChildren[row.uuid]
},
exportConfig() {
this.configInfo['robotList'] = this.tableDataRobotChildren
const saveJsonStr = JSON.stringify(this.configInfo)
const blob = new Blob([saveJsonStr], {
type: 'application/json'
})
const objectUrl = URL.createObjectURL(blob)
const aa = document.createElement('a')
aa.href = objectUrl
aa.download = 'config.json'
aa.click()
URL.revokeObjectURL(objectUrl)
},
applyRobotConfig(row, index) {
const rootRobotJoint = window.editor.robotList[this.currentUUid][index]
if (row.ModelId === rootRobotJoint.ModelId) {
window.editor.robotList[this.currentUUid][index].axis = row.axis
window.editor.robotList[this.currentUUid][index].delta = row.delta
window.editor.robotList[this.currentUUid][index].flip = row.flip
window.editor.robotList[this.currentUUid][index].type = row.type
}
}
}
}
</script>
<style scoped>
.row-Show {
margin: 10px 0
}
.title-show {
font-weight: bolder;
font-size: 16px;
margin: 0 10px;
width: 130px;
display: inline-block;
text-align: right;
}
</style>
<style>
.myDia .el-dialog {
pointer-events: auto;
}
.myDia .el-dialog__body {
padding: 5px 15px;
}
.myDia .el-dialog--center .el-dialog__body {
padding: 15px;
}
.myDia .el-dialog__title {
font-size: 22px;
color: #000000;
}
.myDia .el-dialog__header {
padding: 15px;
}
.myDia .el-dialog__wrapper{
pointer-events:none;
}
.myDia .el-dialog{
pointer-events:auto;
}
</style>

View File

@@ -0,0 +1,46 @@
export default{
bind(el, binding) {
const dialogHeaderEl = el.querySelector('.el-dialog__header')
const dragDom = el.querySelector('.el-dialog')
dialogHeaderEl.style = 'cursor:move;'
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)
dialogHeaderEl.onmousedown = (e) => {
// 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX - dialogHeaderEl.offsetLeft
const disY = e.clientY - dialogHeaderEl.offsetTop
// 获取到的值带px 正则匹配替换
let styL, styT
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
if (sty.left.includes('%')) {
styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100)
styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100)
} else {
styL = +sty.left.replace(/\px/g, '')
styT = +sty.top.replace(/\px/g, '')
}
document.onmousemove = function(e) {
// 通过事件委托,计算移动的距离
const l = e.clientX - disX
const t = e.clientY - disY
// 移动当前元素
dragDom.style.left = `${l + styL}px`
dragDom.style.top = `${t + styT}px`
// 将此时的位置传出去
// binding.value({x:e.pageX,y:e.pageY})
}
document.onmouseup = function(e) {
document.onmousemove = null
document.onmouseup = null
}
}
}
}

View File

@@ -0,0 +1,13 @@
import drag from './drag'
const install = function(Vue) {
Vue.directive('el-drag-dialog', drag)
}
if (window.Vue) {
window['el-drag-dialog'] = drag
Vue.use(install); // eslint-disable-line
}
drag.install = install
export default drag

1437
src/components/DMT/index.vue Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,78 @@
import { WebsocketMessageReceive } from './WebSocketMessage.js'
import mqtt from 'mqtt'
function connectMqtt(editor) {
const connection = {
host: editor.mqttHost,
port: editor.mqttPort,
endpoint: '/mqtt',
clean: true, // 保留会话
connectTimeout: 4000, // 超时时间
reconnectPeriod: 4000, // 重连时间间隔
// 认证信息
clientId: 'mqttjs_3be2c321' + new Date().getTime(), // 同一个ID 无法二次连接
username: 'DT',
password: ''
}
const subscription = {
topic: editor.opname,
qos: 0
}
const websocketMessageReceive = new WebsocketMessageReceive(editor)
const { host, port, endpoint, ...options } = connection
const wsHeaderString = location.protocol === 'https:' ? 'wss' : 'ws'
// const connectUrl = `${wsHeaderString}://${location.host}${endpoint}`
const connectUrl = `${wsHeaderString}://${host}:${port}${endpoint}`
console.log(connectUrl)
try {
editor.mqttClient = mqtt.connect(connectUrl, options)
} catch (error) {
console.log('MQTT connect error', error)
}
editor.mqttClient.on('connect', () => {
editor.showMessage('加载完成连接MQTT服务器成功', 'success', 2000)
console.log('MQTT Connection succeeded!')
editor.isOk = true
const { topic, qos } = subscription
editor.mqttClient.subscribe(topic, { qos }, (error, res) => {
if (error) {
console.log('Subscribe to topics error', error)
return
}
websocketMessageReceive.getOriginTagValue()
})
})
editor.mqttClient.on('error', error => {
console.log('MQTT Connection failed', error)
try {
editor.showMessage('MQTT服务器连接失败', 'error', 2000)
editor.socket.close()
if (editor.IsAllowConnect) {
// 显示一下
editor.showMessage('重新连接MQTT服务器', 'warning', 2000)
console.log('重新连接MQTT服务器')
// 重新连接,打开计时器
setTimeout(function() {
connectMqtt(editor)
}, 5000)
}
} catch (exception) {
const error = exception.toString()
editor.showMessage.error('MQTT服务器出现错误,关闭连接' + error, 'error', 2000)
}
})
// 接收消息
editor.mqttClient.on('message', (topic, message) => {
try {
websocketMessageReceive.websocketMessage({ data: message.toString() })
} catch (exception) {
console.log(exception.toString())
}
})
editor.mqttClient.on('close', () => {
editor.mqttClient.end()
})
}
export { connectMqtt }

View File

@@ -0,0 +1,40 @@
import * as THREE from 'three'
/**
* @param editor Editor
* @param object THREE.Object3D
* @constructor
*/
class ObjectAlarmCommand {
constructor(editor, ModelId) {
this.type = 'ObjectAlarmCommand'
this.ModelId = ModelId
this.editor = editor
this.object = editor.getObjectById(ModelId)
}
exec(isAlarm = true) {
if (!this.object) return
if (isAlarm) {
this.object.traverse(object => {
if (object instanceof THREE.Mesh && !Object.hasOwnProperty.call(object.userData, 'isAxis')) {
object.material.color = new THREE.Color('#ff0000')
object.material.side = 2
object.material.transparent = true
object.material.opacity = 0.8
}
})
// this.editor.playSoundCommand.exec('Alarm', true, this.ModelId)
} else {
this.object.traverse(object => {
if (object instanceof THREE.Mesh) {
const m = this.editor.objMaterial.get(object.id)
if (m)object.material = m.clone()
}
})
// this.editor.playSoundCommand.exec('Alarm', false, this.ModelId)
}
}
}
export { ObjectAlarmCommand }

View File

@@ -0,0 +1,58 @@
/**
* @param editor Editor
* @param object THREE.Object3D
* @constructor
*/
class PlaySoundCommand {
constructor() {
this.type = 'PlaySoundCommand'
this.PlayType = {
Alarm: 'Alarm',
Clash: 'Clash'
}
this.AlarmList = []
this.isAlarm = false
}
/**
* 系统声音
* @param type 报警Alarm 碰撞Clash 。。。。。。。
* @param state 报警/解除报警
* @param ModelId 模型ID
*/
exec(type, state = true, ModelId) {
switch (type) {
case this.PlayType.Alarm:
if (state) {
if (!this.isAlarm) this.playAlarmSound(true)
if (this.AlarmList.indexOf(ModelId) === -1) this.AlarmList.push(ModelId)
this.isAlarm = true
} else {
this.AlarmList = this.AlarmList.filter(res => { return res !== ModelId })
if (this.AlarmList.length === 0) {
this.playAlarmSound(false)
this.isAlarm = false
}
}
break
case this.PlayType.Clash:
break
default:
break
}
}
/**
*
*/
playAlarmSound(play = true) {
// const audio = document.getElementById('alarm')
// play ? audio.play() : audio.pause()
}
playClashSound(play) {
const audio = document.getElementById('clash')
play ? audio.play() : audio.pause()
}
}
export { PlaySoundCommand }

View File

@@ -0,0 +1,629 @@
import * as THREE from 'three'
import { ObjectAlarmCommand } from './ObjectAlarmCommand.js'
import { TWEEN } from 'three/examples/jsm/libs/tween.module.min.js'
const WebsocketMessageReceive = function(editor) {
const scope = this
this.websocketMessage = (msg) => {
new Promise((resolve, reject) => {
let returnMes
const arrays_signal = msg.data.split('|')
const m_SourceType = arrays_signal[0] // 数据类型DT数字孪生数据
const m_DeviceType = arrays_signal[1] // 设备类型Robot机器人类型的设备Device普通设备
const m_DeviceName = arrays_signal[2] // 设备名称
const m_DevicePartName = arrays_signal[3] // 设备运动部件
const m_DevicePartDate = arrays_signal[4] // 设备运动部件数据
switch (m_SourceType) {
case 'DT':
switch (m_DeviceType) {
case editor.ProtocolIdentifiers.Robot_7: // 接受机器人运动数据进行播放 --------------------------现场用----------------
returnMes = scope.deviceMoveEvent.RobotTranslation7(m_DeviceName, m_DevicePartName, m_DevicePartDate)
break
case editor.ProtocolIdentifiers.Device_3:
console.log('设备运行')// --------------------------现场用----------------
returnMes = scope.deviceMoveEvent.DeviceThreeAxis(m_DeviceName, m_DevicePartName, m_DevicePartDate)
break
case editor.ProtocolIdentifiers.Agv_3:// --------------------------现场用----------------
console.log('AGV运行')
returnMes = scope.deviceMoveEvent.AGVThreeAxis(m_DeviceName, m_DevicePartName, m_DevicePartDate)
break
case editor.ProtocolIdentifiers.Device_1: // 接受设备运动数据进行播放,已更新
break
case editor.ProtocolIdentifiers.FirstPosition: // 接受第一个点的数据,瞬间跳到该点,已更新
break
case editor.ProtocolIdentifiers.WareHousePart: //
returnMes = scope.drawWareHousePartOne(m_DeviceName)
break
case editor.ProtocolIdentifiers.Robot_6: // 接受机器人运动数据进行播放
returnMes = scope.deviceMoveEvent.RobotTranslation(m_DeviceName, m_DevicePartName, m_DevicePartDate)
break
case editor.ProtocolIdentifiers.ReLoadData: // 加载所有要播放的数据,避免资源浪费 ***********************UUID测试好用了******************************
break
case editor.ProtocolIdentifiers.PlayAct: // 根据ID 播放数据 状态为1 0暂停 ***********************UUID测试好用了******************************
scope.playActData(m_DeviceName, parseInt(m_DevicePartName))
break
// case editor.ProtocolIdentifiers.ModelTransparent: // 根据传过来的模型名字和透明度 改变模型的透明度 ***********************UUID测试好用了******************************
// returnMes = scope.robotPlan_ModelOperation.modelTrans(m_DeviceName, m_DevicePartName)
// break
case editor.ProtocolIdentifiers.Visible: // 接受CS指令显示、隐藏模型 ***********************UUID测试好用了******************************
returnMes = scope.visibleObjectToBS(m_DeviceName, m_DevicePartName)
break
case 'JointMoveTo':
if (!JSON.parse(m_DevicePartName)) console.log('JointMoveTo数据不对' + m_DevicePartName)
this.JointMoveTo(m_DeviceName, JSON.parse(m_DevicePartName))
break
case editor.ProtocolIdentifiers.C_B_TagIDTrigger:
{
const tag = JSON.parse(m_DeviceName)
scope.solveTagValue(tag.TagID, tag.TagValue)
}
break
case editor.ProtocolIdentifiers.C_B_ObjectAlarm:
{
const Info = JSON.parse(m_DeviceName)
console.log(Info)
for (const infoElement of Info) {
new ObjectAlarmCommand(editor, infoElement.ModelId).exec(!!parseInt(infoElement.value))
}
}
break
case editor.ProtocolIdentifiers.C_B_JointMoveTo:
{
const MoveValueList = JSON.parse(m_DeviceName)
scope.ModelJointMoveTo(MoveValueList)
}
break
case 'showWeld':
this.showWeld(m_DeviceName, m_DevicePartName)
break
case 'showCheckOk':
this.showCheckOk(m_DeviceName, m_DevicePartName)
break
default:
returnMes = '不存在协议:' + msg
break
}
break
default:
returnMes = '不存在协议:' + msg
break
}
resolve(returnMes)
})
}
/**
* HandlerType: 1:显隐,2:自转,3:行为,4:私服位置5:附加拆离指令
* HandlerCode: 模型或者工艺代码
* HandlerValue: 显隐0/1 ,自传:正负转速&axis,行为暂停播放0/1
* TagValueTagValue: 信号值
* @param tagId
* @param tagValue
*/
this.solveTagValue = (tagId, tagValue) => {
const scope = this
const actionInfo = editor.TagActList[tagId]
if (!actionInfo) return
for (const actionInfoElement of actionInfo) {
switch (actionInfoElement.HandlerType) {
case editor.signalSolveType.warning: // 报警
if (tagValue === actionInfoElement.TagValue) {
new ObjectAlarmCommand(editor, actionInfoElement.HandlerCode).exec(!!parseInt(actionInfoElement.HandlerValue))
}
break
case editor.signalSolveType.visible: // 显隐
if (tagValue === actionInfoElement.TagValue) {
scope.visibleObjectToBS(actionInfoElement.HandlerCode, parseInt(actionInfoElement.HandlerValue))
}
break
case editor.signalSolveType.rotation: // 自转
if (tagValue === actionInfoElement.TagValue) {
const ValueFactor = actionInfoElement.ValueFactor
const Axis = actionInfoElement.Axis
// const JointType = actionInfoElement.JointType
const Flip = actionInfoElement.Flip
const ModelCode = actionInfoElement.HandlerCode
scope.modelRotation(ModelCode, Axis, Flip * parseFloat(ValueFactor))
}
break
case editor.signalSolveType.craft: // 行为
if (tagValue === actionInfoElement.TagValue) {
scope.playActData(actionInfoElement.HandlerCode, parseInt(actionInfoElement.HandlerValue))
}
break
case editor.signalSolveType.targetLocation: // 伺服位置
scope.solveServoSignal(actionInfoElement, tagValue)
break
case editor.signalSolveType.attach: // 附加功能
console.log('这个地方的附加功能没用写')
break
default:
break
}
}
}
/**
* 根据ACTid播放动作开启线程
* @param actID
* @param state
*/
this.playActData = (actID, state) => {
const scope = this
if (!editor.isOk) return
if (!editor.worker[actID]) editor.worker[actID] = new Worker('./DMT_WEB/webWorker/playFunction.js')
if (editor.moveTrigger[actID].moveStatus !== state) {
editor.worker[actID].postMessage({
ActID: actID,
State: state,
isOk: editor.isOk,
craftPlaySolveType: editor.craftPlaySolveType,
moveTrigger: JSON.stringify(editor.moveTrigger[actID])
})
editor.moveTrigger[actID].moveStatus = state
}
editor.worker[actID].onmessage = function(event) {
editor.moveTrigger[actID].myVarSetInterval = event.data.myVarSetInterval
editor.moveTrigger[actID].currentFrame = event.data.pausedFrame
const currentFrameData = event.data.currentFrameData
const frameType = event.data.frameType
editor.solveAttachModel('', true)
switch (frameType) {
case editor.craftPlaySolveType.attach:
if (editor.FrameOperation.attach) {
const position = currentFrameData['AttachToModelCode']
const List_AttachModel = currentFrameData['List_AttachModel']
const IsTwoWay = currentFrameData['IsTwoWay']
const IsAttach = currentFrameData['IsAttach']
if (IsAttach) {
const attachData = []
for (const editorElement of List_AttachModel) {
attachData.push({
ModelId: editorElement.ModelCode,
ModelName: editorElement.ModelName,
RootId: position,
IsTwoWay: IsTwoWay
})
}
editor.attachList.set(position, attachData)
} else {
for (const detachData of List_AttachModel) {
const detachModelCode = detachData.ModelCode
editor.scene.attach(editor.getObjectById(detachModelCode))
editor.attachList.forEach((value, key) => {
const attachList = value.filter(res => { return res.ModelId !== detachModelCode })
editor.attachList.set(key, attachList)
})
}
}
}
break
case editor.craftPlaySolveType.visible:
if (editor.FrameOperation.visibleObject) {
const position = currentFrameData['ModelCode']
const Visible = parseInt(currentFrameData['Visible'])
scope.visibleObjectToBS(position, Visible)
}
break
case editor.craftPlaySolveType.rotation:
if (editor.FrameOperation.rotationObject) {
const position = currentFrameData['ModelCode']
const Axis = currentFrameData['Axis']
const Rate = currentFrameData['Rate']
scope.modelRotation(position, Axis, Rate)
}
break
case editor.craftPlaySolveType.craft:
if (editor.FrameOperation.playCraft) {
const position = currentFrameData['CraftCode']
const craftState = parseInt(currentFrameData['CraftValue'])
scope.playActData(position, craftState)
}
break
case editor.craftPlaySolveType.FrameData:
{
const position = currentFrameData['i']
const objectToMove = editor.getObjectById(position)
if (objectToMove) {
if (currentFrameData.tx === 'NaN' || currentFrameData.ty === 'NaN' || currentFrameData.tz === 'NaN' || currentFrameData.qx === 'NaN' || currentFrameData.qy === 'NaN' || currentFrameData.qz === 'NaN' || currentFrameData.qw === 'NaN') {
console.log('craftDataError')
// editor.robotPlan_MessageList.execute(position, 'craftDataError')
} else {
const movePosition = new THREE.Vector3(parseFloat(currentFrameData.tx), parseFloat(currentFrameData.ty), parseFloat(currentFrameData.tz))
const nq = new THREE.Quaternion(parseFloat(currentFrameData.qx), parseFloat(currentFrameData.qy), parseFloat(currentFrameData.qz), parseFloat(currentFrameData.qw))
objectToMove.quaternion.copy(nq)
objectToMove.position.copy(movePosition)
}
}
}
break
case editor.craftPlaySolveType.warning: // 报警
if (editor.FrameOperation.warning) {
new ObjectAlarmCommand(scope.editor, currentFrameData['ModelCode']).exec(!!parseInt(currentFrameData['Visible']))
}
break
default:
delete editor.worker[event.data.ActID]
editor.moveTrigger[actID].moveStatus = 0
editor.moveTrigger[actID].myVarSetInterval = null
editor.moveTrigger[actID].currentFrame = 0
editor.moveTrigger[actID].pausedFrame = 0
break
}
editor.solveAttachModel('', false)
}
}
/**
* 接受CS模型自转的指令
* 接受CS模型自转的指令
* @param objectNames
* @param values
* @param axis
*/
this.modelRotation = (objectNames, axis, values) => {
const scope = this
const EP = 0.000001
let dir = 0
if (!editor.getObjectById(objectNames)) return
const currentModel = editor.getObjectById(objectNames)
if ((parseFloat(values) >= -EP) && (parseFloat(values) <= EP)) {
if (editor.RotationWorker[objectNames]) {
editor.RotationWorker[objectNames].terminate()
delete editor.RotationWorker[objectNames]
delete editor.ModelRotateWorker[objectNames]
}
return
} else {
dir = 1
if (editor.RotationWorker[objectNames]) {
editor.RotationWorker[objectNames].terminate()
delete editor.RotationWorker[objectNames]
delete editor.ModelRotateWorker[objectNames]
}
}
editor.RotationWorker[objectNames] = new Worker('webWorker/modelRotation.js')
if (!editor.ModelRotateWorker[objectNames]) {
editor.ModelRotateWorker[objectNames] = {
state: 0,
myVarSetInterval: null,
doAnimation: false,
ModelCode: objectNames
}
}
editor.RotationWorker[objectNames].postMessage({
ObjectNames: objectNames,
Values: values,
Dir: dir,
ModelRotateWorker: editor.ModelRotateWorker[objectNames],
RotateSpeed: editor.rotateSpeed,
RotationValue: currentModel.rotation[axis]
})
editor.RotationWorker[objectNames].onmessage = (event) => {
scope.modelSelfRotation(currentModel, event.data.rotation, axis)
}
}
this.modelSelfRotation = (currentModel, rotation, axis) => {
currentModel.rotation[axis] = rotation
}
this.ModelJointMoveTo = (MoveValueList) => {
// TOBS?WEB?SCADAMain?DT|C_B_JointMoveTo|[{"ModelCode":"5E6D91B8-B44D-4C44-AAEF-10492E548A1A","JointType":"rotation","Axis":"x","Flip":1,"Value":0,"ValueFactor":0.017453292519943295,"Delta":0}]
// TOBS?WEB?SCADAMain?DT|C_B_JointMoveTo|[{"ModelCode":"644506B1-A05A-4E57-BBA2-C63635586C63","JointType":"position","Axis":"y","Flip":-1,"Value":-15.0,"ValueFactor":0.001,"Delta":-655.0}]
new Promise(resolve => {
for (const MoveValue of MoveValueList) {
const ModelCode = MoveValue.ModelCode
const ValueFactor = parseFloat(MoveValue.ValueFactor)
const type = MoveValue.JointType
const Value = parseFloat(MoveValue.Value)
const Flip = parseFloat(MoveValue.Flip)
const axis = MoveValue.Axis
const Delta = parseFloat(MoveValue.Delta)
const object = editor.getObjectById(ModelCode)
const originInfo = editor.objectIdSet.get(ModelCode)
if (!originInfo) return
const matrix = originInfo['matrix']
const originValue = type === 'rotation' ? originInfo[type]['_' + axis] : originInfo[type][axis]
const lastValue = originInfo['lastValue'] === null ? originValue : originInfo['lastValue']
const moveValue = Flip * (Value - Delta) * ValueFactor
if (object) {
editor.solveAttachModel('', true)
const JointValue = originValue + moveValue
new TWEEN.Tween({
moveValue: lastValue
}).to({ moveValue: JointValue }, 50)
.onStart(function() {
originInfo['lastValue'] = JointValue
}).onUpdate(function() {
switch (type) {
case 'position':
object[type][axis] = this._object.moveValue
break
case 'rotation':
{
const moveAxis = {
x: new THREE.Vector3(1, 1, 1),
y: new THREE.Vector3(1, 1, 1),
z: new THREE.Vector3(1, 1, 1)
}
matrix.extractBasis(moveAxis.x, moveAxis.y, moveAxis.z)
const nM = new THREE.Matrix4()
nM.makeRotationAxis(moveAxis[axis], this._object.moveValue)
nM.multiply(matrix)
object.rotation.setFromRotationMatrix(nM)
object.updateWorldMatrix()
}
break
}
}).start()
editor.solveAttachModel('', false)
} else {
console.log('模型不存在')
}
}
})
}
/**
* 接伺服类的数据
* @param ModelInfo
* @param tagValue
*/
this.solveServoSignal = (ModelInfo, tagValue) => {
try {
const type = ModelInfo.JointType
const axis = ModelInfo.Axis
const flip = ModelInfo.Flip
const Value = ModelInfo.Value
const ValueFactor = ModelInfo.ValueFactor // 倍率
const ModelId = ModelInfo.HandlerCode // 模型代码
const object = editor.getObjectById(ModelId)
const originInfo = editor.objectIdSet.get(ModelId)
if (!originInfo) return
const matrix = originInfo['matrix']
const originValue = type === 'rotation' ? originInfo[type]['_' + axis] : originInfo[type][axis]
const lastValue = originInfo['lastValue'] === null ? originValue : originInfo['lastValue']
const moveValue = flip * (parseFloat(tagValue) - Value) * ValueFactor
if (object) {
editor.solveAttachModel('', true)
const JointValue = originValue + moveValue
new TWEEN.Tween({
moveValue: lastValue
}).to({ moveValue: JointValue }, 100)
.onStart(function() {
originInfo['lastValue'] = JointValue
})
.onUpdate(function() {
switch (type) {
case 'position':
object[type][axis] = this._object.moveValue
break
case 'rotation':
{
const moveAxis = {
x: new THREE.Vector3(1, 1, 1),
y: new THREE.Vector3(1, 1, 1),
z: new THREE.Vector3(1, 1, 1)
}
matrix.extractBasis(moveAxis.x, moveAxis.y, moveAxis.z)
const nM = new THREE.Matrix4()
nM.makeRotationAxis(moveAxis[axis], this._object.moveValue)
// nM.makeRotationAxis(moveAxis[axis], JointValue)
nM.multiply(matrix)
object.rotation.setFromRotationMatrix(nM)
object.updateWorldMatrix()
}
break
}
}).start()
editor.solveAttachModel('', false)
}
//
// if (object) {
// editor.solveAttachModel('', true)
// object[type][axis] = originValue + (ValueFactor * flip * parseFloat(tagValue) + Value)
// editor.solveAttachModel('', false)
// }
} catch (e) {
console.log('solveServoSignal错误')
}
}
/**
* 接受机器人类的数据
* @param ModelId
* @param JointData
* @constructor
*/
this.JointMoveTo = (ModelId, JointData = {}) => {
if (editor.robotList[ModelId]) {
const ModelList = editor.robotList[ModelId]
// if (window.updateRobotData) window.updateRobotData(ModelId, JointData)
// window.updateLabelInfoJoint(ModelId, JointData)
for (let i = 0; i < ModelList.length; i++) {
if (ModelList[i].ModelId === '') return
this.jointMoveToPromise(JointData, ModelList[i], i, ModelId)
}
}
}
this.jointMoveToPromise = (JointData, ModelListData, i, ModelId) => {
new Promise(resolve => {
const ModelIdJoint = ModelListData.ModelId
const object = ModelListData.object
const type = ModelListData.type
const axis = ModelListData.axis
const matrix = ModelListData.matrix
const flip = ModelListData.flip
const delta = parseFloat(ModelListData.delta)
const multiple = ModelListData.multiple
const originInfo = editor.objectIdSet.get(ModelIdJoint)
if (!originInfo) return
const originValue = type === 'rotation' ? originInfo[type]['_' + axis] : originInfo[type][axis]
const lastValue = ModelListData.lastValue === null ? originValue : ModelListData.lastValue
const moveValue = flip * (parseFloat(JointData['J' + (i + 1)]) - delta) * multiple
if (object) {
const JointValue = originValue + moveValue
new TWEEN.Tween({
moveValue: lastValue
}).to({ moveValue: JointValue }, 200)
.onStart(function() {
editor.robotList[ModelId][i]['lastValue'] = JointValue
})
.onUpdate(function() {
switch (type) {
case 'position':
object[type][axis] = this._object.moveValue
break
case 'rotation':
{
const moveAxis = {
x: new THREE.Vector3(1, 1, 1),
y: new THREE.Vector3(1, 1, 1),
z: new THREE.Vector3(1, 1, 1)
}
matrix.extractBasis(moveAxis.x, moveAxis.y, moveAxis.z)
const nM = new THREE.Matrix4()
nM.makeRotationAxis(moveAxis[axis], this._object.moveValue)
// nM.makeRotationAxis(moveAxis[axis], JointValue)
nM.multiply(matrix)
object.rotation.setFromRotationMatrix(nM)
object.updateWorldMatrix()
}
break
}
}).start()
}
})
}
this.getAxisValue = (axis, value) => {
return JSON.parse('{"' + axis + '":' + value + '}')
}
this.getAxisValue = (axis, value) => {
return JSON.parse('{"' + axis + '":' + value + '}')
}
this.showWeld = (ModelId, Welding) => {
// 徐工专用
if (ModelId === '46DDBCD8-D775-49A4-BB14-30015FF87595') editor.WeldLightVisible1 = !!parseInt(Welding)
if (ModelId === '1E96DED2-6EEF-469F-BFE6-8F52FB62C2B0') editor.WeldLightVisible2 = !!parseInt(Welding)
}
this.showCheckOk = (check) => {
// 徐工专用
if (parseInt(check)) {
editor.showTagList[3].title = '工件QY16KC, 检测OK'
} else {
editor.showTagList[3].title = '工件QY16KC'
}
}
/**
* 显示隐藏物体
* @param m_DeviceName
* @param isVisible
*/
this.visibleObjectToBS = (m_DeviceName, isVisible) => {
const currentModel = editor.getObjectById(m_DeviceName)
if (currentModel) {
currentModel.visible = !!parseInt(isVisible)
currentModel.traverse(res => {
res.visible = !!parseInt(isVisible)
})
currentModel.userData['visible'] = !!parseInt(isVisible)
}
}
/**
* 初始化获取TagValue
*/
this.getOriginTagValue = () => {
let msg = ''
let socketMsg = ''
const keyWord = 'B_C_DT_WebLoaded'
msg = 'DT|' + keyWord
socketMsg = editor.BSport + msg
const topic = editor.BSport.split('?')[2]
switch (editor.connectType) {
case 1:
editor.socket.send(socketMsg)
break
case 2:
editor.mqttClient.publish(topic, msg, 0, error => {
if (error) {
console.log('Publish error', error)
}
})
break
default:
break
}
}
/**
* 更新库存状态
* @param dataInfo
*/
this.drawWareHousePartOne = (dataInfo) => {
const scope = this
try {
const whInfo = JSON.parse(dataInfo)
for (const whStoreInfo of whInfo) {
const whStoreNum = whStoreInfo.Key // 库位号 唯一值
const whStoreState = whStoreInfo.Value // 立库状态
const whNum = whStoreNum.toString().substring(0, 4) // 立库号 1000一期立库 1003刀具库 1002三坐标测量库 1001机床线旁库
const currentStoreInfo = editor.WareHouse.get(whStoreNum)
if (currentStoreInfo) {
if (parseInt(whStoreState) === 0) {
// 0的时候直接移除库存
editor.removeObject(currentStoreInfo.object)
editor.WareHouse.delete(whStoreNum)
} else {
// 不一样的状态 更新
if (currentStoreInfo.whStoreState !== whStoreState) {
// 移除零件,更新库存信息信息
editor.removeObject(currentStoreInfo.object)
scope.updateStoreModel(whNum, whStoreNum, whStoreState)
currentStoreInfo.whStoreState = whStoreState
currentStoreInfo.object = null
}
}
} else {
editor.WareHouse.set(whStoreNum, {
whNum: whNum,
whStoreNum: whStoreNum,
whStoreState: whStoreState,
object: null
})
scope.updateStoreModel(whNum, whStoreNum, whStoreState)
}
}
} catch (e) {
console.log('库存解析错误')
}
}
/**
* 更新零件
* @param whNum
* @param whStoreNum
* @param whStoreState
*/
this.updateStoreModel = (whNum, whStoreNum, whStoreState) => {
try {
const basicPartModel = editor.WareHouseBasicModel.get('warehousepart' + whStoreState)
const basicWareHouseModelData = editor.WareHouseBasicModel.get('warehouse' + whNum)
if (basicPartModel && basicWareHouseModelData) {
const basicPartModelClone = basicPartModel.clone()
const basicPartModelPosition = basicWareHouseModelData[whStoreNum]
basicPartModelClone.position.copy(basicPartModelPosition.getWorldPosition(new THREE.Vector3()))
editor.scene.add(basicPartModelClone)
editor.WareHouse.get(whStoreNum).object = basicPartModelClone
}
} catch (e) {
console.log('库存模型解析错误')
}
}
}
export {
WebsocketMessageReceive
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,74 @@
import { WebsocketMessageReceive } from './WebSocketMessage.js'
function connect(editor) {
const host = 'ws://' + editor.ip + '//WebModule//websocket'
let timeout = null
const websocketMessageReceive = new WebsocketMessageReceive(editor)
// 尝试连接至服务器
try {
if ('WebSocket' in window) {
editor.socket = new WebSocket(host)
} else {
editor.showMessage('浏览器不支持WebSocket', 'error', 2000)
}
} catch (exception) {
editor.showMessage('与服务器断开连接', 'error', 2000)
return
}
// 连接成功
editor.socket.onopen = function() {
// 关闭timer
try {
clearInterval(timeout)
} catch (exception) {
console.log(exception)
}
const name = editor.opname
editor.socket.send('LIN,' + name)
editor.showMessage('加载完成,连接服务器成功!', 'success', 2000)
editor.isOk = true
websocketMessageReceive.getOriginTagValue()
// let a = 0
// setInterval(() => {
// a += 0.5
// const message = `DT|JointMoveTo|0f26fc6e-1caf-4f57-beb3-d8a65872fbdd|{"J1":"${a}","J2":"0","J3":"0","J4":"0","J5":"0","J6":"0","J7":"0","J8":"0","J9":"0","J10":"0","J11":"0","J12":"0"}`
// websocketMessageReceive.websocketMessage({ data: message })
// }, 10)
}
// 收到消息
editor.socket.onmessage = function(msg) {
try {
websocketMessageReceive.websocketMessage(msg)
} catch (exception) {
const error = exception.toString()
console.log(error)
}
}
// 连接断开
editor.socket.onclose = function(event) {
try {
editor.showMessage('onclose' + '服务器连接失败', 'error', 2000)
editor.socket.close()
if (editor.IsAllowConnect) {
// 显示一下
editor.showMessage('重新连接服务器', 'warning', 2000)
console.log('onclose' + '重新连接服务器')
// 重新连接,打开计时器
timeout = setTimeout(function() {
connect(editor)
}, 5000)
}
} catch (exception) {
const error = exception.toString()
editor.showMessage.error('服务器出现错误,关闭连接' + error, 'error', 2000)
}
}
// 出现错误
editor.socket.onerror = function(event) {
console.log('onerror_' + '服务器连接失败')
editor.showMessage.error('服务器连接失败', 'error', 2000)
}
}
export { connect }

View File

@@ -0,0 +1,58 @@
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
const _changeEvent = { type: 'change' }
class DmtControl extends OrbitControls {
constructor(object, domElement) {
super(object, domElement)
const scope = this
const STATE = {
NONE: -1,
ROTATE: 0,
DOLLY: 1,
PAN: 2,
TOUCH_ROTATE: 3,
TOUCH_PAN: 4,
TOUCH_DOLLY_PAN: 5,
TOUCH_DOLLY_ROTATE: 6
}
// eslint-disable-next-line no-unused-vars
let state = STATE.NONE
this.resetState = function(target0, position0, zoom0) {
scope.target.copy(target0)
scope.object.position.copy(position0)
scope.object.zoom = zoom0
scope.object.updateProjectionMatrix()
scope.dispatchEvent(_changeEvent)
scope.update()
state = STATE.NONE
}
this.setLookAt = function(position0, target0, zoom0) {
scope.target.copy(target0)
scope.object.position.copy(position0)
scope.object.zoom = zoom0
scope.object.updateProjectionMatrix()
scope.dispatchEvent(_changeEvent)
scope.update()
state = STATE.NONE
}
this.moveTo = function(x, y, z) {
// scope.target.set(x, y, z)
}
this.getState = function() {
return {
target: scope.target.clone(),
position: scope.object.position.clone(),
zoom: parseFloat(scope.object.zoom.toString())
}
}
}
}
export {
DmtControl
}

View File

@@ -0,0 +1,536 @@
import * as THREE from 'three'
let viewCubeUpdate = null
const Viewer = function Viewer(editor) {
const ViewerDiv = document.createElement('div')
ViewerDiv.id = 'orientCubeWrapperDiv'
ViewerDiv.style.position = 'absolute'
ViewerDiv.style.left = '10px'
ViewerDiv.style.bottom = '10px'
ViewerDiv.style.display = 'flex'
ViewerDiv.style.backgroundColor = 'transparent'
ViewerDiv.style.width = '180px'
ViewerDiv.style.height = '180px'
ViewerDiv.style.zIndex = '999'
const ViewerUI = document.createElement('div')
ViewerUI.id = 'orientCubeWrapper'
ViewerUI.style.width = '180px'
ViewerUI.style.height = ' 180px'
ViewerUI.style.opacity = ' 0.7'
ViewerUI.style.transition = ' opacity 0.3s'
ViewerDiv.appendChild(ViewerUI)
document.body.appendChild(ViewerDiv)
const cubeCameraDistance = 5
const controlsViewer = editor.cameraControls
const cubeWrapper = ViewerUI
const cubeScene = new THREE.Scene()
const cubeRenderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true,
preserveDrawingBuffer: true
})
const cubeCamera = new THREE.PerspectiveCamera(50, cubeWrapper.offsetWidth / cubeWrapper.offsetHeight, 0.1, 100)
cubeRenderer.setSize(cubeWrapper.offsetWidth, cubeWrapper.offsetHeight)
cubeWrapper.appendChild(cubeRenderer.domElement)
cubeScene.add(cubeCamera)
cubeCamera.position.set(2, 2, 2)
createArrow(new THREE.Vector3(5, 0, 0), new THREE.Vector3(-5, -5, -5), 13, 0xFF0000, 'X')// x
createArrow(new THREE.Vector3(0, 0, 5), new THREE.Vector3(-5, -5, -5), 13, 0x0000FF, 'Z')// z
createArrow(new THREE.Vector3(0, 5, 0), new THREE.Vector3(-5, -5, -5), 13, 0x008000, 'Y')// y
cubeScene.add(new THREE.AmbientLight(0xffffff))
initModel()
let activeObject
cubeRenderer.domElement.onmousemove = (event) => {
const intersects = getIntersects(event)
if (intersects.length !== 0) {
const res = intersects.filter(function(res) {
return res && res.object.name !== '' && res.object instanceof THREE.Mesh
})[0]
if (res && res.object) {
if (activeObject) {
if (activeObject.name === res.object.name) {
activeObject.material.color.set('#6ad0f8')
return
} else {
activeObject.material.color.set('#00c0ff')
activeObject = null
}
}
activeObject = res.object
activeObject.material.color.set('#6ad0f8')
}
} else {
if (activeObject) {
activeObject.material.color.set('#00c0ff')
activeObject = null
}
}
}
cubeRenderer.domElement.onclick = () => {
if (!activeObject) return
const _position = editor.camera.position
const _target = editor.cameraControls.target
const _zoom = editor.camera.zoom
const Params = {
positionX: Math.abs(_position.x),
positionY: Math.abs(_position.y),
positionZ: Math.abs(_position.z),
positionXY: getTwoMax(_position.x, _position.y),
positionXZ: getTwoMax(_position.x, _position.z),
positionYZ: getTwoMax(_position.y, _position.z),
positionXYZ: getThreeMax(_position.x, _position.y, _position.z),
targetX: Math.abs(_target.x),
targetY: Math.abs(_target.y),
targetZ: Math.abs(_target.z),
targetXY: getTwoMax(_target.x, _target.y),
targetXZ: getTwoMax(_target.x, _target.z),
targetYZ: getTwoMax(_target.y, _target.z),
targetXYZ: getThreeMax(_target.x, _target.y, _target.z)
}
const dirAxis = {
'TOP': [0, 0, Params.positionZ,
0, 0, Params.targetZ,
_zoom],
'BOTTOM': [0, 0, -Params.positionZ,
0, 0, -Params.targetZ,
_zoom],
'FRONT': [Params.positionX, 0, 0,
Params.targetX, 0, 0,
_zoom],
'BACK': [-Params.positionX, 0, 0,
-Params.targetX, 0, 0,
_zoom],
'LEFT': [0, -Params.positionY, 0,
0, -Params.targetY, 0,
_zoom],
'RIGHT': [0, Params.positionY, 0,
0, Params.targetY, 0,
_zoom],
'BACK-LEFT': [-Params.positionXY, -Params.positionXY, 0,
-Params.targetXY, -Params.targetXY, 0,
_zoom],
'FRONT-LEFT': [Params.positionXY, -Params.positionXY, 0,
Params.targetXY, -Params.targetXY, 0,
_zoom],
'TOP-LEFT': [0, -Params.positionYZ, Params.positionYZ,
0, -Params.targetYZ, Params.targetYZ,
_zoom],
'TOP-RIGHT': [0, Params.positionYZ, Params.positionYZ,
0, Params.targetYZ, Params.targetYZ,
_zoom],
'RIGHT-BOTTOM': [0, Params.positionYZ, -Params.positionYZ,
0, Params.targetYZ, -Params.targetYZ,
_zoom],
'LEFT-BOTTOM': [0, -Params.positionYZ, -Params.positionYZ,
0, -Params.targetYZ, -Params.targetYZ,
_zoom],
'BACK-BOTTOM': [-Params.positionXZ, 0, -Params.positionXZ,
-Params.targetXZ, 0, -Params.targetXZ,
_zoom],
'TOP-FRONT': [Params.positionXZ, 0, Params.positionXZ,
Params.targetXZ, 0, Params.targetXZ,
_zoom],
'FRONT-BOTTOM': [Params.positionXZ, 0, -Params.positionXZ,
Params.targetXZ, 0, -Params.targetXZ,
_zoom],
'TOP-BACK': [-Params.positionXZ, 0, Params.positionXZ,
-Params.targetXZ, 0, Params.targetXZ,
_zoom],
'RIGHT-FRONT': [Params.positionXY, Params.positionXY, 0,
Params.targetXY, Params.targetXY, 0,
_zoom],
'BACK-RIGHT': [-Params.positionXY, Params.positionXY, 0,
-Params.targetXY, Params.targetXY, 0,
_zoom],
'BACK-RIGHT-BOTTOM': [-Params.positionXYZ, Params.positionXYZ, -Params.positionXYZ,
-Params.targetXYZ, Params.targetXYZ, -Params.targetXYZ,
_zoom],
'TOP-RIGHT-BACK': [-Params.positionXYZ, Params.positionXYZ, Params.positionXYZ,
-Params.targetXYZ, Params.targetXYZ, Params.targetXYZ,
_zoom],
'TOP-LEFT-BACK': [-Params.positionXYZ, -Params.positionXYZ, Params.positionXYZ,
-Params.targetXYZ, -Params.targetXYZ, Params.targetXYZ,
_zoom],
'TOP-LEFT-FRONT': [Params.positionXYZ, -Params.positionXYZ, Params.positionXYZ,
Params.targetXYZ, -Params.targetXYZ, Params.targetXYZ,
_zoom],
'FRONT-BOTTOM-RIGHT': [Params.positionXYZ, Params.positionXYZ, -Params.positionXYZ,
Params.targetXYZ, Params.targetXYZ, -Params.targetXYZ,
_zoom],
'TOP-RIGHT-FRONT': [Params.positionXYZ, Params.positionXYZ, Params.positionXYZ,
Params.targetXYZ, Params.targetXYZ, Params.targetXYZ,
_zoom],
'BACK-BOTTOM-LEFT': [-Params.positionXYZ, -Params.positionXYZ, -Params.positionXYZ,
-Params.targetXYZ, -Params.targetXYZ, -Params.targetXYZ,
_zoom],
'FRONT-BOTTOM-LEFT': [Params.positionXYZ, -Params.positionXYZ, -Params.positionXYZ,
Params.targetXYZ, -Params.targetXYZ, -Params.targetXYZ,
_zoom]
}
if (activeObject.name && dirAxis[activeObject.name]) {
const position = new THREE.Vector3(dirAxis[activeObject.name][0], dirAxis[activeObject.name][1], dirAxis[activeObject.name][2])
const target = new THREE.Vector3(dirAxis[activeObject.name][3], dirAxis[activeObject.name][4], dirAxis[activeObject.name][5])
const zoom = dirAxis[activeObject.name][6]
editor.cameraControls.setLookAt(position, target, zoom)
// editor.cameraControls.setLookAt(dirAxis[activeObject.name][0],
// dirAxis[activeObject.name][1],
// dirAxis[activeObject.name][2],
// 0, 0, 0, true)
// editor.cameraControls.moveTo(editor.cameraControls._target.x, editor.cameraControls._target.y, editor.cameraControls._target.z, true)
editor.camera.updateProjectionMatrix()
editor.camera.clearViewOffset()
updateCubeCamera()
}
function getTwoMax(a, b) {
return Math.abs(a) > Math.abs(b) ? Math.abs(a) : Math.abs(b)
}
function getThreeMax(a, b, c) {
return Math.abs(a) > Math.abs(b) ? Math.abs(a) > Math.abs(c) ? Math.abs(a) : Math.abs(c) : Math.abs(b) > Math.abs(c) ? Math.abs(b) : Math.abs(c)
}
}
function updateCubeCamera() {
cubeRenderer.render(cubeScene, cubeCamera)
cubeCamera.rotation.copy(editor.camera.rotation)
const dir = editor.camera.position.clone().sub(controlsViewer.target).normalize()
dir.multiplyScalar(cubeCameraDistance)
cubeCamera.position.copy(dir.multiplyScalar(cubeCameraDistance))
}
viewCubeUpdate = updateCubeCamera
function createArrow(dir, origin, length = 1, color = '0xffff00', text = '') {
// normalize the direction vector (convert to vector of length 1)
dir.normalize()
const arrowHelper = new THREE.ArrowHelper(dir, origin, length, color)
cubeScene.add(arrowHelper)
}
function initModel() {
const cubeMaterialRIGHT = new THREE.MeshLambertMaterial({
color: 0x00c0ff,
opacity: 1,
map: new THREE.CanvasTexture(getTextCanvas('RIGHT')),
side: THREE.DoubleSide
})
const cubeMaterialLEFT = new THREE.MeshLambertMaterial({
color: 0x00c0ff,
opacity: 1,
map: new THREE.CanvasTexture(getTextCanvas('LEFT')), // BOTTOM
side: THREE.DoubleSide
})
const cubeMaterialFRONT = new THREE.MeshLambertMaterial({
color: 0x00c0ff,
opacity: 1,
map: new THREE.CanvasTexture(getTextCanvas('FRONT')),
side: THREE.DoubleSide
})
const cubeMaterialBACK = new THREE.MeshLambertMaterial({
color: 0x00c0ff,
opacity: 1,
map: new THREE.CanvasTexture(getTextCanvas('BACK')),
side: THREE.DoubleSide
})
const cubeMaterialBOTTOM = new THREE.MeshLambertMaterial({
color: 0x00c0ff,
opacity: 1,
map: new THREE.CanvasTexture(getTextCanvas('BOTTOM')),
side: THREE.DoubleSide
})
const cubeMaterialTOP = new THREE.MeshLambertMaterial({
color: 0x00c0ff,
opacity: 1,
map: new THREE.CanvasTexture(getTextCanvas('TOP')), // LEFT
side: THREE.DoubleSide
})
const cubeMaterial = new THREE.MeshLambertMaterial({
color: 0x00c0ff,
opacity: 1,
map: new THREE.CanvasTexture(getTextCanvas('')),
side: THREE.DoubleSide
})
const SphereA = new THREE.SphereGeometry(1, 32, 32, 0, 0.5 * Math.PI, 0, 0.5 * Math.PI)
const edgesSphereA = new THREE.EdgesGeometry(SphereA, 3)
const CylinderB = new THREE.CylinderGeometry(1, 1, 8, 64, 1, false, 0, 0.5 * Math.PI)
const edgesCylinderB = new THREE.EdgesGeometry(CylinderB, 3)
const cubeC = new THREE.BoxGeometry(7.99, 4.99, 7.99)
const CylinderD = new THREE.CylinderGeometry(1, 1, 8, 64, 1, false, 0, 0.5 * Math.PI)
const edgesCylinderD = new THREE.EdgesGeometry(CylinderD, 3)
const edgesMaterial = new THREE.LineBasicMaterial({
color: '#363636'
})
const cube1 = new THREE.Mesh(cubeC, cubeMaterialRIGHT)
cube1.position.y = 2.5
cube1.rotation.y = Math.PI
cube1.name = 'RIGHT'
cubeScene.add(cube1)
const cube2 = new THREE.Mesh(cubeC, cubeMaterialLEFT)// BOTTOM
cube2.position.y = -2.5
cube2.name = 'LEFT'
cubeScene.add(cube2)
const cube3 = new THREE.Mesh(cubeC, cubeMaterialFRONT)// BACK
cube3.position.x = 2.5
cube3.rotation.z = 0.5 * Math.PI
cube3.name = 'FRONT'
cubeScene.add(cube3)
const cube4 = new THREE.Mesh(cubeC, cubeMaterialTOP)// LEFT
cube4.position.z = 2.5
cube4.rotation.x = 0.5 * Math.PI
cube4.name = 'TOP'
cubeScene.add(cube4)
const cube5 = new THREE.Mesh(cubeC, cubeMaterialBACK)// FRONT
cube5.position.x = -2.5
cube5.rotation.z = 0.5 * Math.PI
cube5.rotation.x = -Math.PI
cube5.name = 'BACK'
cubeScene.add(cube5)
const cube6 = new THREE.Mesh(cubeC, cubeMaterialBOTTOM)
cube6.position.z = -2.5
cube6.rotation.x = -0.5 * Math.PI
cube6.name = 'BOTTOM'
cubeScene.add(cube6)
const cube7 = new THREE.Mesh(CylinderB, cubeMaterial.clone())
cube7.position.x = 4
cube7.position.z = 4
cube7.name = 'TOP-FRONT'
const line7 = new THREE.LineSegments(edgesCylinderB, edgesMaterial)
cube7.add(line7)
cubeScene.add(cube7)
const cube8 = new THREE.Mesh(CylinderB, cubeMaterial.clone())
cube8.position.x = -4
cube8.position.z = -4
cube8.rotation.y = Math.PI
cube8.name = 'BACK-BOTTOM'
const line8 = new THREE.LineSegments(edgesCylinderB, edgesMaterial)
cube8.add(line8)
cubeScene.add(cube8)
const cube9 = new THREE.Mesh(CylinderB, cubeMaterial.clone())
cube9.position.x = 4
cube9.position.z = -4
cube9.rotation.y = 0.5 * Math.PI
cube9.name = 'FRONT-BOTTOM'
const line9 = new THREE.LineSegments(edgesCylinderB, edgesMaterial)
cube9.add(line9)
cubeScene.add(cube9)
const cube10 = new THREE.Mesh(CylinderB, cubeMaterial.clone())
cube10.position.x = -4
cube10.position.z = 4
cube10.rotation.y = -0.5 * Math.PI
cube10.name = 'TOP-BACK'
const line10 = new THREE.LineSegments(edgesCylinderB, edgesMaterial)
cube10.add(line10)
cubeScene.add(cube10)
const cube11 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
cube11.position.x = 4
cube11.position.y = 4
cube11.rotation.z = 0.5 * Math.PI
cube11.rotation.y = 0.5 * Math.PI
cube11.name = 'RIGHT-FRONT'
const line11 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
cube11.add(line11)
cubeScene.add(cube11)
const cube12 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
cube12.position.x = -4
cube12.position.y = 4
cube12.rotation.z = 0.5 * Math.PI
cube12.rotation.y = -0.5 * Math.PI
cube12.name = 'BACK-RIGHT'
const line12 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
cube12.add(line12)
cubeScene.add(cube12)
const cube13 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
cube13.position.x = -4
cube13.position.y = -4
cube13.rotation.z = -0.5 * Math.PI
cube13.rotation.y = -0.5 * Math.PI
cube13.name = 'BACK-LEFT'
const line13 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
cube13.add(line13)
cubeScene.add(cube13)
const cube14 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
cube14.position.x = 4
cube14.position.y = -4
cube14.rotation.z = -0.5 * Math.PI
cube14.rotation.y = 0.5 * Math.PI
cube14.name = 'FRONT-LEFT'
const line14 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
cube14.add(line14)
cubeScene.add(cube14)
const cube15 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
cube15.position.z = 4
cube15.position.y = 4
cube15.rotation.x = -0.5 * Math.PI
cube15.rotation.z = -0.5 * Math.PI
cube15.name = 'TOP-RIGHT'
const line15 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
cube15.add(line15)
cubeScene.add(cube15)
const cube16 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
cube16.position.z = -4
cube16.position.y = 4
cube16.rotation.x = -0.5 * Math.PI
cube16.rotation.z = 0.5 * Math.PI
cube16.name = 'RIGHT-BOTTOM'
const line16 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
cube16.add(line16)
cubeScene.add(cube16)
const cube17 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
cube17.position.z = -4
cube17.position.y = -4
cube17.rotation.z = -0.5 * Math.PI
cube17.rotation.x = 0.5 * Math.PI
cube17.name = 'LEFT-BOTTOM'
const line17 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
cube17.add(line17)
cubeScene.add(cube17)
const cube18 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
cube18.position.z = 4
cube18.position.y = -4
cube18.rotation.z = -0.5 * Math.PI
cube18.name = 'TOP-LEFT'
const line18 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
cube18.add(line18)
cubeScene.add(cube18)
const cube19 = new THREE.Mesh(SphereA, cubeMaterial.clone())
cube19.position.x = 4
cube19.position.y = 4
cube19.position.z = 4
cube19.rotation.z = -0.5 * Math.PI
cube19.name = 'TOP-RIGHT-FRONT'
const line19 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
cube19.add(line19)
cubeScene.add(cube19)
const cube20 = new THREE.Mesh(SphereA, cubeMaterial.clone())
cube20.position.x = 4
cube20.position.y = 4
cube20.position.z = -4
cube20.rotation.z = -0.5 * Math.PI
cube20.rotation.y = 0.5 * Math.PI
cube20.name = 'FRONT-BOTTOM-RIGHT'
const line20 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
cube20.add(line20)
cubeScene.add(cube20)
const cube21 = new THREE.Mesh(SphereA, cubeMaterial.clone())
cube21.position.x = -4
cube21.position.y = 4
cube21.position.z = -4
cube21.rotation.y = -0.5 * Math.PI
cube21.name = 'BACK-RIGHT-BOTTOM'
const line21 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
cube21.add(line21)
cubeScene.add(cube21)
const cube22 = new THREE.Mesh(SphereA, cubeMaterial.clone())
cube22.position.x = -4
cube22.position.y = 4
cube22.position.z = 4
cube22.name = 'TOP-RIGHT-BACK'
const line22 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
cube22.add(line22)
cubeScene.add(cube22)
const cube23 = new THREE.Mesh(SphereA, cubeMaterial.clone())
cube23.position.x = -4
cube23.position.y = -4
cube23.position.z = -4
cube23.rotation.y = -0.5 * Math.PI
cube23.rotation.x = -0.5 * Math.PI
cube23.name = 'BACK-BOTTOM-LEFT'
const line23 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
cube23.add(line23)
cubeScene.add(cube23)
const cube24 = new THREE.Mesh(SphereA, cubeMaterial.clone())
cube24.position.x = 4
cube24.position.y = -4
cube24.position.z = -4
cube24.rotation.y = Math.PI
cube24.rotation.x = -0.5 * Math.PI
cube24.name = 'FRONT-BOTTOM-LEFT'
const line24 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
cube24.add(line24)
cubeScene.add(cube24)
const cube25 = new THREE.Mesh(SphereA, cubeMaterial.clone())
cube25.position.x = 4
cube25.position.y = -4
cube25.position.z = 4
cube25.rotation.y = 0.5 * Math.PI
cube25.rotation.x = 0.5 * Math.PI
cube25.name = 'TOP-LEFT-FRONT'
const line25 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
cube25.add(line25)
cubeScene.add(cube25)
const cube26 = new THREE.Mesh(SphereA, cubeMaterial.clone())
cube26.position.x = -4
cube26.position.y = -4
cube26.position.z = 4
cube26.rotation.x = 0.5 * Math.PI
cube26.name = 'TOP-LEFT-BACK'
const line26 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
cube26.add(line26)
cubeScene.add(cube26)
}
function getTextCanvas(text) {
const width = 64
const height = 64
const canvas = document.createElement('canvas')
canvas.width = width
canvas.height = height
const ctx = canvas.getContext('2d')
ctx.fillStyle = '#8d8d8d'
ctx.fillRect(0, 0, width, height)
ctx.font = 'bolder 14px "Open sans", Arial'
ctx.fillStyle = '#000000'
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.fillText(text, width / 2, height / 2)
return canvas
}
function getIntersects(event) {
event.preventDefault()
// 声明 raycaster 和 mouse 变量
const raycaster = new THREE.Raycaster()
// 通过鼠标点击位置,计算出 raycaster 所需点的位置,以屏幕为中心点,范围 -1 到 1
const x = event.offsetX
const y = event.offsetY
const size = cubeRenderer.getSize(new THREE.Vector2())
const mouse = new THREE.Vector2(x / size.width * 2 - 1, -y / size.height * 2 + 1)
raycaster.setFromCamera(mouse, cubeCamera)
// 获取与射线相交的对象数组,其中的元素按照距离排序,越近的越靠前
return raycaster.intersectObjects(cubeScene.children)
}
}
export { viewCubeUpdate, Viewer }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,452 @@
import * as THREE from 'three'
let viewCubeUpdate = null
const Viewer = function Viewer(editor) {
const cameraPosition = editor.cameraPosition
const ViewerDiv = document.createElement('div')
ViewerDiv.id = 'orientCubeWrapperDiv'
ViewerDiv.style.position = 'absolute'
ViewerDiv.style.left = '10px'
ViewerDiv.style.bottom = '10px'
ViewerDiv.style.display = 'flex'
ViewerDiv.style.backgroundColor = 'transparent'
ViewerDiv.style.width = '180px'
ViewerDiv.style.height = '180px'
ViewerDiv.style.zIndex = '999'
const ViewerUI = document.createElement('div')
ViewerUI.id = 'orientCubeWrapper'
ViewerUI.style.width = '180px'
ViewerUI.style.height = ' 180px'
ViewerUI.style.opacity = ' 0.7'
ViewerUI.style.transition = ' opacity 0.3s'
ViewerDiv.appendChild(ViewerUI)
document.body.appendChild(ViewerDiv)
const dirAxis = {
'TOP': [0, 0, editor.cameraPosition, 0, 0, 0],
'BOTTOM': [0, 0, -editor.cameraPosition, 0, 0, 0],
'FRONT': [editor.cameraPosition, 0, 0, 0, 0, 0],
'BACK': [-editor.cameraPosition, 0, 0, 0, 0, 0],
'LEFT': [0, -editor.cameraPosition, 0, 0, 0, 0],
'RIGHT': [0, editor.cameraPosition, 0, 0, 0, 0],
'BACK-LEFT': [-editor.cameraPosition, -editor.cameraPosition, 0, 0, 0, 0],
'FRONT-LEFT': [editor.cameraPosition, -editor.cameraPosition, 0, 0, 0, 0],
'TOP-LEFT': [0, -editor.cameraPosition, editor.cameraPosition, 0, 0, 0],
'TOP-RIGHT': [0, editor.cameraPosition, editor.cameraPosition, 0, 0, 0],
'RIGHT-BOTTOM': [0, editor.cameraPosition, -editor.cameraPosition, 0, 0, 0],
'LEFT-BOTTOM': [0, -editor.cameraPosition, -editor.cameraPosition, 0, 0, 0],
'BACK-BOTTOM': [-editor.cameraPosition, 0, -editor.cameraPosition, 0, 0, 0],
'TOP-FRONT': [editor.cameraPosition, 0, editor.cameraPosition, 0, 0, 0], //
'FRONT-BOTTOM': [editor.cameraPosition, 0, -editor.cameraPosition, 0, 0, 0],
'TOP-BACK': [-editor.cameraPosition, 0, editor.cameraPosition, 0, 0, 0],
'RIGHT-FRONT': [editor.cameraPosition, editor.cameraPosition, 0, 0, 0, 0],
'BACK-RIGHT': [-editor.cameraPosition, editor.cameraPosition, 0, 0, 0, 0],
'BACK-RIGHT-BOTTOM': [-editor.cameraPosition, editor.cameraPosition, -cameraPosition, 0, 0, 0],
'TOP-RIGHT-BACK': [-editor.cameraPosition, editor.cameraPosition, editor.cameraPosition, 0, 0, 0],
'TOP-LEFT-BACK': [-editor.cameraPosition, -editor.cameraPosition, editor.cameraPosition, 0, 0, 0],
'TOP-LEFT-FRONT': [editor.cameraPosition, -editor.cameraPosition, editor.cameraPosition, 0, 0, 0],
'FRONT-BOTTOM-RIGHT': [editor.cameraPosition, editor.cameraPosition, -editor.cameraPosition, 0, 0, 0],
'TOP-RIGHT-FRONT': [editor.cameraPosition, editor.cameraPosition, editor.cameraPosition, 0, 0, 0],
'BACK-BOTTOM-LEFT': [-editor.cameraPosition, -editor.cameraPosition, -editor.cameraPosition, 0, 0, 0],
'FRONT-BOTTOM-LEFT': [editor.cameraPosition, -editor.cameraPosition, -editor.cameraPosition, 0, 0, 0]
}
const cubeCameraDistance = 5
const controlsViewer = editor.cameraControls
const cubeWrapper = ViewerUI
const cubeScene = new THREE.Scene()
const cubeRenderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true,
preserveDrawingBuffer: true
})
const cubeCamera = new THREE.PerspectiveCamera(50, cubeWrapper.offsetWidth / cubeWrapper.offsetHeight, 0.1, 100)
cubeRenderer.setSize(cubeWrapper.offsetWidth, cubeWrapper.offsetHeight)
cubeWrapper.appendChild(cubeRenderer.domElement)
cubeScene.add(cubeCamera)
cubeCamera.position.set(2, 2, 2)
createArrow(new THREE.Vector3(5, 0, 0), new THREE.Vector3(-5, -5, -5), 13, 0xFF0000, 'X')// x
createArrow(new THREE.Vector3(0, 0, 5), new THREE.Vector3(-5, -5, -5), 13, 0x0000FF, 'Z')// z
createArrow(new THREE.Vector3(0, 5, 0), new THREE.Vector3(-5, -5, -5), 13, 0x008000, 'Y')// y
cubeScene.add(new THREE.AmbientLight(0xffffff))
initModel()
let activeObject
cubeRenderer.domElement.onmousemove = (event) => {
const intersects = getIntersects(event)
if (intersects.length !== 0) {
const res = intersects.filter(function(res) {
return res && res.object.name !== '' && res.object instanceof THREE.Mesh
})[0]
if (res && res.object) {
if (activeObject) {
if (activeObject.name === res.object.name) {
activeObject.material.color.set('#6ad0f8')
return
} else {
activeObject.material.color.set('#00c0ff')
activeObject = null
}
}
activeObject = res.object
activeObject.material.color.set('#6ad0f8')
}
} else {
if (activeObject) {
activeObject.material.color.set('#00c0ff')
activeObject = null
}
}
}
cubeRenderer.domElement.onclick = () => {
if (!activeObject) return
if (activeObject.name && dirAxis[activeObject.name]) {
editor.cameraControls.setLookAt(dirAxis[activeObject.name][0],
dirAxis[activeObject.name][1],
dirAxis[activeObject.name][2],
0, 0, 0, true)
editor.cameraControls.moveTo(editor.cameraControls._target.x, editor.cameraControls._target.y, editor.cameraControls._target.z, true)
editor.camera.updateProjectionMatrix()
editor.camera.clearViewOffset()
updateCubeCamera()
}
}
function updateCubeCamera() {
cubeRenderer.render(cubeScene, cubeCamera)
cubeCamera.rotation.copy(editor.camera.rotation)
const dir = editor.camera.position.clone().sub(controlsViewer._target).normalize()
dir.multiplyScalar(cubeCameraDistance)
cubeCamera.position.copy(dir.multiplyScalar(cubeCameraDistance))
}
viewCubeUpdate = updateCubeCamera
function createArrow(dir, origin, length = 1, color = '0xffff00', text = '') {
// normalize the direction vector (convert to vector of length 1)
dir.normalize()
const arrowHelper = new THREE.ArrowHelper(dir, origin, length, color)
cubeScene.add(arrowHelper)
}
function initModel() {
const cubeMaterialRIGHT = new THREE.MeshLambertMaterial({
color: 0x00c0ff,
opacity: 1,
map: new THREE.CanvasTexture(getTextCanvas('RIGHT')),
side: THREE.DoubleSide
})
const cubeMaterialLEFT = new THREE.MeshLambertMaterial({
color: 0x00c0ff,
opacity: 1,
map: new THREE.CanvasTexture(getTextCanvas('LEFT')), // BOTTOM
side: THREE.DoubleSide
})
const cubeMaterialFRONT = new THREE.MeshLambertMaterial({
color: 0x00c0ff,
opacity: 1,
map: new THREE.CanvasTexture(getTextCanvas('FRONT')),
side: THREE.DoubleSide
})
const cubeMaterialBACK = new THREE.MeshLambertMaterial({
color: 0x00c0ff,
opacity: 1,
map: new THREE.CanvasTexture(getTextCanvas('BACK')),
side: THREE.DoubleSide
})
const cubeMaterialBOTTOM = new THREE.MeshLambertMaterial({
color: 0x00c0ff,
opacity: 1,
map: new THREE.CanvasTexture(getTextCanvas('BOTTOM')),
side: THREE.DoubleSide
})
const cubeMaterialTOP = new THREE.MeshLambertMaterial({
color: 0x00c0ff,
opacity: 1,
map: new THREE.CanvasTexture(getTextCanvas('TOP')), // LEFT
side: THREE.DoubleSide
})
const cubeMaterial = new THREE.MeshLambertMaterial({
color: 0x00c0ff,
opacity: 1,
map: new THREE.CanvasTexture(getTextCanvas('')),
side: THREE.DoubleSide
})
const SphereA = new THREE.SphereGeometry(1, 32, 32, 0, 0.5 * Math.PI, 0, 0.5 * Math.PI)
const edgesSphereA = new THREE.EdgesGeometry(SphereA, 3)
const CylinderB = new THREE.CylinderGeometry(1, 1, 8, 64, 1, false, 0, 0.5 * Math.PI)
const edgesCylinderB = new THREE.EdgesGeometry(CylinderB, 3)
const cubeC = new THREE.BoxGeometry(7.99, 4.99, 7.99)
const CylinderD = new THREE.CylinderGeometry(1, 1, 8, 64, 1, false, 0, 0.5 * Math.PI)
const edgesCylinderD = new THREE.EdgesGeometry(CylinderD, 3)
const edgesMaterial = new THREE.LineBasicMaterial({
color: '#363636'
})
const cube1 = new THREE.Mesh(cubeC, cubeMaterialRIGHT)
cube1.position.y = 2.5
cube1.rotation.y = Math.PI
cube1.name = 'RIGHT'
cubeScene.add(cube1)
const cube2 = new THREE.Mesh(cubeC, cubeMaterialLEFT)// BOTTOM
cube2.position.y = -2.5
cube2.name = 'LEFT'
cubeScene.add(cube2)
const cube3 = new THREE.Mesh(cubeC, cubeMaterialFRONT)// BACK
cube3.position.x = 2.5
cube3.rotation.z = 0.5 * Math.PI
cube3.name = 'FRONT'
cubeScene.add(cube3)
const cube4 = new THREE.Mesh(cubeC, cubeMaterialTOP)// LEFT
cube4.position.z = 2.5
cube4.rotation.x = 0.5 * Math.PI
cube4.name = 'TOP'
cubeScene.add(cube4)
const cube5 = new THREE.Mesh(cubeC, cubeMaterialBACK)// FRONT
cube5.position.x = -2.5
cube5.rotation.z = 0.5 * Math.PI
cube5.rotation.x = -Math.PI
cube5.name = 'BACK'
cubeScene.add(cube5)
const cube6 = new THREE.Mesh(cubeC, cubeMaterialBOTTOM)
cube6.position.z = -2.5
cube6.rotation.x = -0.5 * Math.PI
cube6.name = 'BOTTOM'
cubeScene.add(cube6)
const cube7 = new THREE.Mesh(CylinderB, cubeMaterial.clone())
cube7.position.x = 4
cube7.position.z = 4
cube7.name = 'TOP-FRONT'
const line7 = new THREE.LineSegments(edgesCylinderB, edgesMaterial)
cube7.add(line7)
cubeScene.add(cube7)
const cube8 = new THREE.Mesh(CylinderB, cubeMaterial.clone())
cube8.position.x = -4
cube8.position.z = -4
cube8.rotation.y = Math.PI
cube8.name = 'BACK-BOTTOM'
const line8 = new THREE.LineSegments(edgesCylinderB, edgesMaterial)
cube8.add(line8)
cubeScene.add(cube8)
const cube9 = new THREE.Mesh(CylinderB, cubeMaterial.clone())
cube9.position.x = 4
cube9.position.z = -4
cube9.rotation.y = 0.5 * Math.PI
cube9.name = 'FRONT-BOTTOM'
const line9 = new THREE.LineSegments(edgesCylinderB, edgesMaterial)
cube9.add(line9)
cubeScene.add(cube9)
const cube10 = new THREE.Mesh(CylinderB, cubeMaterial.clone())
cube10.position.x = -4
cube10.position.z = 4
cube10.rotation.y = -0.5 * Math.PI
cube10.name = 'TOP-BACK'
const line10 = new THREE.LineSegments(edgesCylinderB, edgesMaterial)
cube10.add(line10)
cubeScene.add(cube10)
const cube11 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
cube11.position.x = 4
cube11.position.y = 4
cube11.rotation.z = 0.5 * Math.PI
cube11.rotation.y = 0.5 * Math.PI
cube11.name = 'RIGHT-FRONT'
const line11 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
cube11.add(line11)
cubeScene.add(cube11)
const cube12 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
cube12.position.x = -4
cube12.position.y = 4
cube12.rotation.z = 0.5 * Math.PI
cube12.rotation.y = -0.5 * Math.PI
cube12.name = 'BACK-RIGHT'
const line12 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
cube12.add(line12)
cubeScene.add(cube12)
const cube13 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
cube13.position.x = -4
cube13.position.y = -4
cube13.rotation.z = -0.5 * Math.PI
cube13.rotation.y = -0.5 * Math.PI
cube13.name = 'BACK-LEFT'
const line13 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
cube13.add(line13)
cubeScene.add(cube13)
const cube14 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
cube14.position.x = 4
cube14.position.y = -4
cube14.rotation.z = -0.5 * Math.PI
cube14.rotation.y = 0.5 * Math.PI
cube14.name = 'FRONT-LEFT'
const line14 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
cube14.add(line14)
cubeScene.add(cube14)
const cube15 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
cube15.position.z = 4
cube15.position.y = 4
cube15.rotation.x = -0.5 * Math.PI
cube15.rotation.z = -0.5 * Math.PI
cube15.name = 'TOP-RIGHT'
const line15 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
cube15.add(line15)
cubeScene.add(cube15)
const cube16 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
cube16.position.z = -4
cube16.position.y = 4
cube16.rotation.x = -0.5 * Math.PI
cube16.rotation.z = 0.5 * Math.PI
cube16.name = 'RIGHT-BOTTOM'
const line16 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
cube16.add(line16)
cubeScene.add(cube16)
const cube17 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
cube17.position.z = -4
cube17.position.y = -4
cube17.rotation.z = -0.5 * Math.PI
cube17.rotation.x = 0.5 * Math.PI
cube17.name = 'LEFT-BOTTOM'
const line17 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
cube17.add(line17)
cubeScene.add(cube17)
const cube18 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
cube18.position.z = 4
cube18.position.y = -4
cube18.rotation.z = -0.5 * Math.PI
cube18.name = 'TOP-LEFT'
const line18 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
cube18.add(line18)
cubeScene.add(cube18)
const cube19 = new THREE.Mesh(SphereA, cubeMaterial.clone())
cube19.position.x = 4
cube19.position.y = 4
cube19.position.z = 4
cube19.rotation.z = -0.5 * Math.PI
cube19.name = 'TOP-RIGHT-FRONT'
const line19 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
cube19.add(line19)
cubeScene.add(cube19)
const cube20 = new THREE.Mesh(SphereA, cubeMaterial.clone())
cube20.position.x = 4
cube20.position.y = 4
cube20.position.z = -4
cube20.rotation.z = -0.5 * Math.PI
cube20.rotation.y = 0.5 * Math.PI
cube20.name = 'FRONT-BOTTOM-RIGHT'
const line20 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
cube20.add(line20)
cubeScene.add(cube20)
const cube21 = new THREE.Mesh(SphereA, cubeMaterial.clone())
cube21.position.x = -4
cube21.position.y = 4
cube21.position.z = -4
cube21.rotation.y = -0.5 * Math.PI
cube21.name = 'BACK-RIGHT-BOTTOM'
const line21 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
cube21.add(line21)
cubeScene.add(cube21)
const cube22 = new THREE.Mesh(SphereA, cubeMaterial.clone())
cube22.position.x = -4
cube22.position.y = 4
cube22.position.z = 4
cube22.name = 'TOP-RIGHT-BACK'
const line22 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
cube22.add(line22)
cubeScene.add(cube22)
const cube23 = new THREE.Mesh(SphereA, cubeMaterial.clone())
cube23.position.x = -4
cube23.position.y = -4
cube23.position.z = -4
cube23.rotation.y = -0.5 * Math.PI
cube23.rotation.x = -0.5 * Math.PI
cube23.name = 'BACK-BOTTOM-LEFT'
const line23 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
cube23.add(line23)
cubeScene.add(cube23)
const cube24 = new THREE.Mesh(SphereA, cubeMaterial.clone())
cube24.position.x = 4
cube24.position.y = -4
cube24.position.z = -4
cube24.rotation.y = Math.PI
cube24.rotation.x = -0.5 * Math.PI
cube24.name = 'FRONT-BOTTOM-LEFT'
const line24 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
cube24.add(line24)
cubeScene.add(cube24)
const cube25 = new THREE.Mesh(SphereA, cubeMaterial.clone())
cube25.position.x = 4
cube25.position.y = -4
cube25.position.z = 4
cube25.rotation.y = 0.5 * Math.PI
cube25.rotation.x = 0.5 * Math.PI
cube25.name = 'TOP-LEFT-FRONT'
const line25 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
cube25.add(line25)
cubeScene.add(cube25)
const cube26 = new THREE.Mesh(SphereA, cubeMaterial.clone())
cube26.position.x = -4
cube26.position.y = -4
cube26.position.z = 4
cube26.rotation.x = 0.5 * Math.PI
cube26.name = 'TOP-LEFT-BACK'
const line26 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
cube26.add(line26)
cubeScene.add(cube26)
}
function getTextCanvas(text) {
const width = 64
const height = 64
const canvas = document.createElement('canvas')
canvas.width = width
canvas.height = height
const ctx = canvas.getContext('2d')
ctx.fillStyle = '#8d8d8d'
ctx.fillRect(0, 0, width, height)
ctx.font = 'bolder 14px "Open sans", Arial'
ctx.fillStyle = '#000000'
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.fillText(text, width / 2, height / 2)
return canvas
}
function getIntersects(event) {
event.preventDefault()
// 声明 raycaster 和 mouse 变量
const raycaster = new THREE.Raycaster()
// 通过鼠标点击位置,计算出 raycaster 所需点的位置,以屏幕为中心点,范围 -1 到 1
const x = event.offsetX
const y = event.offsetY
const size = cubeRenderer.getSize(new THREE.Vector2())
const mouse = new THREE.Vector2(x / size.width * 2 - 1, -y / size.height * 2 + 1)
raycaster.setFromCamera(mouse, cubeCamera)
// 获取与射线相交的对象数组,其中的元素按照距离排序,越近的越靠前
return raycaster.intersectObjects(cubeScene.children)
}
}
export { viewCubeUpdate, Viewer }

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -0,0 +1,32 @@
# Draco 3D Data Compression
Draco is an open-source library for compressing and decompressing 3D geometric meshes and point clouds. It is intended to improve the storage and transmission of 3D graphics.
[Website](https://google.github.io/draco/) | [GitHub](https://github.com/google/draco)
## Contents
This folder contains three utilities:
* `draco_decoder.js` — Emscripten-compiled decoder, compatible with any modern browser.
* `draco_decoder.wasm` — WebAssembly decoder, compatible with newer browsers and devices.
* `draco_wasm_wrapper.js` — JavaScript wrapper for the WASM decoder.
Each file is provided in two variations:
* **Default:** Latest stable builds, tracking the project's [master branch](https://github.com/google/draco).
* **glTF:** Builds targeted by the [glTF mesh compression extension](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression), tracking the [corresponding Draco branch](https://github.com/google/draco/tree/gltf_2.0_draco_extension).
Either variation may be used with `THREE.DRACOLoader`:
```js
var dracoLoader = new THREE.DRACOLoader();
dracoLoader.setDecoderPath('path/to/decoders/');
dracoLoader.setDecoderConfig({type: 'js'}); // (Optional) Override detection of WASM support.
```
Further [documentation on GitHub](https://github.com/google/draco/tree/master/javascript/example#static-loading-javascript-decoder).
## License
[Apache License 2.0](https://github.com/google/draco/blob/master/LICENSE)

File diff suppressed because one or more lines are too long

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More