forked from natuka/web.puabadge.com
Initial commit
This commit is contained in:
commit
84061c9a18
243 files changed
+63148
No files matched your search
@@ -0,0 +1,271 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import * as SPLAT from 'gsplat'
|
||||
import { showSuccessToast, showToast } from 'vant'
|
||||
const props = defineProps({
|
||||
modelFile: { type: String, default: () => '' },
|
||||
pid: { type: Number, default: 0 },
|
||||
})
|
||||
const emit = defineEmits([
|
||||
'changeBackgound',
|
||||
'rotateControl',
|
||||
'handleProgress',
|
||||
'handleLoaded',
|
||||
])
|
||||
const scene = new SPLAT.Scene()
|
||||
const camera = new SPLAT.Camera()
|
||||
const splat = ref(null)
|
||||
const color = new SPLAT.Color32()
|
||||
const renderer = new SPLAT.WebGLRenderer()
|
||||
const controls = new SPLAT.OrbitControls(camera, renderer.canvas)
|
||||
const STATE = {
|
||||
NONE: -1,
|
||||
MOVE: 0,
|
||||
ZOOM_OR_PAN: 1,
|
||||
POSITION_MOVE: 1,
|
||||
}
|
||||
const mouseInfo = ref({ startX: 0, startY: 0, isDown: false, startPointerDistance: 0, state: STATE.NONE })
|
||||
|
||||
// let model, scene, camera, renderer, controls;
|
||||
const preventStop = ref(false)
|
||||
const autoRotate = ref(false)
|
||||
const rotateInterval = ref(null)
|
||||
const twoFirst = ref(true)
|
||||
const lastPoint = ref(
|
||||
{
|
||||
touchStartX1: 0,
|
||||
touchStartY1: 0,
|
||||
touchStartX2: 0,
|
||||
touchStartY2: 0,
|
||||
},
|
||||
)
|
||||
watch(() => props.modelFile, (val, oldVal) => {
|
||||
if (val) {
|
||||
main(val)
|
||||
// setTimer()
|
||||
}
|
||||
}, {
|
||||
immediate: true,
|
||||
})
|
||||
const initCameraRotation = ref(null)
|
||||
const initCameraPosition = ref(null)
|
||||
const initCameraScale = ref(null)
|
||||
const initialRotation = ref(null)
|
||||
const DEG2RAD = Math.PI / 180
|
||||
let animationFrameId
|
||||
|
||||
// onMounted(async () => {
|
||||
// await main()
|
||||
// })
|
||||
|
||||
// 监听组件销毁事件
|
||||
onBeforeUnmount(() => {
|
||||
// 销毁 Three.js 模型
|
||||
splat.value = null
|
||||
// 清理渲染器
|
||||
renderer.dispose()
|
||||
|
||||
if (animationFrameId)
|
||||
cancelAnimationFrame(animationFrameId)
|
||||
|
||||
if (renderer.canvas.parentNode)
|
||||
renderer.canvas.parentNode.removeChild(renderer.canvas)
|
||||
})
|
||||
|
||||
async function main(val) {
|
||||
// 初始背景
|
||||
renderer.canvas.style.background = 'transparent'
|
||||
controls.orbitSpeed = 3 // 设置相机旋转速度
|
||||
// 初始化模型
|
||||
const url = val;
|
||||
// const url = 'https://suwa3d-test.oss-cn-shanghai.aliyuncs.com/plys/151322_superpoint.ply'
|
||||
// const url = "https://suwa3d-test.oss-cn-shanghai.aliyuncs.com/test/glbs/auto/195231.splat";
|
||||
// const url = "https://suwa3d-test.oss-cn-shanghai.aliyuncs.com/test/glbs/auto/192571.splat";
|
||||
splat.value = await SPLAT.Loader.LoadAsync(url, scene, (e) => {
|
||||
if(e == 1) {
|
||||
emit("handleLoaded")
|
||||
}else {
|
||||
emit("handleProgress",e * 100)
|
||||
}
|
||||
});
|
||||
console.log("splat.value", splat.value)
|
||||
// splat.value = await SPLAT.PLYLoader.LoadAsync(url, scene, (e) => {
|
||||
// console.log('e', e)
|
||||
// if (e == 1)
|
||||
// emit('handleLoaded')
|
||||
// else
|
||||
// emit('handleProgress', e * 100)
|
||||
// })
|
||||
const rotation = new SPLAT.Vector3(-3.2, -0.5, 0)
|
||||
splat.value.rotation = SPLAT.Quaternion.FromEuler(rotation)
|
||||
splat.value.position = new SPLAT.Vector3(0, -0.8, 0)
|
||||
splat.value.scale = new SPLAT.Vector3(1.5, 1.5, 1.5)
|
||||
splat.value.applyPosition()
|
||||
splat.value.applyRotation()
|
||||
splat.value.applyScale()
|
||||
// splat.value.scale = new SPLAT.Vector3(1, 1, 1)
|
||||
|
||||
const frame = () => {
|
||||
controls.update()
|
||||
renderer.render(scene, camera)
|
||||
animationFrameId = requestAnimationFrame(frame)
|
||||
}
|
||||
animationFrameId = requestAnimationFrame(frame)
|
||||
|
||||
// 获取到初始状态的位置
|
||||
initCameraRotation.value = camera.rotation
|
||||
initCameraPosition.value = camera.position
|
||||
initCameraScale.value = camera.scale
|
||||
initialRotation.value = splat.value.rotation.clone()
|
||||
|
||||
// 监听缩放\旋转操作
|
||||
renderer.canvas.addEventListener('touchmove', (event) => {
|
||||
// console.log("camera.rotation", camera.rotation)
|
||||
|
||||
// handleTouchStart(event)
|
||||
})
|
||||
}
|
||||
// -------------------------------事件-------------------------------
|
||||
// 设置背景颜色
|
||||
const changeColorChild = (type, index, param) => {
|
||||
renderer.canvas.style.background = param
|
||||
emit('changeBackgound', index)
|
||||
}
|
||||
|
||||
// 设置自定义背景
|
||||
const changeTransparent = (type, index, param) => {
|
||||
renderer.canvas.style.background = 'transparent'
|
||||
emit('changeBackgound', index)
|
||||
}
|
||||
|
||||
// 按钮事件
|
||||
const controlEvent = (val) => {
|
||||
// let data = localStorage.get("positionData");
|
||||
// let foundData = false;
|
||||
// data.filter(item=>{
|
||||
// if (item.pid == props.pid && props.pid > 0 && !foundData) {
|
||||
// foundData = true;
|
||||
if (val == 1) {
|
||||
ResetPosition()
|
||||
} else if (val == 2) {
|
||||
// 保存当前位置
|
||||
initCameraRotation.value = camera.rotation;
|
||||
initCameraPosition.value = camera.position;
|
||||
initCameraScale.value = camera.scale;
|
||||
showSuccessToast('保存成功'.$t)
|
||||
} else if (val == 3) {
|
||||
spin()
|
||||
} else if (val == 4) {
|
||||
spin()
|
||||
}
|
||||
// })
|
||||
}
|
||||
|
||||
const ResetPosition = () => {
|
||||
if(!autoRotate.value) {
|
||||
camera.rotation = initCameraRotation.value
|
||||
camera.position = initCameraPosition.value
|
||||
camera.scale = initCameraScale.value
|
||||
const rotation = new SPLAT.Vector3(0, -count.value, 0)
|
||||
splat.value.rotation = SPLAT.Quaternion.FromEuler(rotation)
|
||||
// splat.value.scale = new SPLAT.Vector3(0.5, 0.5, 0.5)
|
||||
splat.value.applyRotation()
|
||||
// splat.value.applyScale();
|
||||
// splat.value.rotation = SPLAT.Quaternion.FromAxisAngle(new SPLAT.Vector3(0, 1, 0), DEG2RAD * 87);
|
||||
// splat.value.applyRotation();
|
||||
console.log('splat.value.scale', splat.value.scale)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 旋转
|
||||
const spin = () => {
|
||||
if (!autoRotate.value) {
|
||||
if (preventStop.value)
|
||||
return
|
||||
setTimer()
|
||||
} else {
|
||||
clearTimer()
|
||||
}
|
||||
}
|
||||
const count = ref(0);
|
||||
// 开启自动旋转
|
||||
const setTimer = () => {
|
||||
const val = initCameraRotation.value;
|
||||
clearInterval(rotateInterval.value);
|
||||
rotateInterval.value = setInterval(() => {
|
||||
const a = 0.03
|
||||
const rotation = new SPLAT.Vector3(0, a, 0)
|
||||
splat.value.rotation = SPLAT.Quaternion.FromEuler(rotation)
|
||||
splat.value.applyRotation()
|
||||
count.value +=0.03
|
||||
// let cameraRotation = new SPLAT.Vector3(0, a, 0)
|
||||
// camera.position = new SPLAT.Vector3(x, y, z);
|
||||
// console.log("initCameraRotation", scene.objects[0])
|
||||
// val.y -=0.05;
|
||||
// camera.rotation = SPLAT.Quaternion.FromAxisAngle(val, DEG2RAD * 87);
|
||||
}, 100)
|
||||
autoRotate.value = true
|
||||
emit('rotateControl', true)
|
||||
}
|
||||
|
||||
// 关闭自动旋转
|
||||
const clearTimer = () => {
|
||||
clearInterval(rotateInterval.value)
|
||||
rotateInterval.value = null
|
||||
autoRotate.value = false
|
||||
|
||||
emit('rotateControl', false)
|
||||
}
|
||||
|
||||
const onKeyDown = (event: KeyboardEvent) => {
|
||||
// Use i, j, k, l to move the camera around
|
||||
let translation = new SPLAT.Vector3()
|
||||
if (event.key === 'j')
|
||||
translation = translation.add(new SPLAT.Vector3(-1, 0, 0))
|
||||
|
||||
if (event.key === 'l')
|
||||
translation = translation.add(new SPLAT.Vector3(1, 0, 0))
|
||||
|
||||
if (event.key === 'i')
|
||||
translation = translation.add(new SPLAT.Vector3(0, 0, 1))
|
||||
|
||||
if (event.key === 'k')
|
||||
translation = translation.add(new SPLAT.Vector3(0, 0, -1))
|
||||
|
||||
camera.position = camera.position.add(translation)
|
||||
|
||||
// Use u to set a random look target near the origin
|
||||
if (event.key === 'u') {
|
||||
const target = new SPLAT.Vector3(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5)
|
||||
controls.setCameraTarget(target)
|
||||
}
|
||||
|
||||
// Use space to reset the camera
|
||||
if (event.key === ' ') {
|
||||
camera.position = new SPLAT.Vector3()
|
||||
camera.rotation = new SPLAT.Quaternion()
|
||||
}
|
||||
}
|
||||
window.addEventListener('keydown', onKeyDown)
|
||||
|
||||
defineExpose({
|
||||
changeColorChild,
|
||||
changeTransparent,
|
||||
ResetPosition,
|
||||
controlEvent,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<!-- <canvas ref="glcanvas"></canvas> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.viewer {
|
||||
/* width: 100vw;
|
||||
height: 100vh; */
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user