You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用pythonOCC读取GLB文件自定义Extras/用户数据:RWGltf_CafReader导入支持及正确读取方案咨询

RWGltf_CafReader对GLB Extras的支持及正确读取方案

首先直接给你结论:RWGltf_CafReader 默认并不支持自动将GLB节点的extras字段映射回OCC的TDataStd_NamedData属性——这就是你导出时能成功写入,但读取时找不到对应属性的原因。OCC的GLTF/GLB导出逻辑里做了TDataStd_NamedData到extras的映射,但导入流程没有反向实现这个逻辑。

不过别担心,我们可以通过自定义节点回调的方式,手动把extras数据导入并关联到对应的模型形状Label上。下面是PythonOCC中的具体实现步骤:

1. 核心思路

利用RWGltf_CafReader提供的AddNodeCallback方法,注册一个回调函数。当读取GLB文件中的每个节点时,我们:

  • 提取节点的extras数据
  • 通过读取上下文找到该节点对应的OCC Label
  • 在Label上创建TDataStd_NamedData属性,并写入extras中的键值对

2. 完整代码示例

from OCC.Core.RWGltf import RWGltf_CafReader, RWGltf_GltfNode
from OCC.Core.TDocStd import TDocStd_Document
from OCC.Core.TDataStd import TDataStd_NamedData
from OCC.Core.TCollection import TCollection_ExtendedString
from OCC.Core.XCAFApp import XCAFApp_Application
from OCC.Core.XCAFDoc import XCAFDoc_DocumentTool_ShapeTool

def handle_node_extras(reader_context, node):
    """回调函数:处理GLB节点的extras数据,关联到OCC Label"""
    # 获取节点的extras(如果存在)
    extras = node.Extras()
    if extras.IsNull():
        return
    
    # 获取该节点对应的OCC Label
    label = reader_context.GetLabelForNode(node.Id())
    if label.IsNull():
        return
    
    # 创建或获取TDataStd_NamedData属性
    named_data = TDataStd_NamedData()
    if not label.FindAttribute(TDataStd_NamedData.GetID(), named_data):
        named_data = TDataStd_NamedData.Set(label)
    
    # 遍历extras中的键值对,写入NamedData
    # 这里假设extras是简单的字符串键值对,复杂结构需要额外解析
    keys = extras.GetKeys()
    for key in keys:
        value = extras.GetValue(key)
        # 根据值类型选择对应的Set方法,这里以字符串为例
        named_data.SetString(TCollection_ExtendedString(key), TCollection_ExtendedString(value))

def read_glb_with_extras(glb_file_path):
    # 初始化文档和应用
    app = XCAFApp_Application.GetApplication()
    doc = TDocStd_Document(TCollection_ExtendedString("GLBImport"))
    app.NewDocument(TCollection_ExtendedString("BinXCAF"), doc)
    
    # 初始化GLB读取器
    reader = RWGltf_CafReader()
    reader.SetDocument(doc)
    
    # 注册节点回调
    reader.AddNodeCallback(handle_node_extras)
    
    # 执行读取
    if not reader.Read(glb_file_path):
        print("GLB文件读取失败")
        return None, None
    
    # 获取形状工具,用于后续访问模型形状
    shape_tool = XCAFDoc_DocumentTool_ShapeTool(doc.Main())
    return doc, shape_tool

# 测试读取
if __name__ == "__main__":
    glb_path = "your_model.glb"
    doc, shape_tool = read_glb_with_extras(glb_path)
    if doc is None:
        exit()
    
    # 遍历所有形状Label,验证extras数据是否导入成功
    labels = []
    shape_tool.GetFreeShapes(labels)
    for label in labels:
        # 获取NamedData属性
        named_data = TDataStd_NamedData()
        if label.FindAttribute(TDataStd_NamedData.GetID(), named_data):
            if named_data.HasStrings():
                print("找到自定义数据:")
                # 遍历所有字符串属性
                keys = named_data.GetStrings()
                for key in keys:
                    value = named_data.GetString(key)
                    print(f"  {key}: {value}")
            # 也可以读取其他类型数据,比如整数、浮点数等
            # if named_data.HasIntegers(): ...

3. 注意事项

  • 数据类型匹配:如果导出时你用了SetInteger/SetReal等方法存储数据,导入时要对应使用GetValueAsInteger/GetValueAsReal等方式解析extras中的值,再调用named_data.SetInteger/named_data.SetReal写入。
  • 复杂extras结构:如果你的extras是嵌套的JSON对象,需要手动解析成TDataStd_NamedData支持的简单类型,或者考虑用TDataStd_ByteArray存储序列化后的JSON字符串。
  • 节点与Label的映射:确保回调中reader_context.GetLabelForNode(node.Id())能正确拿到对应Label,对于组合模型,可能需要遍历子节点的Label来获取所有形状的自定义数据。

这样处理后,你就能同时读取GLB的模型形状和对应的自定义extras数据了。

内容的提问来源于stack exchange,提问作者Sankalp Dhupar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 11:13:10