Vue3 HY-Motion 1.0打造你的零代码在线动作设计平台想象一下你是一个游戏策划脑子里有个超酷的战士挥剑动作但你不是动画师不会用复杂的3D软件。或者你是个短视频创作者想给虚拟主播设计一段打招呼的舞蹈却卡在了动作制作上。以前这可能意味着你要么花大价钱外包要么自己花几天时间去学习Blender。但现在情况不一样了。腾讯开源的HY-Motion 1.0让“一句话生成3D动作”变成了现实。而我们要做的就是为这个强大的模型打造一个简单好用的“操作台”——一个基于Vue3的在线动作设计平台。你不用写一行模型推理代码也不用懂复杂的3D渲染只需要一个浏览器就能把文字描述变成会动的3D小人。这篇文章我就带你一步步搭建这样一个平台。我们会用到Vue3构建清爽的前端界面用WebSocket实现动作的实时预览再用Three.js把生成的骨骼数据变成屏幕上活灵活现的动画。整个过程就像搭积木我们把各个技术模块组合起来最终做出一个真正能用的工具。1. 为什么需要这样一个平台从想法到动画的“最后一公里”HY-Motion 1.0本身是个命令行工具或者API服务对普通用户来说门槛还是有点高。你得准备Python环境会调用接口还得想办法把生成的一堆骨骼数据变成能看的动画。这中间的步骤劝退了很多人。我们构建的在线平台就是要解决这“最后一公里”的问题。它的核心价值很简单零代码操作用户只需要在网页输入框里打字比如“一个人开心地跳跃”点击生成然后就能直接看到一个3D模型在页面上把这个动作做出来。实时反馈传统流程生成动作可能需要等几分钟然后下载文件再用其他软件打开查看。我们的平台通过WebSocket可以让用户几乎实时地看到动作生成的进度和预览效果。降低门槛将专业级的3D动作生成能力变成像美图秀秀一样简单易用的网页工具。无论是学生做作业、UP主做视频还是独立游戏开发者做原型都能立刻用上。这个平台就像一个桥梁一头连着普通人天马行空的想法另一头连着HY-Motion 1.0这个强大的AI引擎。我们接下来要做的就是把这个桥建得又稳固又好看。2. 搭建项目骨架Vue3与基础界面我们从最基础的开始创建一个Vue3项目并搭建出平台的雏形。首先用你习惯的方式创建一个新的Vue3项目。这里我用Vitenpm create vuelatest vue3-hymotion-platform # 按照提示选择需要的特性比如TypeScript、Router等 cd vue3-hymotion-platform npm install安装我们初期需要的依赖npm install three types/three socket.io-client # 如果使用Pinia进行状态管理也可以安装 # npm install pinia现在我们来规划一下首页的组件结构。我会创建一个清晰的布局包含动作描述输入区、控制按钮、3D预览画布和动作列表。src/App.vue的简化结构如下template div classapp-container header classapp-header h1 零代码动作设计工坊/h1 p classsubtitle用文字描述让3D角色动起来/p /header main classmain-content !-- 左侧控制面板 -- div classcontrol-panel ActionInput generatehandleGenerateAction / ActionControls playplayAnimation pausepauseAnimation resetresetScene / ActionHistory :actionsactionHistory loadloadHistoryAction / /div !-- 右侧3D预览区 -- div classpreview-panel div classcanvas-container canvas refthreeCanvas/canvas /div div classpreview-info p v-ifgenerating正在生成动作... ({{ generationProgress }}%)/p p v-else-ifcurrentActionDescription当前动作{{ currentActionDescription }}/p p v-else输入描述点击生成预览将在此处显示。/p /div /div /main /div /template script setup langts import { ref, onMounted, onUnmounted } from vue; import ActionInput from ./components/ActionInput.vue; import ActionControls from ./components/ActionControls.vue; import ActionHistory from ./components/ActionHistory.vue; // 稍后我们会创建Three.js场景管理器 import { initThreeScene } from ./utils/threeScene; const threeCanvas refHTMLCanvasElement | null(null); const generating ref(false); const generationProgress ref(0); const currentActionDescription ref(); const actionHistory refArray{id: string, desc: string, data: any}([]); const handleGenerateAction async (description: string) { if (!description.trim()) return; generating.value true; currentActionDescription.value description; // 这里将触发WebSocket调用稍后实现 console.log(生成动作:, description); }; // Three.js场景生命周期 onMounted(() { if (threeCanvas.value) { initThreeScene(threeCanvas.value); } }); onUnmounted(() { // 清理Three.js资源 }); /script style scoped .app-container { max-width: 1400px; margin: 0 auto; padding: 20px; } .app-header { text-align: center; margin-bottom: 40px; } .main-content { display: flex; gap: 30px; } .control-panel { flex: 0 0 350px; } .preview-panel { flex: 1; } .canvas-container { width: 100%; height: 500px; border: 1px solid #eee; border-radius: 8px; overflow: hidden; } canvas { display: block; width: 100%; height: 100%; } /style这个结构搭建了一个基本的左右布局。左边是控制区右边是3D预览区。接下来我们需要实现最核心的三大模块与HY-Motion后端的通信、3D渲染以及实时预览。3. 核心模块一连接AI引擎 - WebSocket实时通信HY-Motion 1.0模型推理通常部署在服务端。为了让前端能实时获取生成进度和结果我们使用WebSocket。这里假设你已经有一个后端服务它启动了Socket.IO或原生WebSocket服务负责调用HY-Motion模型并推送数据。我们在前端创建一个WebSocket管理模块src/utils/socketManager.tsimport { io, Socket } from socket.io-client; class SocketManager { private socket: Socket | null null; private url: string; public isConnected false; constructor(serverUrl: string) { this.url serverUrl; } connect(): Promisevoid { return new Promise((resolve, reject) { this.socket io(this.url, { transports: [websocket], }); this.socket.on(connect, () { console.log(WebSocket连接成功); this.isConnected true; resolve(); }); this.socket.on(connect_error, (error) { console.error(WebSocket连接失败:, error); reject(error); }); this.socket.on(disconnect, () { console.log(WebSocket连接断开); this.isConnected false; }); }); } // 发送生成动作的请求 generateMotion(description: string): Promiseany { return new Promise((resolve, reject) { if (!this.socket || !this.isConnected) { reject(new Error(WebSocket未连接)); return; } // 监听本次请求的特定事件 const resultHandler (data: any) { this.socket?.off(motion_result, resultHandler); this.socket?.off(motion_error, errorHandler); resolve(data); }; const errorHandler (error: any) { this.socket?.off(motion_result, resultHandler); this.socket?.off(motion_error, errorHandler); reject(error); }; this.socket.on(motion_result, resultHandler); this.socket.on(motion_error, errorHandler); // 发送生成指令 this.socket.emit(generate_motion, { text: description }); }); } // 监听实时进度后端可以分步推送token或进度 onProgress(callback: (progress: number) void) { this.socket?.on(generation_progress, callback); } // 断开连接 disconnect() { if (this.socket) { this.socket.disconnect(); this.socket null; this.isConnected false; } } } // 导出一个单例实例方便全局使用 export const socketManager new SocketManager(import.meta.env.VITE_WS_SERVER || ws://localhost:3000);然后在Vue组件中集成这个通信模块。修改ActionInput.vue和App.vue中的handleGenerateAction函数!-- src/components/ActionInput.vue 部分代码 -- script setup langts import { ref } from vue; import { socketManager } from ../utils/socketManager; const emit defineEmits{ (e: generate, description: string): void; }(); const inputText ref(); const isLoading ref(false); const handleSubmit async () { if (!inputText.value.trim() || isLoading.value) return; isLoading.value true; emit(generate, inputText.value); // 通知父组件 try { // 确保连接 if (!socketManager.isConnected) { await socketManager.connect(); } // 请求生成动作并等待结果 const motionData await socketManager.generateMotion(inputText.value); console.log(收到动作数据:, motionData); // 这里应该触发一个全局事件或状态更新让3D场景开始播放这个数据 // 例如window.dispatchEvent(new CustomEvent(motion-data-ready, { detail: motionData })); } catch (error) { console.error(生成动作失败:, error); alert(动作生成失败请重试或检查网络。); } finally { isLoading.value false; } }; /script这样前端和后端的通信管道就打通了。后端负责重活累活运行大模型前端负责发送指令和接收结果。4. 核心模块二让数据活过来 - Three.js 3D渲染HY-Motion 1.0生成的是一系列骨骼数据SMPL-H格式我们需要用Three.js在浏览器里把它可视化。这是整个平台最“炫酷”的部分。我们创建一个Three.js场景管理器src/utils/threeScene.tsimport * as THREE from three; import { OrbitControls } from three/examples/jsm/controls/OrbitControls; let scene: THREE.Scene; let camera: THREE.PerspectiveCamera; let renderer: THREE.WebGLRenderer; let controls: OrbitControls; let skeletonHelper: THREE.SkeletonHelper; let mixer: THREE.AnimationMixer; let clock: THREE.Clock; // 初始化场景 export function initThreeScene(canvas: HTMLCanvasElement) { // 1. 创建场景 scene new THREE.Scene(); scene.background new THREE.Color(0xf0f0f0); // 2. 创建相机 camera new THREE.PerspectiveCamera(45, canvas.clientWidth / canvas.clientHeight, 0.1, 1000); camera.position.set(0, 10, 25); // 3. 创建渲染器 renderer new THREE.WebGLRenderer({ canvas, antialias: true }); renderer.setSize(canvas.clientWidth, canvas.clientHeight); renderer.setPixelRatio(window.devicePixelRatio); // 4. 添加轨道控制器允许用户用鼠标旋转缩放场景 controls new OrbitControls(camera, renderer.domElement); controls.enableDamping true; // 5. 添加光源 const ambientLight new THREE.AmbientLight(0xffffff, 0.6); scene.add(ambientLight); const directionalLight new THREE.DirectionalLight(0xffffff, 0.8); directionalLight.position.set(10, 20, 5); scene.add(directionalLight); // 6. 添加一个简易的参考网格地面 const gridHelper new THREE.GridHelper(20, 20, 0x888888, 0xcccccc); scene.add(gridHelper); // 7. 初始化时钟用于动画更新 clock new THREE.Clock(); // 8. 创建一个人体骨骼的简易表示这里用骨骼辅助对象稍后替换为真实蒙皮模型 createDefaultSkeleton(); // 9. 开始动画循环 animate(); // 窗口大小变化响应 window.addEventListener(resize, onWindowResize); } function onWindowResize() { const canvas renderer.domElement; camera.aspect canvas.clientWidth / canvas.clientHeight; camera.updateProjectionMatrix(); renderer.setSize(canvas.clientWidth, canvas.clientHeight); } // 创建一个默认的骨骼用于占位直到收到真实数据 function createDefaultSkeleton() { // 这里简化处理实际应用中你需要加载一个SMPL-H格式的3D模型如.glb文件 // 并为其创建骨骼和动画混合器。 // 此处我们用骨骼辅助线来示意。 const bones []; const rootBone new THREE.Bone(); bones.push(rootBone); // ... 这里应按照SMPL-H的22个关节结构创建完整的骨骼链 // 这是一个复杂的过程通常需要预定义模型。 const skeleton new THREE.Skeleton(bones); skeletonHelper new THREE.SkeletonHelper(rootBone); skeletonHelper.material.linewidth 3; scene.add(skeletonHelper); scene.add(rootBone); // 初始化动画混合器 mixer new THREE.AnimationMixer(rootBone); } // 核心函数加载HY-Motion生成的骨骼动画数据 export function loadMotionData(motionData: any) { // motionData 应包含 frames帧数, fps, 和 joints关节数据 // 1. 清除旧动画 if (mixer) { mixer.stopAllAction(); } // 2. 将收到的数据转换为Three.js的动画片段AnimationClip // 这是一个关键步骤需要根据SMPL-H数据格式解析每一帧每个关节的位置和旋转。 // 这里是一个高度简化的示例逻辑 const fps motionData.fps || 30; const duration motionData.frames / fps; const tracks: THREE.KeyframeTrack[] []; // 假设 motionData.joints 是一个数组每项是一帧每帧包含22个关节的旋转和平移 motionData.joints.forEach((jointData: any, jointIndex: number) { // 为每个关节创建旋转和平移的KeyframeTrack // 实际代码需要处理四元数或欧拉角并映射到骨骼层级中正确的bone上。 // 例如 // const rotationTrack new THREE.QuaternionKeyframeTrack( // bones[${jointIndex}].quaternion, // times, // values // ); // tracks.push(rotationTrack); }); const clip new THREE.AnimationClip(generated_motion, duration, tracks); // 3. 用混合器播放这个动画片段 if (mixer clip) { const action mixer.clipAction(clip); action.play(); } } // 动画循环 function animate() { requestAnimationFrame(animate); const delta clock.getDelta(); if (mixer) { mixer.update(delta); // 更新动画状态 } controls.update(); // 更新控制器 renderer.render(scene, camera); }这个threeScene.ts文件是3D部分的核心。initThreeScene搭建了舞台loadMotionData则是把HY-Motion传回来的“乐谱”骨骼数据变成舞台上角色的“舞蹈动作”。实际的loadMotionData函数实现需要你仔细研究SMPL-H数据格式并将其精确地映射到Three.js的骨骼动画体系。你可能需要寻找一个现成的SMPL-H Three.js加载器或自己编写转换逻辑。5. 核心模块三拼装与实时预览现在我们把通信模块和渲染模块连接起来。当WebSocket收到动作数据时自动触发3D场景更新。我们可以在App.vue中或者一个全局状态管理器中监听来自WebSocket的数据并调用loadMotionData。!-- 在App.vue的script部分补充 -- script setup langts import { onMounted, onUnmounted } from vue; import { socketManager } from ./utils/socketManager; import { loadMotionData } from ./utils/threeScene; // ... 其他代码 onMounted(async () { // 初始化Three.js场景... // 监听WebSocket的进度事件 socketManager.onProgress((progress) { generationProgress.value progress; }); // 监听一个全局的自定义事件由ActionInput组件触发 window.addEventListener(motion-data-ready, (event: any) { const motionData event.detail; loadMotionData(motionData); // 将生成的动作存入历史记录 actionHistory.value.unshift({ id: Date.now().toString(), desc: currentActionDescription.value, data: motionData }); generating.value false; }); }); onUnmounted(() { socketManager.disconnect(); }); /script同时修改ActionInput.vue中的成功回调使其触发全局事件// 在 handleSubmit 的 try 块中收到数据后 const motionData await socketManager.generateMotion(inputText.value); // 触发事件让3D场景加载数据 window.dispatchEvent(new CustomEvent(motion-data-ready, { detail: motionData }));至此一个最基础的流程就跑通了输入文本 - WebSocket发送 - 后端生成 - 数据返回 - Three.js渲染播放。6. 打磨体验让平台真正好用基础功能有了但要成为一个好用的工具还需要很多细节打磨历史记录与回放ActionHistory组件不仅展示列表点击后应能重新加载并播放该动作数据。动作混合与编辑高级功能允许用户将多个生成的动作片段如“走路”、“挥手”在时间线上拼接甚至简单混合。角色模型切换允许用户上传或选择不同的3D角色模型仍需符合SMPL-H骨骼将动作重定向到新模型上。相机预设提供几个固定的相机角度正面、侧面、俯视方便用户查看动作细节。导出功能将生成的动作数据导出为通用格式如FBX、glTF方便用户导入到Blender、Unity等专业软件中继续加工。这些功能每一个都可以展开成一个独立的小模块用Vue组件来实现通过状态管理如Pinia来协调数据流。7. 总结走完这一趟你会发现用Vue3和现代前端技术封装一个像HY-Motion 1.0这样的AI大模型并没有想象中那么困难。关键是把复杂的技术拆解成几个明确的模块用户交互Vue、实时通信WebSocket、数据可视化Three.js。这个平台的价值不在于我们写了多复杂的Three.js着色器而在于我们成功地降低了一项尖端技术的使用门槛。它让创意不再受限于技术实现让更多人可以轻松地玩转3D动画。当然我们实现的只是一个原型里面还有很多可以优化和深挖的地方比如3D模型的精细度、动画数据的精确解析、更流畅的用户交互等等。但最重要的是我们证明了这条路是可行的。前端技术不仅仅是展示静态页面它完全可以成为连接用户与强大AI能力的交互中枢。如果你对其中某个部分特别感兴趣比如Three.js的骨骼动画系统或者WebSocket的高效数据压缩传输都可以继续深入研究下去。这个项目就像一个乐高底座你可以随时往上添加更酷的模块。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。
Vue3+HY-Motion 1.0打造在线动作设计平台
Vue3 HY-Motion 1.0打造你的零代码在线动作设计平台想象一下你是一个游戏策划脑子里有个超酷的战士挥剑动作但你不是动画师不会用复杂的3D软件。或者你是个短视频创作者想给虚拟主播设计一段打招呼的舞蹈却卡在了动作制作上。以前这可能意味着你要么花大价钱外包要么自己花几天时间去学习Blender。但现在情况不一样了。腾讯开源的HY-Motion 1.0让“一句话生成3D动作”变成了现实。而我们要做的就是为这个强大的模型打造一个简单好用的“操作台”——一个基于Vue3的在线动作设计平台。你不用写一行模型推理代码也不用懂复杂的3D渲染只需要一个浏览器就能把文字描述变成会动的3D小人。这篇文章我就带你一步步搭建这样一个平台。我们会用到Vue3构建清爽的前端界面用WebSocket实现动作的实时预览再用Three.js把生成的骨骼数据变成屏幕上活灵活现的动画。整个过程就像搭积木我们把各个技术模块组合起来最终做出一个真正能用的工具。1. 为什么需要这样一个平台从想法到动画的“最后一公里”HY-Motion 1.0本身是个命令行工具或者API服务对普通用户来说门槛还是有点高。你得准备Python环境会调用接口还得想办法把生成的一堆骨骼数据变成能看的动画。这中间的步骤劝退了很多人。我们构建的在线平台就是要解决这“最后一公里”的问题。它的核心价值很简单零代码操作用户只需要在网页输入框里打字比如“一个人开心地跳跃”点击生成然后就能直接看到一个3D模型在页面上把这个动作做出来。实时反馈传统流程生成动作可能需要等几分钟然后下载文件再用其他软件打开查看。我们的平台通过WebSocket可以让用户几乎实时地看到动作生成的进度和预览效果。降低门槛将专业级的3D动作生成能力变成像美图秀秀一样简单易用的网页工具。无论是学生做作业、UP主做视频还是独立游戏开发者做原型都能立刻用上。这个平台就像一个桥梁一头连着普通人天马行空的想法另一头连着HY-Motion 1.0这个强大的AI引擎。我们接下来要做的就是把这个桥建得又稳固又好看。2. 搭建项目骨架Vue3与基础界面我们从最基础的开始创建一个Vue3项目并搭建出平台的雏形。首先用你习惯的方式创建一个新的Vue3项目。这里我用Vitenpm create vuelatest vue3-hymotion-platform # 按照提示选择需要的特性比如TypeScript、Router等 cd vue3-hymotion-platform npm install安装我们初期需要的依赖npm install three types/three socket.io-client # 如果使用Pinia进行状态管理也可以安装 # npm install pinia现在我们来规划一下首页的组件结构。我会创建一个清晰的布局包含动作描述输入区、控制按钮、3D预览画布和动作列表。src/App.vue的简化结构如下template div classapp-container header classapp-header h1 零代码动作设计工坊/h1 p classsubtitle用文字描述让3D角色动起来/p /header main classmain-content !-- 左侧控制面板 -- div classcontrol-panel ActionInput generatehandleGenerateAction / ActionControls playplayAnimation pausepauseAnimation resetresetScene / ActionHistory :actionsactionHistory loadloadHistoryAction / /div !-- 右侧3D预览区 -- div classpreview-panel div classcanvas-container canvas refthreeCanvas/canvas /div div classpreview-info p v-ifgenerating正在生成动作... ({{ generationProgress }}%)/p p v-else-ifcurrentActionDescription当前动作{{ currentActionDescription }}/p p v-else输入描述点击生成预览将在此处显示。/p /div /div /main /div /template script setup langts import { ref, onMounted, onUnmounted } from vue; import ActionInput from ./components/ActionInput.vue; import ActionControls from ./components/ActionControls.vue; import ActionHistory from ./components/ActionHistory.vue; // 稍后我们会创建Three.js场景管理器 import { initThreeScene } from ./utils/threeScene; const threeCanvas refHTMLCanvasElement | null(null); const generating ref(false); const generationProgress ref(0); const currentActionDescription ref(); const actionHistory refArray{id: string, desc: string, data: any}([]); const handleGenerateAction async (description: string) { if (!description.trim()) return; generating.value true; currentActionDescription.value description; // 这里将触发WebSocket调用稍后实现 console.log(生成动作:, description); }; // Three.js场景生命周期 onMounted(() { if (threeCanvas.value) { initThreeScene(threeCanvas.value); } }); onUnmounted(() { // 清理Three.js资源 }); /script style scoped .app-container { max-width: 1400px; margin: 0 auto; padding: 20px; } .app-header { text-align: center; margin-bottom: 40px; } .main-content { display: flex; gap: 30px; } .control-panel { flex: 0 0 350px; } .preview-panel { flex: 1; } .canvas-container { width: 100%; height: 500px; border: 1px solid #eee; border-radius: 8px; overflow: hidden; } canvas { display: block; width: 100%; height: 100%; } /style这个结构搭建了一个基本的左右布局。左边是控制区右边是3D预览区。接下来我们需要实现最核心的三大模块与HY-Motion后端的通信、3D渲染以及实时预览。3. 核心模块一连接AI引擎 - WebSocket实时通信HY-Motion 1.0模型推理通常部署在服务端。为了让前端能实时获取生成进度和结果我们使用WebSocket。这里假设你已经有一个后端服务它启动了Socket.IO或原生WebSocket服务负责调用HY-Motion模型并推送数据。我们在前端创建一个WebSocket管理模块src/utils/socketManager.tsimport { io, Socket } from socket.io-client; class SocketManager { private socket: Socket | null null; private url: string; public isConnected false; constructor(serverUrl: string) { this.url serverUrl; } connect(): Promisevoid { return new Promise((resolve, reject) { this.socket io(this.url, { transports: [websocket], }); this.socket.on(connect, () { console.log(WebSocket连接成功); this.isConnected true; resolve(); }); this.socket.on(connect_error, (error) { console.error(WebSocket连接失败:, error); reject(error); }); this.socket.on(disconnect, () { console.log(WebSocket连接断开); this.isConnected false; }); }); } // 发送生成动作的请求 generateMotion(description: string): Promiseany { return new Promise((resolve, reject) { if (!this.socket || !this.isConnected) { reject(new Error(WebSocket未连接)); return; } // 监听本次请求的特定事件 const resultHandler (data: any) { this.socket?.off(motion_result, resultHandler); this.socket?.off(motion_error, errorHandler); resolve(data); }; const errorHandler (error: any) { this.socket?.off(motion_result, resultHandler); this.socket?.off(motion_error, errorHandler); reject(error); }; this.socket.on(motion_result, resultHandler); this.socket.on(motion_error, errorHandler); // 发送生成指令 this.socket.emit(generate_motion, { text: description }); }); } // 监听实时进度后端可以分步推送token或进度 onProgress(callback: (progress: number) void) { this.socket?.on(generation_progress, callback); } // 断开连接 disconnect() { if (this.socket) { this.socket.disconnect(); this.socket null; this.isConnected false; } } } // 导出一个单例实例方便全局使用 export const socketManager new SocketManager(import.meta.env.VITE_WS_SERVER || ws://localhost:3000);然后在Vue组件中集成这个通信模块。修改ActionInput.vue和App.vue中的handleGenerateAction函数!-- src/components/ActionInput.vue 部分代码 -- script setup langts import { ref } from vue; import { socketManager } from ../utils/socketManager; const emit defineEmits{ (e: generate, description: string): void; }(); const inputText ref(); const isLoading ref(false); const handleSubmit async () { if (!inputText.value.trim() || isLoading.value) return; isLoading.value true; emit(generate, inputText.value); // 通知父组件 try { // 确保连接 if (!socketManager.isConnected) { await socketManager.connect(); } // 请求生成动作并等待结果 const motionData await socketManager.generateMotion(inputText.value); console.log(收到动作数据:, motionData); // 这里应该触发一个全局事件或状态更新让3D场景开始播放这个数据 // 例如window.dispatchEvent(new CustomEvent(motion-data-ready, { detail: motionData })); } catch (error) { console.error(生成动作失败:, error); alert(动作生成失败请重试或检查网络。); } finally { isLoading.value false; } }; /script这样前端和后端的通信管道就打通了。后端负责重活累活运行大模型前端负责发送指令和接收结果。4. 核心模块二让数据活过来 - Three.js 3D渲染HY-Motion 1.0生成的是一系列骨骼数据SMPL-H格式我们需要用Three.js在浏览器里把它可视化。这是整个平台最“炫酷”的部分。我们创建一个Three.js场景管理器src/utils/threeScene.tsimport * as THREE from three; import { OrbitControls } from three/examples/jsm/controls/OrbitControls; let scene: THREE.Scene; let camera: THREE.PerspectiveCamera; let renderer: THREE.WebGLRenderer; let controls: OrbitControls; let skeletonHelper: THREE.SkeletonHelper; let mixer: THREE.AnimationMixer; let clock: THREE.Clock; // 初始化场景 export function initThreeScene(canvas: HTMLCanvasElement) { // 1. 创建场景 scene new THREE.Scene(); scene.background new THREE.Color(0xf0f0f0); // 2. 创建相机 camera new THREE.PerspectiveCamera(45, canvas.clientWidth / canvas.clientHeight, 0.1, 1000); camera.position.set(0, 10, 25); // 3. 创建渲染器 renderer new THREE.WebGLRenderer({ canvas, antialias: true }); renderer.setSize(canvas.clientWidth, canvas.clientHeight); renderer.setPixelRatio(window.devicePixelRatio); // 4. 添加轨道控制器允许用户用鼠标旋转缩放场景 controls new OrbitControls(camera, renderer.domElement); controls.enableDamping true; // 5. 添加光源 const ambientLight new THREE.AmbientLight(0xffffff, 0.6); scene.add(ambientLight); const directionalLight new THREE.DirectionalLight(0xffffff, 0.8); directionalLight.position.set(10, 20, 5); scene.add(directionalLight); // 6. 添加一个简易的参考网格地面 const gridHelper new THREE.GridHelper(20, 20, 0x888888, 0xcccccc); scene.add(gridHelper); // 7. 初始化时钟用于动画更新 clock new THREE.Clock(); // 8. 创建一个人体骨骼的简易表示这里用骨骼辅助对象稍后替换为真实蒙皮模型 createDefaultSkeleton(); // 9. 开始动画循环 animate(); // 窗口大小变化响应 window.addEventListener(resize, onWindowResize); } function onWindowResize() { const canvas renderer.domElement; camera.aspect canvas.clientWidth / canvas.clientHeight; camera.updateProjectionMatrix(); renderer.setSize(canvas.clientWidth, canvas.clientHeight); } // 创建一个默认的骨骼用于占位直到收到真实数据 function createDefaultSkeleton() { // 这里简化处理实际应用中你需要加载一个SMPL-H格式的3D模型如.glb文件 // 并为其创建骨骼和动画混合器。 // 此处我们用骨骼辅助线来示意。 const bones []; const rootBone new THREE.Bone(); bones.push(rootBone); // ... 这里应按照SMPL-H的22个关节结构创建完整的骨骼链 // 这是一个复杂的过程通常需要预定义模型。 const skeleton new THREE.Skeleton(bones); skeletonHelper new THREE.SkeletonHelper(rootBone); skeletonHelper.material.linewidth 3; scene.add(skeletonHelper); scene.add(rootBone); // 初始化动画混合器 mixer new THREE.AnimationMixer(rootBone); } // 核心函数加载HY-Motion生成的骨骼动画数据 export function loadMotionData(motionData: any) { // motionData 应包含 frames帧数, fps, 和 joints关节数据 // 1. 清除旧动画 if (mixer) { mixer.stopAllAction(); } // 2. 将收到的数据转换为Three.js的动画片段AnimationClip // 这是一个关键步骤需要根据SMPL-H数据格式解析每一帧每个关节的位置和旋转。 // 这里是一个高度简化的示例逻辑 const fps motionData.fps || 30; const duration motionData.frames / fps; const tracks: THREE.KeyframeTrack[] []; // 假设 motionData.joints 是一个数组每项是一帧每帧包含22个关节的旋转和平移 motionData.joints.forEach((jointData: any, jointIndex: number) { // 为每个关节创建旋转和平移的KeyframeTrack // 实际代码需要处理四元数或欧拉角并映射到骨骼层级中正确的bone上。 // 例如 // const rotationTrack new THREE.QuaternionKeyframeTrack( // bones[${jointIndex}].quaternion, // times, // values // ); // tracks.push(rotationTrack); }); const clip new THREE.AnimationClip(generated_motion, duration, tracks); // 3. 用混合器播放这个动画片段 if (mixer clip) { const action mixer.clipAction(clip); action.play(); } } // 动画循环 function animate() { requestAnimationFrame(animate); const delta clock.getDelta(); if (mixer) { mixer.update(delta); // 更新动画状态 } controls.update(); // 更新控制器 renderer.render(scene, camera); }这个threeScene.ts文件是3D部分的核心。initThreeScene搭建了舞台loadMotionData则是把HY-Motion传回来的“乐谱”骨骼数据变成舞台上角色的“舞蹈动作”。实际的loadMotionData函数实现需要你仔细研究SMPL-H数据格式并将其精确地映射到Three.js的骨骼动画体系。你可能需要寻找一个现成的SMPL-H Three.js加载器或自己编写转换逻辑。5. 核心模块三拼装与实时预览现在我们把通信模块和渲染模块连接起来。当WebSocket收到动作数据时自动触发3D场景更新。我们可以在App.vue中或者一个全局状态管理器中监听来自WebSocket的数据并调用loadMotionData。!-- 在App.vue的script部分补充 -- script setup langts import { onMounted, onUnmounted } from vue; import { socketManager } from ./utils/socketManager; import { loadMotionData } from ./utils/threeScene; // ... 其他代码 onMounted(async () { // 初始化Three.js场景... // 监听WebSocket的进度事件 socketManager.onProgress((progress) { generationProgress.value progress; }); // 监听一个全局的自定义事件由ActionInput组件触发 window.addEventListener(motion-data-ready, (event: any) { const motionData event.detail; loadMotionData(motionData); // 将生成的动作存入历史记录 actionHistory.value.unshift({ id: Date.now().toString(), desc: currentActionDescription.value, data: motionData }); generating.value false; }); }); onUnmounted(() { socketManager.disconnect(); }); /script同时修改ActionInput.vue中的成功回调使其触发全局事件// 在 handleSubmit 的 try 块中收到数据后 const motionData await socketManager.generateMotion(inputText.value); // 触发事件让3D场景加载数据 window.dispatchEvent(new CustomEvent(motion-data-ready, { detail: motionData }));至此一个最基础的流程就跑通了输入文本 - WebSocket发送 - 后端生成 - 数据返回 - Three.js渲染播放。6. 打磨体验让平台真正好用基础功能有了但要成为一个好用的工具还需要很多细节打磨历史记录与回放ActionHistory组件不仅展示列表点击后应能重新加载并播放该动作数据。动作混合与编辑高级功能允许用户将多个生成的动作片段如“走路”、“挥手”在时间线上拼接甚至简单混合。角色模型切换允许用户上传或选择不同的3D角色模型仍需符合SMPL-H骨骼将动作重定向到新模型上。相机预设提供几个固定的相机角度正面、侧面、俯视方便用户查看动作细节。导出功能将生成的动作数据导出为通用格式如FBX、glTF方便用户导入到Blender、Unity等专业软件中继续加工。这些功能每一个都可以展开成一个独立的小模块用Vue组件来实现通过状态管理如Pinia来协调数据流。7. 总结走完这一趟你会发现用Vue3和现代前端技术封装一个像HY-Motion 1.0这样的AI大模型并没有想象中那么困难。关键是把复杂的技术拆解成几个明确的模块用户交互Vue、实时通信WebSocket、数据可视化Three.js。这个平台的价值不在于我们写了多复杂的Three.js着色器而在于我们成功地降低了一项尖端技术的使用门槛。它让创意不再受限于技术实现让更多人可以轻松地玩转3D动画。当然我们实现的只是一个原型里面还有很多可以优化和深挖的地方比如3D模型的精细度、动画数据的精确解析、更流畅的用户交互等等。但最重要的是我们证明了这条路是可行的。前端技术不仅仅是展示静态页面它完全可以成为连接用户与强大AI能力的交互中枢。如果你对其中某个部分特别感兴趣比如Three.js的骨骼动画系统或者WebSocket的高效数据压缩传输都可以继续深入研究下去。这个项目就像一个乐高底座你可以随时往上添加更酷的模块。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。