Skip to content

案例展示

模型剖切效果

模型:
选择模型
剖切轴:
位置:
89.5
<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删除模型剖切面