1) 解决增加A节点的问题

https://github.com/A-Ribeiro/CustomBlenderFBXExporter

2)找出blendshape 不一致,生成blendshape key name映射map 文件compare.txt

C:\Users\49938\Documents\DazToUnreal\zhang01\UpdatedFBX\zhang01_fix7.fbx
C:\Users\49938\Documents\DazToUnreal\zhang01\UpdatedFBX\zhang01.fbx
C:\Users\49938\Documents\DazToUnreal\zhang01\UpdatedFBX\compare.txt

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
BlendShape差异可视化报告生成器
生成HTML格式的BlendShape比较报告
"""from fbx import *
import sys
import os
import json
from datetime import datetimedef InitializeSdk():"""初始化SDK"""manager = FbxManager.Create()ios = FbxIOSettings.Create(manager, IOSROOT)manager.SetIOSettings(ios)return managerdef LoadFBX(manager, filename):"""加载FBX文件"""scene = FbxScene.Create(manager, "")importer = FbxImporter.Create(manager, "")if not importer.Initialize(filename, -1, manager.GetIOSettings()):return Noneif not importer.Import(scene):importer.Destroy()return Noneimporter.Destroy()return scenedef SafeCastToBlendShape(deformer):"""安全地将变形器转换为 BlendShape 对象"""try:if hasattr(FbxBlendShape, 'Cast'):return FbxBlendShape.Cast(deformer)else:return deformerexcept Exception as e:print(f"类型转换错误: {e}")return deformerdef ExtractBlendShapeKeys(scene):"""提取场景中所有的 BlendShape Key Names"""blendshape_data = {'keys': [],'meshes': {},  # 记录每个mesh的blendshape信息'total_channels': 0}def TraverseNode(node):try:mesh = node.GetMesh()if mesh:mesh_name = node.GetName()mesh_blendshapes = []deformer_count = mesh.GetDeformerCount()for i in range(deformer_count):deformer = mesh.GetDeformer(i)deformer_type = deformer.GetDeformerType()if deformer_type == FbxDeformer.eBlendShape:blend_shape = SafeCastToBlendShape(deformer)try:channel_count = blend_shape.GetBlendShapeChannelCount()blendshape_data['total_channels'] += channel_countfor j in range(channel_count):channel = blend_shape.GetBlendShapeChannel(j)if channel:channel_name = channel.GetName()target_shape_count = channel.GetTargetShapeCount()if target_shape_count > 0:key_info = {'name': channel_name,'mesh': mesh_name,'target_count': target_shape_count}blendshape_data['keys'].append(key_info)mesh_blendshapes.append(channel_name)except Exception as e:print(f"处理 BlendShape 通道时出错: {e}")if mesh_blendshapes:blendshape_data['meshes'][mesh_name] = mesh_blendshapes# 递归遍历子节点for i in range(node.GetChildCount()):TraverseNode(node.GetChild(i))except Exception as e:print(f"处理节点 '{node.GetName()}' 时出错: {e}")root_node = scene.GetRootNode()if root_node:TraverseNode(root_node)return blendshape_datadef process_blendshape_diff(file_a, file_b, output_file):"""生成HTML比较报告"""# 初始化SDKmanager = InitializeSdk()# 加载文件scene_a = LoadFBX(manager, file_a)scene_b = LoadFBX(manager, file_b)if not scene_a or not scene_b:print("错误: 无法加载文件")manager.Destroy()return False# 获取BlendShape信息print("正在分析文件A的BlendShape...")blendshapes_a = ExtractBlendShapeKeys(scene_a)print("正在分析文件B的BlendShape...")blendshapes_b = ExtractBlendShapeKeys(scene_b)blendshapes_a['keys']# 创建BlendShape名称列表names_a = [key['name'] for key in blendshapes_a['keys']]names_b = [key['name'] for key in blendshapes_b['keys']]if len(names_a) != len(names_b):print("❌ 错误: 文件A和文件B的BlendShape数量不一致")manager.Destroy()return Falseelse:with open(output_file, 'w', encoding='utf-8') as f:print("文件A和文件B的BlendShape数量一致\n")# in rangefor i in range(len(names_a)):if names_a[i] != names_b[i]:f.write(f"{names_a[i]}|{names_b[i]}\n")# 清理manager.Destroy()return Truedef main():"""主函数"""if len(sys.argv) < 3:print("🎭 BlendShape差异可视化报告生成器")print("\n📖 使用方法:")print("  python fbx_blendshape_diff_visualizer.py <fbxA> <fbxB> [blendshape_comparison.txt]")print("\n📋 参数:")print("  fbxA: 第一个FBX文件")print("  fbxB: 第二个FBX文件")print("  output.html: 可选 ")sys.exit(1)file_a = sys.argv[1]file_b = sys.argv[2]output_file = sys.argv[3] if len(sys.argv) > 3 else "blendshape_comparison.txt"# 检查文件if not os.path.exists(file_a):print(f"❌ 错误: 文件不存在 - {file_a}")sys.exit(1)if not os.path.exists(file_b):print(f"❌ 错误: 文件不存在 - {file_b}")sys.exit(1)print("🚀 开始分析BlendShape差异...")print(f"📁 文件A: {file_a}")print(f"📁 文件B: {file_b}")process_blendshape_diff(file_a, file_b, output_file)if __name__ == "__main__":main()

 3)在blender里执行脚本修改blendshape key name


import bpy
import sys
import osdef rename_shape_keys_by_map(object_name, map_dict):"""批量重命名指定物体的形状键,移除指定前缀"""# 获取指定的物体obj = bpy.data.objects.get(object_name)if not obj:print(f"Error: Object '{object_name}' not found.")return -1if not obj.data or not hasattr(obj.data, 'shape_keys') or not obj.data.shape_keys:print(f"Error: Object '{object_name}' has no shape keys.")return -1shape_keys = obj.data.shape_keys.key_blocksrenamed_count = 0# 从第二个key开始遍历 (跳过'Basis'基础键)for key in shape_keys[1:]:if key.name in map_dict:# 保存原名称用于打印old_name = key.name# 获取新名称new_name = map_dict[key.name]# 重命名key.name = new_nameprint(f"Renamed '{old_name}' to '{new_name}'")renamed_count += 1print(f"\nBatch renaming complete! Renamed {renamed_count} shape keys.")return renamed_countdef batch_rename_all_objects():"""遍历场景中的所有物体,对每个物体执行形状键重命名操作对每个物体名称取'.'前面的部分作为基础名称,然后移除'_facs_ctrl'和'_facs_bs'前缀"""map_path = r"C:\Users\49938\Documents\DazToUnreal\zhang01\UpdatedFBX\compare.txt"if not os.path.exists(map_path):print(f"Error: Map file '{map_path}' does not exist.")return -1# 读取文件的所有行with open(map_path, 'r', encoding='utf-8') as file:lines = file.readlines()# 创建一个字典来存储旧名称和新名称的映射map_dict = {}for line in lines:# 去除行首尾的空白字符line = line.strip()if not line:continue  # 跳过空行# 分割行,假设格式为 "旧名称|新名称"parts = line.split('|')if len(parts) == 2:old_name, new_name = partsmap_dict[old_name] = new_nameelse:print(f"Warning: Line '{line}' is not in the expected format 'old_name new_name'. Skipping.")# 获取场景中的所有物体all_objects = bpy.data.objectsprint("Starting batch rename for all objects in scene...")print("=" * 50)for obj in all_objects:# 获取物体名称,取'.'前面的部分object_name = obj.namebase_name = object_name.split('.')[0]print(f"\nProcessing object: '{object_name}' (base: '{base_name}')")# 对每个物体调用两次重命名函数rename_shape_keys_by_map(object_name, map_dict)print("\n" + "=" * 50)print("Batch processing complete!")print("=" * 50)
batch_rename_all_objects() 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/913097.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/913097.shtml
英文地址,请注明出处:http://en.pswp.cn/news/913097.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI时代下的IT服务管理转型:趋势、挑战与破局之道

近年来&#xff0c;人工智能&#xff08;AI&#xff09;与自动化技术的迅猛发展&#xff0c;正以前所未有的速度重塑企业运营的各个层面。特别是在IT服务管理&#xff08;ITSM&#xff09;领域&#xff0c;AI的介入不仅提高了问题响应效率&#xff0c;也推动了组织从“被动响应…

三体融合实战:Django+讯飞星火+Colossal-AI的企业级AI系统架构

目录 技术栈关键词&#xff1a;Django 5.0 讯飞星火4.0Ultra Colossal-AI 1.2 WebSocket 联邦学习 ⚡ 核心架构设计 &#x1f6e0;️ 一、Django深度集成讯飞星火API&#xff08;免费版&#xff09; 1. 获取API凭证 2. 流式通信改造&#xff08;解决高并发阻塞&#xff09…

多模态数据融合预警:从IoT传感器到卫星监测的可视化方案升级

你有没有想过&#xff0c;为什么有些城市在暴雨来临时能提前数小时发布内涝预警&#xff0c;而有些地方却只能“等水来了才反应”&#xff1f; 背后的关键&#xff0c;就是多模态数据融合预警系统——它把来自IoT传感器、无人机、地面雷达、气象站、甚至卫星的数据整合在一起&a…

面试八股---css

2、css 2.1 说说你对盒子模型的理解 是什么 当对一个文档进行布局&#xff08;layout&#xff09;的时候&#xff0c;浏览器的渲染引擎会根据标准之一的 CSS 基础框盒模型&#xff08;CSS basic box model&#xff09;&#xff0c;将所有元素表示为一个个矩形的盒子&#xf…

day52-硬件学习之RTC及ADC

一、RTCRTC&#xff08;实时时钟&#xff09;&#xff1a;非易失性在IMX6ULL内部SNVS&#xff08;安全的非易失性存储器&#xff09;提供RTC功能&#xff1b;原理图&#xff1a;二、ADC 2.1 基本概念ADC(模拟数字转换器)&#xff1a;用于将连续变化的模拟信号转换为离散的数字信…

Web 项目如何自动化测试?

Web 项目的自动化测试可以通过 UI自动化 和 接口自动化 结合实现&#xff0c;提高测试效率和覆盖率。以下是关键方法和工具&#xff1a; 【自动化测试】从基础到实战基于Pytest自动化/python自动化的详细教程&#xff01;1. UI自动化测试&#xff08;前端交互&#xff09; 适用…

Java连接阿里云MaxCompute例

要使用Java连接阿里云MaxCompute&#xff08;原名ODPS&#xff09;数据库&#xff0c;您可以遵循以下步骤进行配置和编程&#xff1a; 1. 添加依赖 确保您的项目中包含了MaxCompute JDBC驱动的依赖。如果您使用Maven&#xff0c;可以在pom.xml中添加如下依赖&#xff1a; &l…

【网络与系统安全】强制访问控制——BLP模型

一、模型背景与定义 BLP&#xff08;Bell-LaPadula&#xff09;模型是由David Bell和Len Adula在1973年提出的强制访问控制&#xff08;MAC&#xff09;模型&#xff0c;是最早的计算机安全模型之一&#xff0c;主要用于解决多用户系统中的信息机密性保护问题&#xff0c;尤其…

HTTPS详解:原理 + 加解密过程 + 面试问答

一、HTTP 与 HTTPS 的区别 项目HTTPHTTPS全称HyperText Transfer ProtocolHyperText Transfer Protocol Secure端口80443协议层应用层应用层 TLS&#xff08;安全层&#xff09;加密方式明文传输加密传输&#xff08;TLS&#xff09;安全性易被劫持、中间人攻击可加密、防篡改…

Python-GUI-wxPython-控件

1 需求 2 接口 3.* 控件&#xff1a;wx.StaticText import wxclass MainFrame(wx.Frame):def __init__(self, *args, **kwargs):super(MainFrame, self).__init__(*args, **kwargs)self.init_ui()self.Center()self.Maximize()def init_ui(self):static_text wx.StaticText(pa…

3-1 PID算法改进(积分部分)

目录 1、积分限幅 2、积分分离 3、变速积分 在位置式PID的基础上进行改进 定速用PI控制&#xff0c;定位置用PD控制 1、积分限幅 在定速控制上体现 第一种方法确定上下限方法&#xff1a;Out最大时&#xff0c;除以Ki&#xff0c;得到一个值&#xff0c;上限不能超过这个…

Linux探秘坊-------13.进程间通信

1.进程间通信⽬的 2.管道 2.1 匿名管道 -----通常用来实现 父子通信 创建子进程时&#xff0c;需要把父进程的进程内容全部拷贝一份&#xff0c;但文件管理是不需要拷贝的 但是我们把父进程的文件描述符表给拷贝下来了&#xff0c;文件描述符表里是一堆指针&#xff0c;他们仍…

深入理解Vapnik-Chervonenkis(VC)维度:机器学习泛化能力的理论基础

引言 通过本篇阅读,从理论上去理解为什么: 要选择复杂度低的模型 过拟合的时候,增加样本量有用 以及如何根据样本量选择特征个数 PAC机器学习框架, VC 维是机器学习最重要的基础理论之一 在机器学习领域&#xff0c;模型泛化能力是衡量算法性能的核心指标…

redis持久化-纯缓存模式

redis持久化-纯缓存模式 文档 redis单机安装redis常用的五种数据类型redis数据类型-位图bitmapredis数据类型-基数统计HyperLogLogredis数据类型-地理空间GEOredis数据类型-流Streamredis数据类型-位域bitfieldredis持久化-RDBredis持久化-AOFredis持久化-RDBAOF混合模式 官…

HTML DOM 访问

HTML DOM 访问 引言 HTML DOM&#xff08;文档对象模型&#xff09;是现代Web开发中不可或缺的一部分。它允许开发者通过JavaScript操作HTML文档中的元素&#xff0c;从而实现丰富的交互效果。本文将详细介绍HTML DOM的访问方法&#xff0c;包括如何获取元素、如何修改元素属…

双系统如何做接口认证-V1

现有A系统&#xff0c;B系统&#xff0c;A系统启动的时候调用B系统的注册接口API1&#xff08;把A系统配置信息注册到B系统&#xff09;&#xff0c;A系统定时向B系统接口AP2发送心跳信息&#xff0c;B系统根据业务情况&#xff0c;调用A系统的业务接口AP3&#xff0c;请设计两…

Wireshark TS | 诡异的光猫网络问题

前言 来自于朋友分享的一个案例&#xff0c;最后定位的原因是光猫问题&#xff0c;而类似这类的设备所产生的网络问题&#xff0c;也曾碰到过两三次&#xff0c;但这一次的数据包现象挺特别&#xff0c;分析思路和过程也有所不同&#xff0c;故记录分享一下。 问题背景 用户所反…

mac mini m4安装node.js@16以下版本方法

设备&#xff1a;mac mini m4 目的&#xff1a;使用nvm 安装 node.js14.x 版本 结果&#xff1a;安装不上 原因&#xff1a;Node.js 14 发布时&#xff0c;Apple Silicon&#xff08;M1/M2&#xff09;尚未普及&#xff0c;因此 没有官方预编译的 macOS ARM64 版本 处理方案&am…

系统安全设计方案,软件系统安全设计方案

1.1 总体设计 1.1.1 设计原则 1.2 物理层安全 1.2.1 机房建设安全 1.2.2 电气安全特性 1.2.3 设备安全 1.2.4 介质安全措施 1.3 网络层安全 1.3.1 网络结构安全 1.3.2 划分子网络 1.3.3 异常流量管理 1.3.4 网络安全审计 1.3.5 网络访问控制 1.3.6 完整性检查 1.…

Python入门Day3

Python的基础数据类型 1.Python中提供了六种内置的数据类型&#xff0c;一般用于存储数据&#xff1a; –数值Number –字符串String –列表List –元组Tuple –字典Dictionary –集合Set 2.Python中的数据类型可以做以下几个分类&#xff1a; –有序&#xff1a;可以使用下标…