案例展示
模型剖切效果
<template>
<div class="vp-px2vw">
<div class="demo-wrap">
<div id="TO"></div>
<div id="formContainer">
<ClipModelForm
:model-options="modelNames"
:clip-min="clipMin"
:clip-max="clipMax"
@request-clip-range="handleRequestClipRange"
@apply-clip="handleApplyClip" />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import ClipModelForm, { type ClipApplyPayload, type ClipRangeRequestPayload } from './ClipModelForm.vue'
// @ts-ignore
declare const ThingOrigin: any
const clipMin = ref(65)
const clipMax = ref(89.5)
let TO: any = null
let currentClipModel: any = null
const modelList = [
{
id: 3017,
modelName: 'agv-2', //模型名称
base: {
modelUrl: 'https://124.70.30.193:8443/model2/loadFileAsId/613112990' //模型地址
},
modelType: 'gltf', //模型类型
scale: {
//缩放大小
x: 1.8,
y: 1.8,
z: 1.8
},
rotation: {
//旋转
x: 0,
y: 1.5708,
z: 0
},
position: {
//位置
x: 76.90687943165758,
y: 0,
z: 19.922502148523417 //z轴位置
}
},
{
modelType: 'gltf',
modelName: '非皮带传送带-2',
id: 3021,
position: {
x: 40.90687943165758,
y: 0,
z: 19.922502148523417
},
base: {
modelUrl: 'https://124.70.30.193:8443/model2/loadFileAsId/258642254'
}
},
{
modelType: 'gltf',
modelName: '数字机床-1',
id: 3014,
position: {
x: 46,
y: 0,
z: -4
},
rotation: {
x: 3.14,
y: 0,
z: 3.14
},
base: {
modelUrl: 'https://124.70.30.193:8443/model2/loadFileAsId/878966042'
}
}
]
const modelNames = computed(() => modelList.map((item) => item.modelName))
onMounted(() => {
// 初始化场景
TO = new ThingOrigin(
'fileModel',
document.getElementById('TO'),
{
camera: {
lookAt: {
x: 68.99587428883535,
y: -8.087862389988479,
z: -62.550695464478885
},
position: {
x: 61.850059653907124,
y: 66.73228864442682,
z: 126.91101302956017
}
},
modelList: modelList
},
() => {
console.log('场景初始化完成')
}
)
})
// 应用剖切效果
function applyClip(modelScene: any, axis: 'x' | 'y' | 'z', constant: number) {
// 清除旧的剖切
deleteClip()
// 创建新的剖切
currentClipModel = modelScene
TO.effect.initModelClip(modelScene, [
{
axis,
constant
}
])
}
// 删除剖切
function deleteClip() {
if (currentClipModel) {
TO.effect.deleteModelClip()
}
}
// 计算模型的边界框范围
function calculateModelBounds(model: any, axis: 'x' | 'y' | 'z'): { min: number; max: number } {
if (!model) {
return { min: -10, max: 10 }
}
// 获取模型包围盒
const box = TO.tool.getModelBox(model)
return {
min: box.min[axis],
max: box.max[axis]
}
}
function updateClipRange(modelName: string, axis: 'x' | 'y' | 'z') {
if (!TO) return
const model = TO.scene.getObjectByName(modelName)
if (model) {
const bounds = calculateModelBounds(model, axis)
clipMin.value = bounds.min
clipMax.value = bounds.max
}
}
function handleRequestClipRange(payload: ClipRangeRequestPayload) {
updateClipRange(payload.modelName, payload.axis)
}
function handleApplyClip(payload: ClipApplyPayload) {
if (!TO) return
const model = TO.scene.getObjectByName(payload.modelName)
if (model) {
const clampedPosition = Math.max(clipMin.value, Math.min(clipMax.value, payload.position))
applyClip(model, payload.axis, clampedPosition)
}
}
</script>
<style scoped lang="scss">
.vp-px2vw {
.demo-wrap {
position: relative;
}
#TO {
width: 100%;
height: 400px;
position: relative;
}
#formContainer {
position: absolute;
top: 10px;
right: 10px;
font-size: 14px;
}
}
</style>API 介绍
effect.initModelClip
| 方法签名 | 返回值 | 描述 |
|---|---|---|
initModelClip(model: Object3D, options: Array<any>) | void | 模型剖切 |
参数说明:
| 参数名 | 说明 | 类型 | 必填 | 默认值 |
|---|---|---|---|---|
model | 被剖切的模型 | Object3D | 是 | - |
options | 剖切参数(如 [{axis:'x', constant:0}]) | Array<any> | 是 | - |
effect.updateModelClip
| 方法签名 | 返回值 | 描述 |
|---|---|---|
updateModelClip(constant: number) | void | 更新模型剖切面位置 |
参数说明:
| 参数名 | 说明 | 类型 | 必填 | 默认值 |
|---|---|---|---|---|
constant | 初始剖切位置 | number | 是 | - |
effect.deleteModelClip
| 方法签名 | 返回值 | 描述 |
|---|---|---|
deleteModelClip() | void | 删除模型剖切面 |