diff --git a/docs/dna.md b/docs/dna.md
deleted file mode 100644
index 03504dc..0000000
--- a/docs/dna.md
+++ /dev/null
@@ -1,253 +0,0 @@
-## DNA 库
-
-DNA 库作为 DNACalib 的依赖项之一捆绑在本仓库中。
-它提供了读取和写入 MetaHuman DNA 文件的核心功能。
-它使用户能够查询和更改其中包含的信息。
-
-DNACalib 提供了一组用于编辑 MetaHuman DNA 文件的实用命令。在底层,它使用 DNA 库。一些命令只是封装了对 DNA 库的几个调用,而其他命令则包含额外的逻辑。
-虽然用户可以仅使用 DNA 库自己完成所有这些操作,但这些命令旨在让他们的工作更轻松。
-
-## MetaHuman DNA
-
-MetaHuman DNA 是一种文件格式,旨在存储 3D 对象的骨骼和几何体的完整描述。
-仅依靠 MetaHuman DNA 文件,就可以重建对象的完整网格并使其完全装配好骨骼,准备好进行动画制作。在实践中,MetaHuman DNA 文件仅用于存储人物角色的面部。
-
-### 层级
-
-MetaHuman DNA 文件中的数据分为几个逻辑层。这些层通过松散的层级结构连接在一起,其中 MetaHuman DNA 文件中的每个后续层都依赖于其上层中存储的数据。
-
-
-
-可以选择性地只加载 MetaHuman DNA 到指定层。如层级组织图所示,行为层和几何层彼此不依赖。这种独立性对于只需要使用 MetaHuman DNA 文件来驱动骨骼(使用行为层进行运行时评估)而不需要访问几何数据的用例至关重要。
-
-#### 描述符
-
-描述符层包含关于骨骼的基本元数据,例如:
-
- - 角色名称
- - 年龄
- - 面部原型
- - 以键/值对形式的任意字符串元数据
- - 所需的兼容性参数(与高级系统相关,例如用于混合 MetaHuman DNA 文件)
-
-#### 定义
-
-定义层包含骨骼的静态数据,例如:
-
- - 控制器、关节、变形、动画贴图和网格的名称
- - 关节、变形、动画贴图和网格到各个 LOD 的映射
- - 关节层级
- - 绑定姿态(如 T 姿态)中的关节变换
-
-该层包含基于所选 LOD 在后续层中进行过滤所需的信息。
-
-#### 行为
-
-行为层包含骨骼的动态数据,用于:
-
- - 将 GUI 控制器映射到原始控制值
- - 计算修正表情
- - 计算关节变换
- - 计算变形通道权重
- - 计算动画贴图权重
-
-#### 几何
-
-几何层包含重建角色网格所需的所有数据,以及其蒙皮权重和变形目标增量。网格信息本身的结构类似于 OBJ 格式。
-
-### API 概述
-
-在使用 MetaHuman DNA 文件时,使用的两个主要接口是:
-- [`BinaryStreamReader`](/dnacalib/DNACalib/include/dna/BinaryStreamReader.h)
-- [`BinaryStreamWriter`](/dnacalib/DNACalib/include/dna/BinaryStreamWriter.h)
-
-它们用于从二进制流读取数据或将数据写入二进制流。例如,使用 [`FileStream`](/dnacalib/DNACalib/include/trio/streams/FileStream.h) 处理文件时。
-
-这里我们将展示一些展示库基本用法的代码片段。
-DNA 库的一般 API 概述可以在[此处](/docs/dna_api.md)找到。
-
-与 DNACalib 一样,DNA 库是用 C++ 编写的,但有一个 Python 包装器,因此可以从 C++ 和 Python 中使用它。
-
-#### 创建读取器/写入器
-
-##### 读取器
-
-从文件读取二进制 DNA 的函数示例:
-
-```
-def load_dna(path):
- stream = FileStream(path, FileStream.AccessMode_Read, FileStream.OpenMode_Binary)
- reader = BinaryStreamReader(stream, DataLayer_All)
- reader.read()
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error loading DNA: {status.message}")
- return reader
-```
-
-创建读取器时,除了流参数外,还可以指定要加载的数据层。在此示例中,将加载所有层,因为使用了 ```DataLayer_All```,但您可以指定以下任何一项:
-```
-DataLayer_Descriptor
-DataLayer_Definition - 包括描述符和定义
-DataLayer_Behavior - 包括描述符、定义和行为
-DataLayer_Geometry - 包括描述符、定义和几何
-DataLayer_GeometryWithoutBlendShapes - 包括描述符、定义和不含变形的几何
-DataLayer_AllWithoutBlendShapes - 包括除几何中的变形之外的所有内容
-DataLayer_All
-```
-
-例如,如果您只想加载行为层(包括定义和描述符),请使用:
-
-```
-stream = FileStream(path, FileStream.AccessMode_Read, FileStream.OpenMode_Binary)
-reader = BinaryStreamReader(stream, DataLayer_Behavior)
-reader.read()
-if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error loading DNA: {status.message}")
-```
-
-##### 写入器
-
-从文件写入二进制 DNA 的函数示例:
-
-```
-def save_dna(reader, path):
- stream = FileStream(path, FileStream.AccessMode_Write, FileStream.OpenMode_Binary)
- writer = BinaryStreamWriter(stream)
- # 使用所有数据层基于读取器创建写入器(如果没有传递参数给 setFrom(),DataLayer_All 是默认值)
- writer.setFrom(reader)
- # 例如,要仅使用几何层(包括定义和描述符)创建写入器,请使用:
- # writer.setFrom(reader, DataLayer_Geometry)
-
- writer.write()
-
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error saving DNA: {status.message}")
-```
-除了在创建读取器时指定层外,还可以在创建写入器时指定要使用的层(作为 ```setFrom()``` 方法的参数)。
-
-```load_dna``` 和 ```save_dna``` 函数在大多数[`示例`](/examples/)中都有使用。
-
-**注意**: 还有 [`JSONStreamReader`](/dnacalib/DNACalib/include/dna/JSONStreamReader.h) 和 [`JSONStreamWriter`](/dnacalib/DNACalib/include/dna/JSONStreamWriter.h),用于处理 JSON 格式而不是二进制格式的 MetaHuman DNA 文件。但是应该注意,JSON 变体仅用于调试等目的。与二进制读取器和写入器不同,它们的 JSON 对应项不能执行过滤,并且通常会生成更大的文件。
-存储 DNA 文件的推荐格式是二进制格式。
-
-**已知问题**: 目前读取 JSON MetaHuman DNA 文件会失败。此问题将在未来版本中解决。
-
-#### 示例
-
-以下是使用该库的一些示例片段。
-
-##### 示例 1: 读取指定网格的中性顶点位置
-
-```
-dna = load_dna(input_path)
-
-if dna.getMeshCount() == 0:
- print("No meshes found in DNA.")
- return
-
-mesh_index = 0
-xs = dna.getVertexPositionXs(mesh_index)
-ys = dna.getVertexPositionYs(mesh_index)
-zs = dna.getVertexPositionZs(mesh_index)
-```
-
-##### 示例 2: 读取中性关节坐标和关节方向值
-
-```
-dna = load_dna(input_path)
-
-# 读取关节坐标
-neutral_joint_translation_xs = dna.getNeutralJointTranslationXs()
-neutral_joint_translation_ys = dna.getNeutralJointTranslationYs()
-neutral_joint_translation_zs = dna.getNeutralJointTranslationZs()
-
-# 读取关节方向
-neutral_joint_orient_xs = dna.getNeutralJointRotationXs()
-neutral_joint_orient_ys = dna.getNeutralJointRotationYs()
-neutral_joint_orient_zs = dna.getNeutralJointRotationZs()
-```
-
-##### 示例 3: 读取表情的变形目标增量并更改它们
-
-```
-def read_blend_shape_target_deltas(reader, mesh_index, blend_shape_target_index):
- """
- 读取变形目标增量和相应的顶点索引。
- """
-
- vertex_indices = reader.getBlendShapeTargetVertexIndices(
- mesh_index, blend_shape_target_index
- )
- blend_shape_target_delta_count = reader.getBlendShapeTargetDeltaCount(
- mesh_index, blend_shape_target_index
- )
- deltas = []
- for delta_index in range(blend_shape_target_delta_count):
- x, y, z = reader.getBlendShapeTargetDelta(
- mesh_index, blend_shape_target_index, delta_index
- )
- deltas.append([x, y, z])
- return vertex_indices, deltas
-
-# 读取然后更改表情 "jaw_open" 的变形目标增量,网格为 "head_lod0_mesh"
-input_dna = load_dna(input_path)
-
-mesh_name = "head_lod0_mesh"
-mesh_count = input_dna.getMeshCount()
-head_mesh_index = 0
-for mesh_index in range(mesh_count):
- if input_dna.getMeshName(mesh_index) == mesh_name:
- head_mesh_index = mesh_index
- break
-
-bs_target_count = input_dna.getBlendShapeTargetCount(head_mesh_index)
-expr_name = "jaw_open"
-
-# 获取指定表情的变形目标索引
-for i in range(bs_target_count):
- bs_channel_index = input_dna.getBlendShapeChannelIndex(head_mesh_index, i)
- bs_name = input_dna.getBlendShapeChannelName(bs_channel_index)
- if bs_name == expr_name:
- bs_target_index = i
- break
-
-vertex_indices, deltas = read_blend_shape_target_deltas(input_dna, head_mesh_index, bs_target_index)
-
-# 修改增量(在本例中,只是给每个增量加 1.0)
-for i in range(len(deltas)):
- deltas[i][0] += 1.0
- deltas[i][1] += 1.0
- deltas[i][2] += 1.0
-
-# 从输入 DNA 创建写入器 DNA
-output_stream = dna.FileStream(outputPath, dna.FileStream.AccessMode_Write, dna.FileStream.OpenMode_Binary)
-
-# 在此示例中,为了调试目的,以 JSON 格式写入 DNA,以快速查看变形增量是否已更改
-output_dna = dna.JSONStreamWriter(output_stream)
-output_dna.setFrom(input_dna)
-
-# 为表情写入新的变形增量值
-output_dna.setBlendShapeTargetDeltas(mesh_index, bs_target_index, deltas)
-
-# 如果您以删除或添加某些增量的方式修改了增量,
-# 那么您还必须设置与新增量对应的新顶点索引:
-# output_dna.setBlendShapeTargetVertexIndices(mesh_index, bs_target_index, new_vertex_indices)
-
-# 写入具有修改值的 DNA
-output_dna.write()
-
-if not dna.Status.isOk():
- status = dna.Status.get()
- raise RuntimeError("Error saving DNA: {}".format(status.message))
-```
-
-### 使用
-
-有一些简短的[`示例`](/examples)涵盖了用户在使用 MetaHuman DNA 时可能遇到的一些情况。
-其中包括:
- - [`将二进制 DNA 文件内容写入 JSON 格式以供检查`](/examples/dna_binary_to_json_demo.py)
- - [`从 DNA 中清除所有变形数据`](/examples/dnacalib_clear_blend_shapes.py)
- - [`从 DNA 中删除某些 LOD`](/examples/dnacalib_lod_demo.py)
diff --git a/docs/dna_api.md b/docs/dna_api.md
deleted file mode 100644
index 1b35607..0000000
--- a/docs/dna_api.md
+++ /dev/null
@@ -1,564 +0,0 @@
-# DNA API 概述
-
-以下是用于读取和写入 DNA 文件的主要方法概述。
-以下文档适用于 C++。目前尚无 Python 文档。
-
-如[此处](/docs/dna.md#api-overview)所述,有一些类用于从流中读取 DNA 或将其写入流。这些类包括:
-- [BinaryStreamReader](/dnacalib/DNACalib/include/dna/BinaryStreamReader.h)
-- [BinaryStreamWriter](/dnacalib/DNACalib/include/dna/BinaryStreamWriter.h)
-- [JSONStreamReader](/dnacalib/DNACalib/include/dna/JSONStreamReader.h)
-- [JSONStreamWriter](/dnacalib/DNACalib/include/dna/JSONStreamWriter.h)
-
-创建读取器后,可以用它来查询 DNA 中包含的不同信息。
-创建写入器后,可以用它来在 DNA 中设置新值。
-
-这是通过本页列出的方法完成的。这些方法根据 DNA 文件中的[层级](/docs/dna.md#layers)进行分组。
-
-**注意**: 本页并未列出所有可用方法。有关此处列出的方法的更多详细信息以及所有可用方法的列表,请参阅相应的读取器和/或写入器[文档](/dnacalib/DNACalib/include/dna/layers)。
-
-## BinaryStreamReader
-包含用于创建和销毁 [BinaryStreamReader](/dnacalib/DNACalib/include/dna/BinaryStreamReader.h) 的方法。
-创建 BinaryStreamReader 时,用户可以通过指定要加载的 LOD 来过滤 DNA 文件中的数据。如[此处](/docs/dna.md#reader)所述,还可以通过指定要加载的数据层来进行过滤。
-
-- `create(stream, layer = DataLayer::All, maxLOD = 0u, memRes = nullptr)`
- BinaryStreamReader 的工厂方法。
- 参数:
- `stream` - 将从中读取数据的源流。
- `layer` - 指定需要加载的数据层。
- `maxLOD` - 要加载的最大细节级别。值为零表示加载所有 LOD。
- `memRes` - 用于分配的内存资源。如果未提供内存资源,将使用默认分配机制。用户负责通过调用 destroy 释放返回的指针。
-
-- `create(stream, layer, maxLOD, minLOD, memRes = nullptr)`
- BinaryStreamReader 的工厂方法。
- 参数:
- `stream` - 将从中读取数据的源流。
- `layer` - 指定需要加载的数据层。
- `maxLOD` - 要加载的最大细节级别。
- `minLOD` - 要加载的最小细节级别。maxLOD / minLOD 的范围为 [0, LOD 总数 - 1] 表示加载所有 LOD。
- `memRes` - 用于分配的内存资源。如果未提供内存资源,将使用默认分配机制。用户负责通过调用 destroy 释放返回的指针。
-
-- `create(stream, layer, lods, lodCount, memRes = nullptr)`
- BinaryStreamReader 的工厂方法。
- 参数:
- `stream` - 将从中读取数据的源流。
- `layer` - 指定需要加载的数据层。
- `lods` - 指定要加载的具体 LOD 的数组。
- `lodCount` - lods 数组中的元素数量。
- `memRes` - 用于分配的内存资源。如果未提供内存资源,将使用默认分配机制。用户负责通过调用 destroy 释放返回的指针。
-
-- `destroy(instance)`
- 用于释放 BinaryStreamReader 实例的方法。
- 参数:
- `instance` - 要释放的 BinaryStreamReader 实例。
-
-## BinaryStreamWriter
-- `create(stream, memRes = nullptr)`
- BinaryStreamWriter 的工厂方法。
- 参数:
- `stream` - 将向其写入数据的流。
- `memRes` - 用于分配的内存资源。如果未提供内存资源,将使用默认分配机制。用户负责通过调用 destroy 释放返回的指针。
-
-- `destroy(BinaryStreamWriter* instance)`
- 用于释放 BinaryStreamWriter 实例的方法。
- 参数:
- `instance` - 要释放的 BinaryStreamWriter 实例。
-
-## JSONStreamReader
-- `create(stream, memRes = nullptr)`
- JSONStreamReader 的工厂方法。
- 参数:
- `stream` - 将从中读取数据的源流。
- `memRes` - 用于分配的内存资源。如果未提供内存资源,将使用默认分配机制。用户负责通过调用 destroy 释放返回的指针。
-
-- `destroy(instance)`
- 用于释放 JSONStreamReader 实例的方法。
- 参数:
- `instance` - 要释放的 JSONStreamReader 实例。
-
-## JSONStreamWriter
-- `create(stream, indentWidth = 4u, memRes = nullptr)`
- JSONStreamWriter 的工厂方法。
- 参数:
- `stream` - 将向其写入数据的流。
- `indentWidth` - 用于缩进的空格数。
- `memRes` - 用于分配的内存资源。如果未提供内存资源,将使用默认分配机制。用户负责通过调用 destroy 释放返回的指针。
-
-- `destroy(instance)`
- 用于释放 JSONStreamWriter 实例的方法。
- 参数:
- `instance` - 要释放的 JSONStreamWriter 实例。
-
-## setFrom() 方法
-除了创建写入器的方法外,BinaryStreamReader 和 JSONStreamReader 都有一个从 [Writer](/dnacalib/DNACalib/include/dna/Writer.h) 继承的 setFrom() 方法,用于使用读取器中的数据初始化写入器。
-使用此方法时,用于初始化写入器的数据可以按数据层进行过滤。
-- `setFrom(source, layer = DataLayer::All, memRes = nullptr)`
- 从给定的读取器初始化写入器。
- 此函数通过调用读取器的每个 getter 函数并将返回值传递给写入器中的匹配 setter 函数,将所有数据从给定的读取器复制到写入器实例中。
- 参数:
- `source` - 需要从中复制数据的源 DNA 读取器。
- `layer` - 限制应从给定源读取器接管哪些层。
- `memRes` - 用于复制期间临时分配的可选内存资源。
-
-## 读取器方法
-### DescriptorReader
-包含用于访问角色和骨骼各种元数据的只读访问器。
-
-- `getName()`
- 角色名称。
-- `getArchetype()`
- 角色原型。
-- `getGender()`
- 角色性别。
-- `getAge()`
- 角色年龄。
-- `getTranslationUnit()`
- 使用的平移单位(厘米或米)。
-- `getRotationUnit()`
- 使用的旋转单位(度或弧度)。
-- `getCoordinateSystem()`
- 使用的坐标系统(x、y 和 z 轴的方向)。
-- `getLODCount()`
- 可用的细节级别(例如 6 表示以下级别可用:[0,1,2,3,4,5],其中 0 是细节最高的 LOD,5 是细节最低的 LOD)。
-- `getDBMaxLOD()`
- 此角色的 DNA 数据中存储的最大细节级别。该值相对于数据库中的 LOD-0。
-- `getDBComplexity()`
- 用于驱动此角色骨骼的输入控制接口的名称。此参数表示角色的输入控制复杂度。
-- `getDBName()`
- 角色源自的数据库的名称。来自同一数据库的所有角色必须具有相同的定义,但可能具有不同的复杂度或 LOD。
-
-### DefinitionReader
-包含用于表示骨骼静态数据的 DNA 属性的只读访问器。
-
-- `getGUIControlCount()`
- GUI 控制器的数量。
-- `getGUIControlName(index)`
- 请求的 GUI 控制器的名称。
-- `getRawControlCount()`
- 原始控制器的数量。
-- `getRawControlName(index)`
- 请求的原始控制器的名称。
-- `getJointCount()`
- 关节的数量。
-- `getJointName(index)`
- 请求的关节的名称。
-- `getJointIndicesForLOD(lod)`
- 指定 LOD 的关节索引列表。
-- `getJointParentIndex(index)`
- 请求的关节父级的索引。
- 可以使用此函数遍历和重建关节层级。示例:
- 关节名称: [A, B, C, D, E, F, G, H, I]
- 层级结构: [0, 0, 0, 1, 1, 4, 2, 6, 2]
- 描述了以下层级结构:
- ```
- A
- ├── B
- │ ├── D
- │ └── E
- │ └── F
- └── C
- ├── G
- │ └── H
- └── I
- ```
- 请求关节 5(关节名称:F)的父级索引将返回 4(关节名称:E)。
- 请求根关节的父级索引:0(关节名称:A)将返回相同的索引 0。
-- `getBlendShapeChannelCount()`
- 变形通道的数量。
-- `getBlendShapeChannelName(index)`
- 请求的变形通道的名称。
-- `getBlendShapeChannelIndicesForLOD(lod)`
- 指定 LOD 的变形通道索引列表。
-- `getAnimatedMapCount()`
- 动画贴图的数量。
-- `getAnimatedMapName(index)`
- 请求的动画贴图的名称。
-- `getAnimatedMapIndicesForLOD(lod)`
- 指定 LOD 的动画贴图索引列表。
-- `getMeshCount()`
- 网格的数量。
-- `getMeshName(index)`
- 请求的网格的名称。
-- `getMeshIndicesForLOD(lod)`
- 指定 LOD 的网格索引列表。
-- `getMeshBlendShapeChannelMappingCount()`
- 网格-变形通道映射项的数量。
-- `getMeshBlendShapeChannelMapping(index)`
- 保存指定映射索引的网格索引和相关变形通道索引的结构。
-- `getMeshBlendShapeChannelMappingIndicesForLOD(lod)`
- 指定 LOD 的网格-变形通道映射索引列表。
-- `getNeutralJointTranslation(index)`
- 绑定姿态下关节的平移值(x, y, z)。
-- `getNeutralJointTranslationXs()`
- 绑定姿态下所有关节的 X 轴平移值列表。
-- `getNeutralJointTranslationYs()`
- 绑定姿态下所有关节的 Y 轴平移值列表。
-- `getNeutralJointTranslationZs()`
- 绑定姿态下所有关节的 Z 轴平移值列表。
-- `getNeutralJointRotation(index)`
- 绑定姿态下关节的旋转值(x, y, z)。
-- `getNeutralJointRotationXs()`
- 绑定姿态下所有关节的 X 轴旋转值列表。
-- `getNeutralJointRotationYs()`
- 绑定姿态下所有关节的 Y 轴旋转值列表。
-- `getNeutralJointRotationZs()`
- 绑定姿态下所有关节的 Z 轴旋转值列表。
-
-### BehaviorReader
-包含用于定义骨骼评估的 DNA 属性的只读访问器。
-
-- `getGUIToRawInputIndices()`
- 用于将 GUI 映射到原始控制器的输入索引。
-- `getGUIToRawOutputIndices()`
- 用于将 GUI 映射到原始控制器的输出索引。
-- `getGUIToRawFromValues()`
- 在 GUI 到原始控制器映射期间用于决定是否应评估特定条目的过滤值(下限)。
-- `getGUIToRawToValues()`
- 在 GUI 到原始控制器映射期间用于决定是否应评估特定条目的过滤值(上限)。
-- `getGUIToRawSlopeValues()`
- 在 GUI 到原始控制器映射期间用于计算输出值的计算值(斜率/梯度)。
-- `getGUIToRawCutValues()`
- 在 GUI 到原始控制器映射期间用于计算输出值的计算值(垂直截距)。
-- `getPSDCount()`
- 不同 PSD 表情的数量。
-- `getPSDRowIndices()`
- PSD(输入)索引。
-- `getPSDColumnIndices()`
- 控制器(输入)索引。
-- `getPSDValues()`
- 与每个 PSD 行和列对相关联的权重。
-- `getJointRowCount()`
- 完整未压缩关节矩阵中的行数。
-- `getJointColumnCount()`
- 完整未压缩关节矩阵中的列数。
-- `getJointVariableAttributeIndices(lod)`
- 请求的 LOD 的关节属性索引(输出索引)。
-- `getJointGroupCount()`
- 整个关节矩阵中存在的关节组数量。
-- `getJointGroupLODs(jointGroupIndex)`
- 请求的关节组中每个细节级别的行数。
- 每个元素的位置代表级别本身,而值表示属于该级别的关节组内的行数。例如:
- ```
- [12, 9, 3]
- │ │ └── LOD-2 包含前 3 行
- │ └── LOD-1 包含前 9 行
- └── LOD-0 包含前 12 行
- ```
-- `getJointGroupInputIndices(jointGroupIndex)`
- 请求的关节组包含的列索引。这些列索引指向完整的未压缩关节矩阵。
-- `getJointGroupOutputIndices(jointGroupIndex)`
- 请求的关节组包含的行索引。这些行索引指向完整的未压缩关节矩阵。
-- `getJointGroupValues(jointGroupIndex)`
- 请求的关节组包含的值。
-- `getJointGroupJointIndices(jointGroupIndex)`
- 请求的关节组包含的关节索引。
-- `getBlendShapeChannelLODs()`
- 变形通道每个细节级别的输入索引数量。
- 每个元素的位置代表级别本身(例如 [0,1,2,3,4,5] 值 0 是最高细节的 LOD,值 5 是最低细节的 LOD),而值表示属于该级别的输入索引数量。
-- `getBlendShapeChannelInputIndices()`
- 用于索引输入向量的输入索引。
-- `getBlendShapeChannelOutputIndices()`
- 指定变形通道输出值位置的输出索引。
-- `getAnimatedMapLODs()`
- 动画贴图每个细节级别的行数。
- 每个元素的位置代表级别本身(例如 [0,1,2,3,4,5] 值 0 是最高细节的 LOD,值 5 是最低细节的 LOD),而值表示属于该级别的行数(在条件表中)。
-- `getAnimatedMapInputIndices()`
- 用于索引输入值数组的输入索引。
-- `getAnimatedMapOutputIndices()`
- 指定计算输出值位置的输出索引。
-- `getAnimatedMapFromValues()`
- 用于决定是否应评估特定条目的过滤值(下限)。
-- `getAnimatedMapToValues()`
- 用于决定是否应评估特定条目的过滤值(上限)。
-- `getAnimatedMapSlopeValues()`
- 用于计算输出值的计算值(斜率/梯度)。
-- `getAnimatedMapCutValues()`
- 用于计算输出值的计算值(垂直截距)。
-
-### GeometryReader
-包含与骨骼相关的几何数据的只读访问器。
-
-- `getVertexPositionCount(meshIndex)`
- 整个网格中顶点位置的数量。
-- `getVertexPosition(meshIndex, vertexIndex)`
- 指定网格中指定顶点的位置。顶点按顶点 ID 排序。
-- `getVertexPositionXs(meshIndex)`
- 引用网格的所有顶点位置 X 值列表。
-- `getVertexPositionYs(meshIndex)`
- 引用网格的所有顶点位置 Y 值列表。
-- `getVertexPositionZs(meshIndex)`
- 引用网格的所有顶点位置 Z 值列表。
-- `getVertexTextureCoordinateCount(meshIndex)`
- 整个网格中纹理坐标的数量。
-- `getVertexTextureCoordinate(meshIndex, textureCoordinateIndex)`
- 指定网格中指定索引的纹理坐标。
-- `getVertexTextureCoordinateUs(meshIndex)`
- 引用网格的所有纹理坐标 U 值列表。
-- `getVertexTextureCoordinateVs(meshIndex)`
- 引用网格的所有纹理坐标 V 值列表。
-- `getVertexNormalCount(meshIndex)`
- 整个网格中顶点法线的数量。
-- `getVertexNormal(meshIndex, normalIndex)`
- 指定网格中指定索引的顶点法线。
-- `getVertexNormalXs(meshIndex)`
- 引用网格的所有法线 X 值列表。
-- `getVertexNormalYs(meshIndex)`
- 引用网格的所有法线 Y 值列表。
-- `getVertexNormalZs(meshIndex)`
- 引用网格的所有法线 Z 值列表。
-- `getVertexLayoutCount(meshIndex)`
- 整个网格中顶点布局的数量。顶点布局是顶点属性的集合。
-- `getVertexLayout(meshIndex, layoutIndex)`
- 顶点布局仅包含可用于查询与顶点关联的实际属性(如位置、纹理坐标和法线)的属性索引。布局中的索引可与上述定义的 API 一起使用。
-- `getVertexLayoutPositionIndices(meshIndex)`
- 引用网格中每个顶点的位置索引。
-- `getVertexLayoutTextureCoordinateIndices(meshIndex)`
- 引用网格中每个顶点的纹理坐标索引。
-- `getVertexLayoutNormalIndices(meshIndex)`
- 引用网格中每个顶点的法线索引。
-- `getFaceCount(meshIndex)`
- 指定网格所包含的面的数量。
-- `getFaceVertexLayoutIndices(meshIndex, faceIndex)`
- 属于指定网格上某个面的顶点布局索引列表。
-- `getMaximumInfluencePerVertex(meshIndex)`
- 可能影响任何单个顶点的最大关节数量。
-- `getSkinWeightsCount(meshIndex)`
- 与指定网格关联的蒙皮权重数量。
-- `getSkinWeightsValues(meshIndex, vertexIndex)`
- 影响请求顶点的蒙皮权重列表。
-- `getSkinWeightsJointIndices(meshIndex, vertexIndex)`
- 与指定顶点的每个蒙皮权重关联的关节索引列表。关节索引的存储顺序与其关联的权重相同。
-- `getBlendShapeTargetCount(meshIndex)`
- 属于指定网格的变形目标数量。
-- `getBlendShapeChannelIndex(meshIndex, blendShapeTargetIndex)`
- 请求的变形目标对应的变形通道索引。
-- `getBlendShapeTargetDeltaCount(meshIndex, blendShapeTargetIndex)`
- 属于指定变形目标的增量数量。
-- `getBlendShapeTargetDelta(meshIndex, blendShapeTargetIndex, deltaIndex)`
- 每个受影响顶点的增量列表。
-- `getBlendShapeTargetDeltaXs(meshIndex, blendShapeTargetIndex)`
- 引用变形目标的所有增量 X 值列表。
-- `getBlendShapeTargetDeltaYs(meshIndex, blendShapeTargetIndex)`
- 引用变形目标的所有增量 Y 值列表。
-- `getBlendShapeTargetDeltaZs(meshIndex, blendShapeTargetIndex)`
- 引用变形目标的所有增量 Z 值列表。
-- `getBlendShapeTargetVertexIndices(meshIndex, blendShapeTargetIndex)`
- 受引用变形目标影响的顶点位置索引。顶点位置索引的存储顺序与其关联的增量相同。这些索引可以通过 getVertexPosition 用于查询关联的顶点本身。
-
-## Writer methods
-
-### DescriptorWriter
-包含用于访问角色和骨骼各种元数据的只写访问器。
-
-- `setName(name)`
- Sets character name.
-- `setArchetype(archetype)`
- Sets character archetype.
-- `setGender(gender)`
- Sets character gender.
-- `setAge(age)`
- Sets character age.
-- `setTranslationUnit(unit)`
- Sets translation unit (cm or m).
-- `setRotationUnit(unit)`
- Sets rotation unit (degrees or radians).
-- `setCoordinateSystem(system)`
- Sets coordinate system (directions of the axes).
-- `setLODCount(lodCount)`
- Sets available levels of detail (e.g. 6 which means the following levels are available: [0,1,2,3,4,5], where 0 is the LOD with the highest details, and 5 is the LOD with lowest details).
-- `setDBMaxLOD(lod)`
- Sets the maximum level of detail stored in the DNA data for this character.
-- `setDBComplexity(name)`
- Sets name of the input control interface used to drive this character rig.
-- `setDBName(name)`
- Sets name of the database from which the character originates.
-
-### DefinitionWriter
-包含用于表示骨骼静态数据的 DNA 属性的只写访问器。
-
-- `clearGUIControlNames()`
- 删除所有存储的 GUI 控制器名称。
-- `setGUIControlName(index, name)`
- 设置指定 GUI 控制器的名称。
-- `clearRawControlNames()`
- 删除所有存储的原始控制器名称。
-- `setRawControlName(index, name)`
- 设置指定原始控制器的名称。
-- `clearJointNames()`
- 删除所有存储的关节名称。
-- `setJointName(index, name)`
- 设置指定关节的名称。
-- `clearJointIndices()`
- 删除所有存储的关节索引。
-- `setJointIndices(index, jointIndices, count)`
- 将关节索引列表存储到指定索引。该索引表示整个关节索引列表的位置,而不是其单个元素的位置,即关节索引 2D 矩阵中的行索引。
-- `clearLODJointMappings()`
- 删除所有存储的 LOD 到关节列表索引的映射条目。
-- `setLODJointMapping(lod, index)`
- 设置哪些关节属于哪个细节级别。
-- `clearBlendShapeChannelNames()`
- 删除所有存储的变形通道名称。
-- `setBlendShapeChannelName(index, name)`
- 设置指定变形通道的名称。
-- `clearBlendShapeChannelIndices()`
- 删除所有存储的变形通道索引。
-- `setBlendShapeChannelIndices(index, blendShapeChannelIndices, count)`
- 将变形通道名称索引列表存储到指定索引。该索引表示整个变形通道索引列表的位置,而不是其单个元素的位置,即变形通道索引 2D 矩阵中的行索引。
-- `clearLODBlendShapeChannelMappings()`
- 删除所有存储的 LOD 到变形通道列表索引的映射条目。
-- `setLODBlendShapeChannelMapping(lod, index)`
- 设置哪些变形通道属于哪个细节级别。
-- `clearAnimatedMapNames()`
- 删除所有存储的动画贴图名称。
-- `setAnimatedMapName(index, name)`
- 设置指定动画贴图的名称。
-- `clearAnimatedMapIndices()`
- 删除所有存储的动画贴图索引。
-- `setAnimatedMapIndices(index, animatedMapIndices, count)`
- 将动画贴图名称索引列表存储到指定索引。该索引表示整个动画贴图索引列表的位置,而不是其单个元素的位置,即动画贴图索引 2D 矩阵中的行索引。
-- `clearLODAnimatedMapMappings()`
- 删除所有存储的 LOD 到动画贴图列表索引的映射条目。
-- `setLODAnimatedMapMapping(lod, index)`
- 设置哪些动画贴图属于哪个细节级别。
-- `clearMeshNames()`
- 删除所有存储的网格名称。
-- `setMeshName(index, name)`
- 设置指定网格的名称。
-- `clearMeshIndices()`
- 删除所有存储的网格索引。
-- `setMeshIndices(index, meshIndices, count)`
- 将网格名称索引列表存储到指定索引。该索引表示整个网格索引列表的位置,而不是其单个元素的位置,即网格索引 2D 矩阵中的行索引。
-- `clearLODMeshMappings()`
- 删除所有存储的 LOD 到网格列表索引的映射条目。
-- `setLODMeshMapping(lod, index)`
- 设置哪些网格属于哪个细节级别。
-- `clearMeshBlendShapeChannelMappings()`
- 删除所有存储的网格到变形通道的映射条目。
-- `setMeshBlendShapeChannelMapping(index, meshIndex, blendShapeChannelIndex)`
- 将变形通道与其网格关联。
-- `setJointHierarchy(jointIndices, count)`
- 设置描述关节之间父子关系的简单数组。
- 示例:
- 关节名称: [A, B, C, D, E, F, G, H]
- 层级结构: [0, 0, 0, 1, 1, 4, 2, 2]
- 描述了以下层级结构:
- ```
- A
- ├── B
- │ ├── D
- │ └── E
- │ └── F
- └── C
- ├── G
- └── H
- ```
-- `setNeutralJointTranslations(translations, count)`
- 设置绑定姿态下关节的平移值。
-- `setNeutralJointRotations(rotations, count)`
- 设置绑定姿态下关节的旋转值。
-
-### BehaviorWriter
-包含用于定义骨骼评估的 DNA 属性的只写访问器。
-
-- `setGUIToRawInputIndices(inputIndices, count)`
- 设置用于将 GUI 映射到原始控制器的输入索引。
-- `setGUIToRawOutputIndices(outputIndices, count)`
- 设置用于将 GUI 映射到原始控制器的输出索引。
-- `setGUIToRawFromValues(fromValues, count)`
- 设置在 GUI 到原始控制器映射期间用于决定是否应评估特定条目的过滤值(下限)。
-- `setGUIToRawToValues(toValues, count)`
- 设置在 GUI 到原始控制器映射期间用于决定是否应评估特定条目的过滤值(上限)。
-- `setGUIToRawSlopeValues(slopeValues, count)`
- 设置在 GUI 到原始控制器映射期间用于计算输出值的计算值(斜率/梯度)。
-- `setGUIToRawCutValues(cutValues, count)`
- 设置在 GUI 到原始控制器映射期间用于计算输出值的计算值(垂直截距)。
-- `setPSDCount(count)`
- 设置不同 PSD 表情的数量。
-- `setPSDRowIndices(rowIndices, count)`
- 设置将成为 PSD 矩阵行的 PSD(输入)索引。
-- `setPSDColumnIndices(columnIndices, count)`
- 设置将成为 PSD 矩阵列的控制器(输入)索引。
-- `setPSDValues(weights, count)`
- 设置与每个 PSD 行和列对相关联的权重。
-- `setJointRowCount(rowCount)`
- 设置完整未压缩关节矩阵中的行数。
-- `setJointColumnCount(columnCount)`
- 设置完整未压缩关节矩阵中的列数。
-- `clearJointGroups()`
- 删除所有关节组。
-- `deleteJointGroup(jointGroupIndex)`
- 删除指定的关节组。
-- `setJointGroupLODs(jointGroupIndex, lods, count)`
- 设置指定关节组中每个细节级别的行数。
- 每个元素的位置代表级别本身,而值表示属于该级别的关节组内的行数。例如:
- ```
- [12, 9, 3]
- │ │ └── LOD-2 包含前 3 行
- │ └── LOD-1 包含前 9 行
- └── LOD-0 包含前 12 行
- ```
-- `setJointGroupInputIndices(jointGroupIndex, inputIndices, count)`
- 设置指定关节组包含的列索引。这些列索引指向完整的未压缩关节矩阵。
-- `setJointGroupOutputIndices(jointGroupIndex, outputIndices, count)`
- 设置指定关节组包含的行索引。这些行索引指向完整的未压缩关节矩阵。
-- `setJointGroupValues(jointGroupIndex, values, count)`
- 设置指定关节组包含的值。
-- `setJointGroupJointIndices(jointGroupIndex, jointIndices, count)`
- 设置指定关节组包含的关节索引。
-- `setBlendShapeChannelLODs(lods, count)`
- 设置变形通道每个细节级别的输入索引数量。
- 每个元素的位置代表级别本身(例如 [0,1,2,3,4,5] 值 0 是最高细节的 LOD,值 5 是最低细节的 LOD),而值表示属于该级别的输入索引数量。
-- `setBlendShapeChannelInputIndices(inputIndices, count)`
- 设置用于索引输入向量的输入索引。
-- `setBlendShapeChannelOutputIndices(outputIndices, count)`
- 设置指定变形通道输出值位置的输出索引。
-- `setAnimatedMapLODs(lods, count)`
- 设置动画贴图每个细节级别的行数。
- 每个元素的位置代表级别本身(例如 [0,1,2,3,4,5] 值 0 是最高细节的 LOD,值 5 是最低细节的 LOD),而值表示属于该级别的行数(在条件表中)。
-- `setAnimatedMapInputIndices(inputIndices, count)`
- 设置用于索引输入值数组的输入索引。
-- `setAnimatedMapOutputIndices(outputIndices, count)`
- 设置指定计算输出值位置的输出索引。
-- `setAnimatedMapFromValues(fromValues, count)`
- 设置用于决定是否应评估特定条目的过滤值(下限)。
-- `setAnimatedMapToValues(toValues, count)`
- 设置用于决定是否应评估特定条目的过滤值(上限)。
-- `setAnimatedMapSlopeValues(slopeValues, count)`
- 设置用于计算输出值的计算值(斜率/梯度)。
-- `setAnimatedMapCutValues(cutValues, count)`
- 设置用于计算输出值的计算值(垂直截距)。
-
-### GeometryWriter
-包含与骨骼相关的几何数据的只写访问器。
-
-- `clearMeshes()`
- 删除所有网格。
-- `deleteMesh(meshIndex)`
- 删除指定的网格。
-- `setVertexPositions(meshIndex, positions, count)`
- 设置顶点位置。
-- `setVertexTextureCoordinates(meshIndex, textureCoordinates, count)`
- 设置顶点纹理坐标。
-- `setVertexNormals(meshIndex, normals, count)`
- 设置顶点法线。
-- `setVertexLayouts(meshIndex, layouts, count)`
- 设置属于指定网格的顶点布局。
-- `clearFaceVertexLayoutIndices(meshIndex)`
- 删除指定网格的所有顶点布局索引列表。
-- `setFaceVertexLayoutIndices(meshIndex, faceIndex, layoutIndices, count)`
- 设置属于指定面的顶点布局索引。布局索引指向通过 setVertexLayouts() 设置的数组。
-- `setMaximumInfluencePerVertex(meshIndex, maxInfluenceCount)`
- 设置可能影响任何单个顶点的最大关节数量。
-- `clearSkinWeights(meshIndex)`
- 删除指定网格的所有蒙皮权重。
-- `setSkinWeightsValues(meshIndex, vertexIndex, weights, count)`
- 设置影响引用顶点的蒙皮权重。权重总和必须等于 1。
-- `setSkinWeightsJointIndices(meshIndex, vertexIndex, jointIndices, count)`
- 设置与指定顶点的每个蒙皮权重关联的关节索引。关节索引必须按与其关联的权重相同的顺序存储。
-- `clearBlendShapeTargets(meshIndex)`
- 删除指定网格的所有变形目标。
-- `setBlendShapeChannelIndex(meshIndex, blendShapeTargetIndex, blendShapeChannelIndex)`
- 设置指定变形目标对应的变形通道索引。将网格本地变形目标索引与定义层中的绝对变形通道索引关联。
-- `setBlendShapeTargetDeltas(meshIndex, blendShapeTargetIndex, deltas, count)`
- 设置每个受影响顶点的增量。
-- `setBlendShapeTargetVertexIndices(meshIndex, blendShapeTargetIndex, vertexIndices, count)`
- 设置受指定变形目标影响的顶点位置索引。顶点位置索引必须按与其关联的增量相同的顺序存储。
diff --git a/docs/dna_viewer.md b/docs/dna_viewer.md
deleted file mode 100644
index 45f857f..0000000
--- a/docs/dna_viewer.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# DNAViewer
-[`dna_viewer`](/dna_viewer) 包含从 DNA 文件读取和在 Maya 中创建功能性骨骼所需的所有类。
-它的组织方式使每个选项都可配置,因此您可以轻松获得想要的确切结果。
-
-## 示例
-- [生成骨骼](/examples/dna_viewer_build_rig.py)
-- [按 LOD 导出 FBX](/examples/dna_viewer_export_fbx.py)
-- [将 Maya 场景的更改传播到 DNA](/examples/dna_viewer_grab_changes_from_scene_and_propagate_to_dna.py)
-- [简单 UI](/examples/dna_viewer_run_in_maya.py)
-
-## 从代码使用
-有两个 [API](dna_viewer_api.md):
- - [build_meshes](dna_viewer_api_build_meshes.md)
- - [build_rig](dna_viewer_api_build_rig.md)
-
-## 在 Maya 中使用
-在 Maya 中的使用说明位于[此处](/docs/dna_viewer_maya.md)
-
-## 文件夹结构
-
-- [builder](/dna_viewer/builder) - 包含构建器类,用于轻松添加配置选项并构建场景、配置、网格等。
-- [dnalib](/dna_viewer/dnalib) - 包含用于更好地访问 DNA 文件的 API 类。
-- [ui](/dna_viewer/ui) - 包含 Maya UI 所需的类。
-
-## 工作原理
-
-一般流程如下:
-
-
-
-场景构建过程的流程如下:
-
-
-
-骨骼构建过程的流程如下:
-
-
-
-图例:
-- 蓝色: 构建器相关
-- 绿色: 配置相关
-- 棕色: 模型相关
-- 紫色: 读取器相关
diff --git a/docs/dna_viewer_API.md b/docs/dna_viewer_API.md
deleted file mode 100644
index 1491c59..0000000
--- a/docs/dna_viewer_API.md
+++ /dev/null
@@ -1,54 +0,0 @@
-# 环境设置
-
-为了能够从 dna_viewer 导入,需要设置环境。这可以通过在下面提到的任何示例开头添加以下代码来完成:
-
-```
-from sys import path as syspath, platform
-from os import environ, path as ospath
-
-ROOT_DIR = fr"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/") # 如果使用 Maya,请使用绝对路径
-ROOT_LIB_DIR = fr"{ROOT_DIR}/lib"
-if platform == "win32":
- LIB_DIR = f"{ROOT_LIB_DIR}/windows"
-elif platform == "linux":
- LIB_DIR = f"{ROOT_LIB_DIR}/linux"
-else:
- raise OSError("不支持的操作系统,请编译依赖项并添加 LIB_DIR 值")
-
-
-if "MAYA_PLUG_IN_PATH" in environ:
- separator = ":" if platform == "linux" else ";"
- environ["MAYA_PLUG_IN_PATH"] = separator.join([environ["MAYA_PLUG_IN_PATH"], LIB_DIR])
-else:
- environ["MAYA_PLUG_IN_PATH"] = LIB_DIR
-
-syspath.append(ROOT_DIR)
-syspath.append(LIB_DIR)
-```
-
-从 Maya 运行时,应将 `ROOT_DIR` 设置为仓库根目录的绝对路径。
-
-# DNA
-
-## 加载 DNA
-
-加载 DNA 并返回一个 [`DNA`](../dna_viewer/dnalib/dnalib.py#L13) 对象。
-
-```
-from dna_viewer import DNA
-
-dna_ada = DNA(DNA_PATH_ADA)
-dna_taro = DNA(DNA_PATH_TARO)
-```
-
-这使用以下参数:
-- `dna_path: str` - 要使用的 DNA 文件的路径。
-- `layers: Optional[List[Layer]]` - 要加载的 DNA 部分列表。如果未传递任何内容,将加载整个 DNA。等同于传递 Layer.all。
-
-## 构建网格
-
-构建网格 API 说明位于[此处](/docs/dna_viewer_api_build_meshes.md)。
-
-## 构建骨骼
-
-构建骨骼 API 说明位于[此处](/docs/dna_viewer_api_build_rig.md)。
\ No newline at end of file
diff --git a/docs/dna_viewer_api_build_meshes.md b/docs/dna_viewer_api_build_meshes.md
deleted file mode 100644
index 66fea97..0000000
--- a/docs/dna_viewer_api_build_meshes.md
+++ /dev/null
@@ -1,106 +0,0 @@
-# 网格工具
-
-以下方法的目的是提供:
-- 从给定 DNA 文件路径构建网格的简单机制
-- 返回和打印 DNA 文件中包含的网格信息
-
-## 导入
-
-```
-from dna_viewer import DNA, Config, build_meshes
-```
-
-```
-DNA_PATH_ADA = f"{ROOT_DIR}/data/dna_files/Ada.dna"
-DNA_PATH_TARO = f"{ROOT_DIR}/data/dna_files/Taro.dna"
-```
-
-## 创建 Config 实例([`Config`](../dna_viewer/builder/config.py#35))
-创建一个将在网格构建过程中使用的配置对象。
-
-```
-config = Config(
- add_joints=True,
- add_blend_shapes=True,
- add_skin_cluster=True,
- add_ctrl_attributes_on_root_joint=True,
- add_animated_map_attributes_on_root_joint=True,
- lod_filter=[0, 1],
- mesh_filter=["head"],
-)
-```
-
-以下是 `Config` 类的一些属性:
-- `add_joints: bool` - 表示是否应添加关节的标志,默认为 `True`。
-- `add_blend_shapes: bool` - 表示是否应添加变形的标志,默认为 `True`。
-- `add_skin_cluster: bool` - 表示是否应添加蒙皮簇的标志,默认为 `True`。
-- `add_ctrl_attributes_on_root_joint: bool` - 表示是否应将控制属性作为属性添加到根关节的标志,默认为 `False`。它们在引擎中用作 Rig Logic 输入的动画曲线。
-- `add_animated_map_attributes_on_root_joint: bool` - 表示是否应将动画贴图属性添加到根关节作为属性的标志,默认为 `True`。它们在引擎中用作动画贴图的动画曲线。
-
-**重要**: 某些标志值的组合可能会导致骨骼不可用或禁用某些功能!
-
-## 构建网格 ([`build_meshes`](../dna_viewer/api.py#L26))
-
-用于构建骨骼元素(关节、网格、变形和蒙皮簇),不包含 Rig Logic。
-它返回已添加到场景中的网格的长名称。
-
-```
-config = Config(
- add_joints=True,
- add_blend_shapes=True,
- add_skin_cluster=True,
- add_ctrl_attributes_on_root_joint=True,
- add_animated_map_attributes_on_root_joint=True,
- lod_filter=[0, 1],
- mesh_filter=["head"],
-)
-mesh_names = build_meshes(
- dna=dna_ada,
- config=config
-)
-```
-
-这使用以下参数:
-- `dna: DNA` - 通过 `DNA` 获得的 DNA 实例。
-- `config: Config` - 配置实例。
-
-```
-mesh_names = build_meshes(dna=dna_ada)
-```
-
-这默认添加 DNA 文件中的所有网格。
-
-### 示例
-
-**重要**: 运行此示例之前需要执行上述[环境设置](dna_viewer_api.md#environment-setup)。
-
-```
-from dna_viewer import DNA, Config, build_meshes
-
-# if you use Maya, use absolute path
-ROOT_DIR = f"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/")
-# Sets DNA file path
-DNA_PATH_ADA = f"{ROOT_DIR}/data/dna_files/Ada.dna"
-dna_ada = DNA(DNA_PATH_ADA)
-
-# Starts the mesh build process with all the default values
-build_meshes(dna=dna_ada)
-
-# Creates the options to be passed in `build_meshes`
-config = Config(
- add_joints=True,
- add_blend_shapes=True,
- add_skin_cluster=True,
- add_ctrl_attributes_on_root_joint=True,
- add_animated_map_attributes_on_root_joint=True,
- lod_filter=[0, 1],
- mesh_filter=["head"],
-)
-
-# Starts the mesh building process with the provided parameters
-# In this case it will create every mesh contained in LODs 0 and 1 with 'head` in it's name,
-build_meshes(
- dna=dna_ada,
- config=config,
-)
-```
diff --git a/docs/dna_viewer_api_build_rig.md b/docs/dna_viewer_api_build_rig.md
deleted file mode 100644
index b948732..0000000
--- a/docs/dna_viewer_api_build_rig.md
+++ /dev/null
@@ -1,42 +0,0 @@
-# 构建骨骼 ([`build_rig`](../dna_viewer/api.py#L9))
-
-构建骨骼 API 用于从给定的 DNA 文件路径在 Maya 场景中轻松组装角色骨骼。
-
-## 创建 RigConfig 实例([`RigConfig`](../dna_viewer/builder/config.py#35))
-创建一个将在骨骼构建过程中使用的配置对象。
-
-```
-from dna_viewer import RigConfig
-```
-
-以下是 `RigConfig` 类的一些属性:
-- `gui_path: str` - GUI 文件路径。
-- `analog_gui_path: str` - 模拟 GUI 文件路径。
-- `aas_path: str` - 附加组装脚本路径。
-- `aas_method: str` - 应从附加组装脚本调用的方法名称。
-- `add_ctrl_attributes_on_root_joint: bool` - 表示是否应在根关节上添加属性的标志,默认为 `True`。
-- `add_key_frames: bool` - 表示是否应添加关键帧的标志,默认为 `True`。
-
-## 示例
-
-**重要**: 运行此示例之前需要执行上述[环境设置](dna_viewer_api.md#environment-setup)。
-
-```
-from dna_viewer import DNA, RigConfig, build_rig
-
-# if you use Maya, use absolute path
-ROOT_DIR = f"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/")
-
-# Sets the values that will used
-DNA_PATH_ADA = f"{ROOT_DIR}/data/dna_files/Ada.dna"
-dna_ada = DNA(DNA_PATH_ADA)
-
-config = RigConfig(
- gui_path=f"{ROOT_DIR}/data/gui.ma",
- analog_gui_path=f"{ROOT_DIR}/data/analog_gui.ma",
- aas_path=f"{ROOT_DIR}/data/additional_assemble_script.py",
-)
-
-# Creates the rig
-build_rig(dna=dna_ada, config=config)
-```
diff --git a/docs/dna_viewer_maya.md b/docs/dna_viewer_maya.md
deleted file mode 100644
index 7772419..0000000
--- a/docs/dna_viewer_maya.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# 在 Maya 中使用
-
-还有一个 [Maya UI 窗口](/examples/dna_viewer_run_in_maya.py),可用于以非编程方式创建包含功能性骨骼的场景。
-
-
-
-
-
-在场景生成期间,RigLogic4 插件将自动加载,您可能会看到以下消息:
-
-
-
-点击 `允许` 加载插件。如果启用 **应用于此位置的所有插件** 选项,Maya 将不再显示此通知。
\ No newline at end of file
diff --git a/docs/dnacalib.md b/docs/dnacalib.md
deleted file mode 100644
index 3dd2aab..0000000
--- a/docs/dnacalib.md
+++ /dev/null
@@ -1,100 +0,0 @@
-# DNACalib
-这个库用于对 DNA 文件进行修改。
-它使用 C++ 编写,并且也有 Python 包装器。[SWIG](https://www.swig.org/) 库用于生成 Python 的绑定。DNACalib 可以在命令行或 Maya 中使用。
-提供了 Windows 和 Linux 的二进制文件。**如果您使用不同的架构和/或平台,您必须自行构建 DNACalib。**
-
-## DNACalib 文件夹结构
-- [`DNACalib`](/dnacalib/DNACalib) - 包含 DNACalib 及其依赖项的 C++ 源代码。其中有一个用于读写 DNA 文件的库,以及一些其他实用库。
-- [`PyDNACalib`](/dnacalib/PyDNACalib) - 包含用于生成 DNACalib Python 包装器的源代码。
-- [`PyDNA`](/dnacalib/PyDNA) - 包含用于生成 DNA 库 Python 包装器的源代码,该库位于包含 C++ 源代码的 DNACalib 文件夹下。
-- [`SPyUS`](/dnacalib/SPyUS) - 包含 PyDNACalib 和 PyDNA 都使用的一些通用 SWIG 接口文件。
-- [`CMakeModulesExtra`](/dnacalib/CMakeModulesExtra) - 包含在整个项目中使用的一些通用 CMake 函数,包括 C++ 和 Python 包装器。
-
-## 使用
-
-例如,要更改中性关节的旋转值,使用
-[`SetNeutralJointRotationsCommand`](/dnacalib/DNACalib/include/dnacalib/commands/SetNeutralJointRotationsCommand.h)。
-
-下面是一个示例,它读取 DNA,将所有中性关节的旋转值更改为 `{1, 2, 3}`,并用这些新值覆写 DNA 文件。
-
-```
-
-// 创建 DNA 读取器
-auto inOutStream = dnac::makeScoped("example.dna",
- dnac::FileStream::AccessMode::ReadWrite,
- dnac::FileStream::OpenMode::Binary);
-auto reader = dnac::makeScoped(inOutStream.get());
-reader->read();
-
-// 检查读取 DNA 文件时是否发生错误
-if (!dnac::Status::isOk()) {
- // 处理读取器错误
-}
-
-// 创建 DNACalib 读取器以编辑 DNA
-auto dnaReader = dnac::makeScoped(reader.get());
-
-std::vector rotations{dnaReader->getJointCount(), {1.0f, 2.0f, 3.0f}};
-
-// 创建命令实例
-dnac::SetNeutralJointRotationsCommand cmd{dnac::ConstArrayView{rotations}};
-
-// 执行命令
-cmd.run(dnaReader.get());
-
-// 写入 DNA 文件
-auto writer = dnac::makeScoped(inOutStream.get());
-writer->setFrom(dnaReader.get());
-writer->write();
-
-// 检查写入 DNA 文件时是否发生错误
-if (!dnac::Status::isOk()) {
- // 处理写入器错误
-}
-```
-
-## 示例
-
-### C++
-C++ 库使用示例可以在[此处](/dnacalib/DNACalib/examples)找到。
-
-这些包括:
-- [链接多个命令](/dnacalib/DNACalib/examples/CommandSequence.cpp)
-- [重命名变形](/dnacalib/DNACalib/examples/SingleCommand.cpp)
-
-### Python
-从 Python 使用库的示例在[此处](/examples)。
-
-这些包括:
-- [展示几个命令](/examples/dnacalib_demo.py)
-- [重命名关节](/examples/dnacalib_rename_joint_demo.py)
-- [从头开始创建一个小型 DNA](/examples/dna_demo.py)
-- [通过提取特定 LOD 从现有 DNA 创建新 DNA](/examples/dnacalib_lod_demo.py)
-- [读取二进制 DNA 并以人类可读格式写入](/examples/dna_binary_to_json_demo.py)
-- [删除关节](/examples/dnacalib_remove_joint.py)
-- [清除变形数据](/examples/dnacalib_clear_blend_shapes.py)
-- [从中性网格中减去值](/examples/dnacalib_neutral_mesh_subtract.py)
-
-## 构建
-提供了 64 位 Windows 和 Linux 的[预构建二进制文件](/lib)。
-如果您使用不同的架构和/或平台,您必须构建 DNACalib。
-
-先决条件:
-- [CMake](https://cmake.org/download/) 至少 3.14 版本
-- [SWIG](https://www.swig.org/download.html) 至少 4.0.0 版本
-- [Python](https://www.python.org/downloads/) 要指定要使用的 python3 的确切版本,请设置 CMake 变量
-`PYTHON3_EXACT_VERSION`。例如,要在 Maya 2022 中使用该库,请使用 3.7 版本。对于 Maya 2023,使用 3.9 版本。
-
-使用 CMake 生成构建所需的构建脚本,例如通过从
-[`MetaHuman-DNA-Calibration/dnacalib/`](/dnacalib) 目录执行以下命令:
-
-```
-mkdir build
-cd build
-cmake ..
-```
-
-然后,要开始构建过程:
-```
-cmake --build
-```
diff --git a/docs/dnacalib_api.md b/docs/dnacalib_api.md
deleted file mode 100644
index 3a928eb..0000000
--- a/docs/dnacalib_api.md
+++ /dev/null
@@ -1,78 +0,0 @@
-# API 概述
-DNA 修改是通过可用的命令完成的。每个命令都实现了 `run(DNACalibDNAReader* output)` 方法,
-该方法修改通过其参数指定的 DNA。要配置在 `run()` 中发生的修改,可以通过构造函数或特定的 setter 方法传递参数。
-以下文档适用于 C++。目前尚无 Python 文档。
-
-所有可用命令列表:
-
-## 用于删除 DNA 特定部分的命令:
-
- - [`RemoveJointAnimationCommand`](/dnacalib/DNACalib/include/dnacalib/commands/RemoveJointAnimationCommand.h) 从 DNA 中删除
-给定索引的关节动画。
-
- - [`RemoveJointCommand`](/dnacalib/DNACalib/include/dnacalib/commands/RemoveJointCommand.h) 从 DNA 中删除给定
-索引的关节。
-
- - [`RemoveMeshCommand`](/dnacalib/DNACalib/include/dnacalib/commands/RemoveMeshCommand.h) 从 DNA 中删除给定索引
-的网格。
-
- - [`ClearBlendShapesCommand`](/dnacalib/DNACalib/include/dnacalib/commands/ClearBlendShapesCommand.h) 从 DNA 中清除所有变形数据。
-
-## 用于重命名 DNA 特定部分的命令:
-
- - [`RenameAnimatedMapCommand`](/dnacalib/DNACalib/include/dnacalib/commands/RenameAnimatedMapCommand.h) 重命名给定
-索引或之前名称的动画贴图。
-
- - [`RenameBlendShapeCommand`](/dnacalib/DNACalib/include/dnacalib/commands/RenameBlendShapeCommand.h) 重命名给定
-索引或之前名称的变形。
-
- - [`RenameJointCommand`](/dnacalib/DNACalib/include/dnacalib/commands/RenameJointCommand.h) 重命名给定
-索引或之前名称的关节。
-
- - [`RenameMeshCommand`](/dnacalib/DNACalib/include/dnacalib/commands/RenameMeshCommand.h) 重命名给定
-索引或之前名称的网格。
-
-## 用于变换 DNA 的命令:
-
- - [`RotateCommand`](/dnacalib/DNACalib/include/dnacalib/commands/RotateCommand.h) 围绕给定原点旋转中性关节和顶点
-位置。
-
- - [`ScaleCommand`](/dnacalib/DNACalib/include/dnacalib/commands/ScaleCommand.h) 按因子缩放中性关节、顶点位置
-和关节及变形增量。对于中性关节和关节增量,只缩放平移属性。
-
- - [`TranslateCommand`](/dnacalib/DNACalib/include/dnacalib/commands/TranslateCommand.h) 平移中性关节和
-顶点位置。
-
-## 用于修改变形的命令:
-
- - [`SetBlendShapeTargetDeltasCommand`](/dnacalib/DNACalib/include/dnacalib/commands/SetBlendShapeTargetDeltasCommand.h)
-更改变形目标增量。
-
- - [`PruneBlendShapeTargetsCommand`](/dnacalib/DNACalib/include/dnacalib/commands/PruneBlendShapeTargetsCommand.h)
-修剪小于或等于指定阈值的变形目标增量。
-
-## 用于更改绑定姿态的命令:
-
- - [`SetNeutralJointRotationsCommand`](/dnacalib/DNACalib/include/dnacalib/commands/SetNeutralJointRotationsCommand.h)
-为中性关节设置新的旋转值。
-
- - [`SetNeutralJointTranslationsCommand`](/dnacalib/DNACalib/include/dnacalib/commands/SetNeutralJointTranslationsCommand.h)
-为中性关节设置新的平移值。
-
- - [`SetVertexPositionsCommand`](/dnacalib/DNACalib/include/dnacalib/commands/SetVertexPositionsCommand.h) 更改
-顶点位置值。
-
-## 执行有用计算或提供附加功能的命令:
-
- - [`SetLODsCommand`](/dnacalib/DNACalib/include/dnacalib/commands/SetLODsCommand.h) 过滤 DNA,使其只包含
-指定 LOD 的数据。
-
- - [`CalculateMeshLowerLODsCommand`](/dnacalib/DNACalib/include/dnacalib/commands/CalculateMeshLowerLODsCommand.h)
-重新计算指定网格的较低 LOD 网格的顶点位置。
-
- - [`CommandSequence`](/dnacalib/DNACalib/include/dnacalib/commands/CommandSequence.h) 在指定的 DNA 上运行
-一系列命令。
-
-
-每个可用命令及其方法的更详细描述可以在
-[`DNACalib/include/dnacalib/commands`](/dnacalib/DNACalib/include/dnacalib/commands/)中找到。
\ No newline at end of file
diff --git a/docs/faq.md b/docs/faq.md
deleted file mode 100644
index fb15b87..0000000
--- a/docs/faq.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# 常见问题解答 (FAQ)
-
-## 修复 "RuntimeError: Error loading DNA: DNA signature mismatched, expected DNA, got ver?"
-
-要修复此问题,您应该安装 [git-lfs](https://git-lfs.github.com/),然后重新克隆仓库。
-这样 DNA 文件就会正确下载。
-如果您无法安装 git-lfs,可以手动下载 DNA 文件。
-
-## 如何分发 Maya 场景?
-
-如果您包含以下内容,您的场景应该可以直接使用:
-- 场景文件 (`.mb` 文件)
-- DNA (`.dna` 文件)
-- 工作空间 (`workspace.mel` 文件)
-
-所有这些文件需要一起分发。如果这些文件没有打包在一起,并且您在 Maya 中遇到骨骼问题,
-请尝试以下步骤:
-
-### 如何共享生成的文件?
-如果您想将生成的 Maya 场景分发给其他用户,必须将 `.dna` 文件和 `workspace.mel` 与场景一起分发。
-
-### 如何打开生成的场景?
-在加载生成的场景之前,请按照以下步骤操作:
-- 从主菜单中,转到 文件 > 设置项目。
-- 选择 `workspace.mel`
-- 设置包含文件夹(包含生成的 maya 场景、`.dna` 文件和 `workspace.mel`)。
-
-### 如何在 Maya 场景中更改 DNA 路径?
-如果您想更改场景中的 DNA 路径:
-- 在 `大纲视图` 中,取消选择 **仅 DAG 对象**:
- - 
-- 仍在大纲视图中,搜索 `rl4`。您会看到一个名称以 `rl4Embedded_` 开头的文件。点击此文件以选择它。
- - 
-- 在 `属性编辑器` 中,您可以通过 `Dna 文件路径` 更改路径:
- - 
diff --git a/docs/img/aas.png b/docs/img/aas.png
deleted file mode 100644
index 4e3723f..0000000
Binary files a/docs/img/aas.png and /dev/null differ
diff --git a/docs/img/change_path_node_path.png b/docs/img/change_path_node_path.png
deleted file mode 100644
index f21cac2..0000000
Binary files a/docs/img/change_path_node_path.png and /dev/null differ
diff --git a/docs/img/change_path_outliner.png b/docs/img/change_path_outliner.png
deleted file mode 100644
index bad1141..0000000
Binary files a/docs/img/change_path_outliner.png and /dev/null differ
diff --git a/docs/img/change_path_outliner_settings.png b/docs/img/change_path_outliner_settings.png
deleted file mode 100644
index dd2b3eb..0000000
Binary files a/docs/img/change_path_outliner_settings.png and /dev/null differ
diff --git a/docs/img/flow_character_build.png b/docs/img/flow_character_build.png
deleted file mode 100644
index 7a0efce..0000000
Binary files a/docs/img/flow_character_build.png and /dev/null differ
diff --git a/docs/img/flow_general.png b/docs/img/flow_general.png
deleted file mode 100644
index ecb24f8..0000000
Binary files a/docs/img/flow_general.png and /dev/null differ
diff --git a/docs/img/flow_scene_build.png b/docs/img/flow_scene_build.png
deleted file mode 100644
index aacac05..0000000
Binary files a/docs/img/flow_scene_build.png and /dev/null differ
diff --git a/docs/img/layers.svg b/docs/img/layers.svg
deleted file mode 100644
index 0b30546..0000000
--- a/docs/img/layers.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/docs/img/maya_warn.png b/docs/img/maya_warn.png
deleted file mode 100644
index 5860825..0000000
Binary files a/docs/img/maya_warn.png and /dev/null differ
diff --git a/docs/img/metahuman_008.png b/docs/img/metahuman_008.png
deleted file mode 100644
index 3d69436..0000000
Binary files a/docs/img/metahuman_008.png and /dev/null differ
diff --git a/docs/img/metahuman_010.png b/docs/img/metahuman_010.png
deleted file mode 100644
index 9d03a8a..0000000
Binary files a/docs/img/metahuman_010.png and /dev/null differ
diff --git a/docs/img/ui.png b/docs/img/ui.png
deleted file mode 100644
index 9097255..0000000
Binary files a/docs/img/ui.png and /dev/null differ
diff --git a/docs/img/ui_extra_options.png b/docs/img/ui_extra_options.png
deleted file mode 100644
index 03e1742..0000000
Binary files a/docs/img/ui_extra_options.png and /dev/null differ
diff --git a/docs/repository_organization.md b/docs/repository_organization.md
deleted file mode 100644
index 1468a7a..0000000
--- a/docs/repository_organization.md
+++ /dev/null
@@ -1,62 +0,0 @@
-# 仓库组织结构
-
-本仓库包含两个独立的组件:
-1. **dnacalib C++ 库** - 用于操作 DNA 文件
-2. **dna_viewer python 代码** - 用于在 Autodesk Maya 中可视化 DNA
-
-# 文件夹结构
-
-- [dnacalib](/dnacalib) - DNACalib 源代码
-- [dna_viewer](/dna_viewer) - dna_viewer 源代码
-- [examples](/examples) - 多个 Python 脚本,展示 dna_viewer 和 DNACalib Python 封装的基本用法
-- [lib](/lib) - DNACalib、PyDNACalib 和 PyDNA 的预编译二进制文件
-- [data](/data) - 必需的 DNA 文件和 Maya 场景文件
-- [docs](/docs) - 文档
-
-## DNACalib
-文档位于[此处](dnacalib.md)
-
-## DNAViewer
-文档位于[此处](dna_viewer.md)
-
-## 示例
-要运行 [DNAViewer 示例](/docs/dna_viewer.md#examples),您必须安装 Maya 2022。
-要运行 [DNACalib 示例](/docs/dnacalib.md#python),您需要 Python3。
-
-## Lib
-
-[Lib 文件夹](/lib)包含 Windows 和 Linux 平台的 DNACalib 库预编译二进制文件。此外,还提供了 Maya 的 RL4 插件。
-
-### Linux 路径
-您需要为[lib](lib/Maya2022/linux)中的所有 **.so** 文件复制或创建符号链接:
-
-```shell
-sudo ln -s ~/MetaHuman-DNA-Calibration/lib/Maya2022/linux/_py3dna.so /usr/lib/_py3dna.so
-
-sudo ln -s ~/MetaHuman-DNA-Calibration/lib/Maya2022/linux/libdnacalib.so /usr/lib/libdnacalib.so
-
-sudo ln -s ~/MetaHuman-DNA-Calibration/lib/Maya2022/linux/libdnacalib.so.6 /usr/lib/libdnacalib.so.6
-
-sudo ln -s ~/MetaHuman-DNA-Calibration/lib/Maya2022/linux/libembeddedRL4.so /usr/lib/embeddedRL4.mll
-
-sudo ln -s ~/MetaHuman-DNA-Calibration/lib/Maya2022/linux/MayaUERBFPlugin.mll /usr/lib/MayaUERBFPlugin.mll
-```
-
-注意:请将路径 `~/MetaHuman-DNA-Calibration` 更改为您的 `MetaHuman-DNA-Calibration` 实际所在位置。
-
-## Data
-
-[`data 文件夹`](/data)包含示例 DNA 文件。我们提供了两个 MetaHuman DNA 文件(我们的首个预设 Ada 和 Taro)。
-
-| Ada | Taro |
-|---|---|
-||  |
-
-此外,我们添加了在 Maya 场景组装过程中使用的[`gui`](/data/gui.ma)和[`analog_gui`](/data/analog_gui.ma) Maya 场景文件。
-另外,[`additional_assemble_script.py`](/data/additional_assemble_script.py)用于组织场景中的对象并连接控制器。理想的设置如下所示:
-
-
-
-MHC 2023 春季版本对骨骼定义进行了更改(增加了关节数量和表情数量)。
-为适应这些更改,我们在 `/data/mh4` 文件夹中添加了几个文件:新的[gui 场景](/data/mh4/gui.ma)、更新的[组装脚本](/data/mh4/additional_assemble_script.py)和 Ada 的[DNA 文件](data/mh4/dna_files/Ada.dna)示例。
-此外,在 lib 文件夹中我们添加了用于控制颈部表情的 Maya RBF 插件。最近对颈部设置进行了改进,添加 RBF 插件以及新的 gui 场景来使用它,我们可以获得更好的颈部变形效果。
\ No newline at end of file
diff --git a/examples/dna_binary_to_json_demo.py b/examples/dna_binary_to_json_demo.py
deleted file mode 100644
index d843364..0000000
--- a/examples/dna_binary_to_json_demo.py
+++ /dev/null
@@ -1,83 +0,0 @@
-"""
-This example demonstrates reading a DNA file in binary format and writing it in a human readable JSON format.
-IMPORTANT: You have to setup the environment before running this example. Please refer to the 'Environment setup' section in README.md.
-
-- usage in command line:
- python dna_binary_to_json_demo.py
- mayapy dna_binary_to_json_demo.py
-- usage in Maya:
- 1. copy whole content of this file to Maya Script Editor
- 2. change value of ROOT_DIR to absolute path of dna_calibration, e.g. `c:/dna_calibration` in Windows or `/home/user/dna_calibration`. Important:
- Use `/` (forward slash), because Maya uses forward slashes in path.
-
-- customization:
- - change CHARACTER_NAME to Taro, or the name of a custom DNA file placed in /data/dna_files
-
-Expected: Script will generate Ada_output.json in OUTPUT_DIR from original Ada.dna.
-NOTE: If OUTPUT_DIR does not exist, it will be created.
-"""
-
-from os import makedirs
-from os import path as ospath
-
-# If you use Maya, use absolute path
-ROOT_DIR = f"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/")
-OUTPUT_DIR = f"{ROOT_DIR}/output"
-
-CHARACTER_NAME = "Ada"
-
-DATA_DIR = f"{ROOT_DIR}/data"
-CHARACTER_DNA = f"{DATA_DIR}/dna_files/{CHARACTER_NAME}.dna"
-OUTPUT_DNA = f"{OUTPUT_DIR}/{CHARACTER_NAME}_output.json"
-
-from dna import DataLayer_All, FileStream, Status, BinaryStreamReader, JSONStreamWriter
-
-
-def load_dna(path):
- stream = FileStream(path, FileStream.AccessMode_Read, FileStream.OpenMode_Binary)
- reader = BinaryStreamReader(stream, DataLayer_All)
- reader.read()
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error loading DNA: {status.message}")
- return reader
-
-
-def save_dna(reader, path):
- stream = FileStream(path, FileStream.AccessMode_Write, FileStream.OpenMode_Binary)
- writer = JSONStreamWriter(stream)
- # Create a writer based on the reader using all data layers (if no argument is passed, DataLayer_All is the default value)
- writer.setFrom(reader)
- # Alternatively, a writer can be created using only a subset of layers,
- # e.g. to write only Behavior layer (Descriptor and Definition included with it), use:
- # writer.setFrom(reader, DataLayer_Behavior)
- #
- # Available layer options and their approximate sizes for this example (Ada.dna, JSON format):
- # DataLayer_Descriptor - ~ 3 KB
- # DataLayer_Definition - includes Descriptor, ~ 131 KB
- # DataLayer_Behavior - includes Descriptor and Definition, ~ 10 MB
- # DataLayer_Geometry - includes Descriptor and Definition, ~ 191 MB
- # DataLayer_GeometryWithoutBlendShapes - includes Descriptor and Definition, ~ 22 MB
- # DataLayer_AllWithoutBlendShapes - includes everything except blend shapes from Geometry, ~ 32 MB
- # DataLayer_All - ~ 201 MB
- #
- # If using one of the other layer options, be sure to add it to the import list.
- #
- # Beside specifying layers when creating a writer, layers to use can be specified when
- # creating a reader as well.
- writer.write()
-
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error saving DNA: {status.message}")
-
-
-def create_json_dna(input_path, output_path):
- dna_reader = load_dna(input_path)
- save_dna(dna_reader, output_path)
- print('Done.')
-
-
-if __name__ == "__main__":
- makedirs(OUTPUT_DIR, exist_ok=True)
- create_json_dna(CHARACTER_DNA, OUTPUT_DNA)
diff --git a/examples/dna_demo.py b/examples/dna_demo.py
deleted file mode 100644
index 3ad4b5f..0000000
--- a/examples/dna_demo.py
+++ /dev/null
@@ -1,101 +0,0 @@
-"""
-This example demonstrates creating DNA from scratch.
-IMPORTANT: You have to setup the environment before running this example. Please refer to the 'Environment setup' section in README.md.
-
-- usage in command line:
- python dna_demo.py
- mayapy dna_demo.py
-- usage in Maya:
- 1. copy whole content of this file to Maya Script Editor
- 2. change value of ROOT_DIR to absolute path of dna_calibration, e.g. `c:/dna_calibration` in Windows or `/home/user/dna_calibration`. Important:
- Use `/` (forward slash), because Maya uses forward slashes in path.
-
-- customization:
- - change CHARACTER_NAME to Taro, or the name of a custom DNA file placed in /data/dna_files
-
-Expected: Script will generate Ada_output.dna in OUTPUT_DIR from original Ada.dna.
-NOTE: If OUTPUT_DIR does not exist, it will be created.
-"""
-
-
-from os import makedirs
-from os import path as ospath
-
-# If you use Maya, use absolute path
-ROOT_DIR = f"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/")
-OUTPUT_DIR = f"{ROOT_DIR}/output"
-
-CHARACTER_NAME = "Ada"
-
-DATA_DIR = f"{ROOT_DIR}/data"
-CHARACTER_DNA = f"{DATA_DIR}/dna_files/{CHARACTER_NAME}.dna"
-OUTPUT_DNA = f"{OUTPUT_DIR}/{CHARACTER_NAME}_output.dna"
-
-
-from dna import DataLayer_All, FileStream, Status, BinaryStreamReader, BinaryStreamWriter
-
-
-def create_dna(path):
- stream = FileStream(path, FileStream.AccessMode_Write, FileStream.OpenMode_Binary)
- writer = BinaryStreamWriter(stream)
-
- # Sets a couple of parameters about in the dna that is about to be created and written to
- writer.setName("rig name")
- writer.setLODCount(4)
- writer.setJointName(0, "spine")
- writer.setJointName(1, "neck")
-
- writer.setMeshName(0, "head")
- writer.setVertexPositions(0, [[0.0, 0.5, 0.3], [1.0, 3.0, -8.0]])
- writer.setVertexTextureCoordinates(0, [[0.25, 0.55], [1.5, 3.6]])
-
- # Creates the DNA
- writer.write()
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error saving DNA: {status.message}")
-
-
-def load_dna(path):
- stream = FileStream(path, FileStream.AccessMode_Read, FileStream.OpenMode_Binary)
- reader = BinaryStreamReader(stream, DataLayer_All)
- reader.read()
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error loading DNA: {status.message}")
- return reader
-
-
-def print_dna_summary(dna_reader):
- print(f"Name: {dna_reader.getName()}")
- print(f"Joint count: {dna_reader.getJointCount()}")
- joint_names = ", ".join(
- dna_reader.getJointName(i) for i in range(dna_reader.getJointCount())
- )
- print(f"Joint names: {joint_names}")
-
- for mesh_idx in range(dna_reader.getMeshCount()):
- # Get vertices one by one
- for vtx_id in range(dna_reader.getVertexPositionCount(mesh_idx)):
- vtx = dna_reader.getVertexPosition(mesh_idx, vtx_id)
- print(f"Mesh {mesh_idx} - Vertex {vtx_id} : {vtx}")
- # Get all X / Y / Z coordinates
- print(dna_reader.getVertexPositionXs(mesh_idx))
- print(dna_reader.getVertexPositionYs(mesh_idx))
- print(dna_reader.getVertexPositionZs(mesh_idx))
-
- for tc_idx in range(dna_reader.getVertexTextureCoordinateCount(mesh_idx)):
- tex_coord = dna_reader.getVertexTextureCoordinate(mesh_idx, tc_idx)
- print(f"Mesh {mesh_idx} - Texture coordinate {tc_idx} : {tex_coord}")
-
-
-def create_new_dna(dna_path):
- create_dna(dna_path)
- dna_reader = load_dna(dna_path)
- print_dna_summary(dna_reader)
- print('Done.')
-
-
-if __name__ == "__main__":
- makedirs(OUTPUT_DIR, exist_ok=True)
- create_new_dna(OUTPUT_DNA)
diff --git a/examples/dna_viewer_build_rig.py b/examples/dna_viewer_build_rig.py
deleted file mode 100644
index 585d1d7..0000000
--- a/examples/dna_viewer_build_rig.py
+++ /dev/null
@@ -1,74 +0,0 @@
-"""
-This example demonstrates generating functional rig in maya scene and exporting fbx per lod.
-IMPORTANT: You have to setup the environment before running this example. Please refer to the 'Environment setup' section in README.md.
-
-- usage in command line:
- python dna_viewer_build_rig.py
- mayapy dna_viewer_build_rig.py
- NOTE: Script cannot be called with Python, it must be called with mayapy.
-
-- usage in Maya:
- 1. copy whole content of this file to Maya Script Editor
- 2. change value of ROOT_DIR to absolute path of dna_calibration, e.g. `c:/dna_calibration` in Windows or `/home/user/dna_calibration`. Important:
- Use `/` (forward slash), because Maya uses forward slashes in path.
-
-- customization:
- - change CHARACTER_NAME to Taro, or the name of a custom DNA file placed in /data/dna_files
-Expected:
- - script will generate maya scene Ada.mb in OUTPUT_DIR
- - script will generate workspace.mel in OUTPUT_DIR
- - script will copy original Ada.dna file to OUTPUT_DIR
-
-Expected: script will generate .
-NOTE: If OUTPUT_DIR does not exist, it will be created.
-"""
-
-
-from os import makedirs
-from os import path as ospath
-from shutil import copyfile
-
-# if you use Maya, use absolute path
-ROOT_DIR = f"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/")
-OUTPUT_DIR = f"{ROOT_DIR}/output"
-EXAMPLES_DIR = f"{ROOT_DIR}/examples"
-ROOT_LIB_DIR = f"{ROOT_DIR}/lib"
-
-CHARACTER_NAME = "Ada"
-
-DATA_DIR = f"{ROOT_DIR}/data"
-CHARACTER_DNA = f"{DATA_DIR}/dna_files/{CHARACTER_NAME}.dna"
-ANALOG_GUI = f"{DATA_DIR}/analog_gui.ma"
-GUI = f"{DATA_DIR}/gui.ma"
-ADDITIONAL_ASSEMBLE_SCRIPT = f"{DATA_DIR}/additional_assemble_script.py"
-
-
-from maya import cmds, mel
-
-from dna_viewer import DNA, RigConfig, build_rig
-
-
-if __name__ == "__main__":
- dna = DNA(CHARACTER_DNA)
-
- makedirs(OUTPUT_DIR, exist_ok=True)
-
- # This fixes warning when calling this script with headless maya Warning: line 1: Unknown object type: HIKCharacterNode
- mel.eval(f"HIKCharacterControlsTool;")
-
- # Generate workspace.mel
- mel.eval(f'setProject "{OUTPUT_DIR}";')
-
- config = RigConfig(
- gui_path=GUI,
- analog_gui_path=ANALOG_GUI,
- aas_path=ADDITIONAL_ASSEMBLE_SCRIPT,
- )
-
- # Creates the rig
- build_rig(dna=dna, config=config)
- # Renames and saves the scene
- cmds.file(rename=f"{OUTPUT_DIR}/{CHARACTER_NAME}.mb")
- cmds.file(save=True)
- # Copy dna file and workspace file alongside generated scene
- copyfile(CHARACTER_DNA, f"{OUTPUT_DIR}/{CHARACTER_NAME}.dna")
diff --git a/examples/dna_viewer_build_rig_with_textures.py b/examples/dna_viewer_build_rig_with_textures.py
deleted file mode 100644
index 81a7200..0000000
--- a/examples/dna_viewer_build_rig_with_textures.py
+++ /dev/null
@@ -1,355 +0,0 @@
-"""
-This example demonstrates generating functional rig based on DNA file in Maya scene with applied textures.
-Maps added in data folder belong to Ada preset character. User should use source data downloaded from Quixel Bridge.
-IMPORTANT: You have to setup the environment before running this example. Please refer to the 'Environment setup' section in README.md.
-
-- usage in command line:
- mayapy dna_viewer_build_rig_with_textures.py
- NOTE: Script cannot be called with Python, it must be called with mayapy.
-
-- usage in Maya:
- 1. copy whole content of this file to Maya Script Editor
- 2. change value of ROOT_DIR to absolute path of dna_calibration, e.g. `c:/dna_calibration` in Windows or `/home/user/dna_calibration`. Important:
- Use `/` (forward slash), because Maya uses forward slashes in path.
-"""
-import time
-import os
-
-# if you use Maya, use absolute path
-ROOT_DIR = f"{os.path.dirname(os.path.abspath(__file__))}/..".replace("\\", "/")
-DATA_DIR = f"{ROOT_DIR}/data"
-
-from maya import cmds, mel
-from dna_viewer import (
- DNA,
- RigConfig,
- build_rig
-)
-
-ORIENT_Y = [0.0, 0.0, 0.0]
-COMMON_MAP_INFOS = [
- ("dx11_diffuseIrradiance", 1),
- ("dx11_jitter", 1),
- ("dx11_skinLUT", 1),
- ("dx11_specularIrradiance", 1),
-]
-
-MAP_INFOS = [
- ("head_color", 1),
- ("head_cm1_color", 0),
- ("head_cm2_color", 0),
- ("head_cm3_color", 0),
- ("head_normal", 1),
- ("head_wm1_normal", 0),
- ("head_wm2_normal", 0),
- ("head_wm3_normal", 0),
- ("head_specular", 1),
- ("head_specular_16Bits", 1),
- ("head_occlusion", 1),
- ("head_occlusion_16Bits", 1),
- ("head_cavity", 1),
- ("head_cavity_16Bits", 1),
- ("head_transmission", 1),
- ("head_transmission_16Bits", 1),
- ("head_curvature", 1),
- ("head_curvature_16Bits", 1),
- ("head_position", 1),
- ("head_position_16Bits", 1),
- ("head_worldspace", 1),
- ("head_worldspace_16Bits", 1),
- ("head_bentNormal", 1),
- ("head_bentNormal_16Bits", 1),
- ("teeth_color", 1),
- ("teeth_normal", 1),
- ("eyes_color", 1),
- ("eyeLeft_color", 1),
- ("eyeRight_color", 1),
- ("eyeLeft_normal", 1),
- ("eyeRight_normal", 1),
- ("eyes_color_16Bits", 1),
- ("eyes_normal", 1),
- ("eyes_normal_16Bits", 1),
- ("eyelashes_color", 1),
-]
-
-MASKS = [
- "head_wm1_blink_L",
- "head_wm1_blink_R",
- "head_wm1_browsRaiseInner_L",
- "head_wm1_browsRaiseInner_R",
- "head_wm1_browsRaiseOuter_L",
- "head_wm1_browsRaiseOuter_R",
- "head_wm1_chinRaise_L",
- "head_wm1_chinRaise_R",
- "head_wm1_jawOpen",
- "head_wm1_purse_DL",
- "head_wm1_purse_DR",
- "head_wm1_purse_UL",
- "head_wm1_purse_UR",
- "head_wm1_squintInner_L",
- "head_wm1_squintInner_R",
- "head_wm2_browsDown_L",
- "head_wm2_browsDown_R",
- "head_wm2_browsLateral_L",
- "head_wm2_browsLateral_R",
- "head_wm2_mouthStretch_L",
- "head_wm2_mouthStretch_R",
- "head_wm2_neckStretch_L",
- "head_wm2_neckStretch_R",
- "head_wm2_noseWrinkler_L",
- "head_wm2_noseWrinkler_R",
- "head_wm3_cheekRaiseInner_L",
- "head_wm3_cheekRaiseInner_R",
- "head_wm3_cheekRaiseOuter_L",
- "head_wm3_cheekRaiseOuter_R",
- "head_wm3_cheekRaiseUpper_L",
- "head_wm3_cheekRaiseUpper_R",
- "head_wm3_smile_L",
- "head_wm3_smile_R",
- "head_wm13_lips_DL",
- "head_wm13_lips_DR",
- "head_wm13_lips_UL",
- "head_wm13_lips_UR",
-]
-
-MESH_SHADER_MAPPING = {
- "head_lod": "head_shader",
- "teeth_lod": "teeth_shader",
- "saliva_lod": "saliva_shader",
- "eyeLeft_lod": "eyeLeft_shader",
- "eyeRight_lod": "eyeRight_shader",
- "eyeshell_lod": "eyeshell_shader",
- "eyelashes_lod": "eyelashes_shader",
- "eyelashesShadow_lod": "eyelashesShadow_shader",
- "eyeEdge_lod": "eyeEdge_shader",
- "cartilage_lod": "eyeEdge_shader",
-}
-
-SHADERS = ["head_shader", "teeth_shader", "eyeLeft_shader", "eyeRight_shader"]
-
-SHADER_ATTRIBUTES_MAPPING = {
- "FRM_WMmultipliers.head_cm2_color_head_wm2_browsDown_L": "shader_head_shader.maskWeight_00",
- "FRM_WMmultipliers.head_wm2_normal_head_wm2_browsDown_L": "shader_head_shader.maskWeight_01",
- "FRM_WMmultipliers.head_cm2_color_head_wm2_browsDown_R": "shader_head_shader.maskWeight_02",
- "FRM_WMmultipliers.head_wm2_normal_head_wm2_browsDown_R": "shader_head_shader.maskWeight_03",
- "FRM_WMmultipliers.head_cm2_color_head_wm2_browsLateral_L": "shader_head_shader.maskWeight_04",
- "FRM_WMmultipliers.head_wm2_normal_head_wm2_browsLateral_L": "shader_head_shader.maskWeight_05",
- "FRM_WMmultipliers.head_cm2_color_head_wm2_browsLateral_R": "shader_head_shader.maskWeight_06",
- "FRM_WMmultipliers.head_wm2_normal_head_wm2_browsLateral_R": "shader_head_shader.maskWeight_07",
- "FRM_WMmultipliers.head_cm1_color_head_wm1_browsRaiseInner_L": "shader_head_shader.maskWeight_08",
- "FRM_WMmultipliers.head_wm1_normal_head_wm1_browsRaiseInner_L": "shader_head_shader.maskWeight_09",
- "FRM_WMmultipliers.head_cm1_color_head_wm1_browsRaiseInner_R": "shader_head_shader.maskWeight_10",
- "FRM_WMmultipliers.head_wm1_normal_head_wm1_browsRaiseInner_R": "shader_head_shader.maskWeight_11",
- "FRM_WMmultipliers.head_cm1_color_head_wm1_browsRaiseOuter_L": "shader_head_shader.maskWeight_12",
- "FRM_WMmultipliers.head_wm1_normal_head_wm1_browsRaiseOuter_L": "shader_head_shader.maskWeight_13",
- "FRM_WMmultipliers.head_cm1_color_head_wm1_browsRaiseOuter_R": "shader_head_shader.maskWeight_14",
- "FRM_WMmultipliers.head_wm1_normal_head_wm1_browsRaiseOuter_R": "shader_head_shader.maskWeight_15",
- "FRM_WMmultipliers.head_cm1_color_head_wm1_blink_L": "shader_head_shader.maskWeight_16",
- "FRM_WMmultipliers.head_cm1_color_head_wm1_squintInner_L": "shader_head_shader.maskWeight_17",
- "FRM_WMmultipliers.head_wm1_normal_head_wm1_blink_L": "shader_head_shader.maskWeight_18",
- "FRM_WMmultipliers.head_wm1_normal_head_wm1_squintInner_L": "shader_head_shader.maskWeight_19",
- "FRM_WMmultipliers.head_cm1_color_head_wm1_blink_R": "shader_head_shader.maskWeight_20",
- "FRM_WMmultipliers.head_cm1_color_head_wm1_squintInner_R": "shader_head_shader.maskWeight_21",
- "FRM_WMmultipliers.head_wm1_normal_head_wm1_blink_R": "shader_head_shader.maskWeight_22",
- "FRM_WMmultipliers.head_wm1_normal_head_wm1_squintInner_R": "shader_head_shader.maskWeight_23",
- "FRM_WMmultipliers.head_cm3_color_head_wm3_cheekRaiseInner_L": "shader_head_shader.maskWeight_24",
- "FRM_WMmultipliers.head_cm3_color_head_wm3_cheekRaiseOuter_L": "shader_head_shader.maskWeight_25",
- "FRM_WMmultipliers.head_cm3_color_head_wm3_cheekRaiseUpper_L": "shader_head_shader.maskWeight_26",
- "FRM_WMmultipliers.head_wm3_normal_head_wm3_cheekRaiseInner_L": "shader_head_shader.maskWeight_27",
- "FRM_WMmultipliers.head_wm3_normal_head_wm3_cheekRaiseOuter_L": "shader_head_shader.maskWeight_28",
- "FRM_WMmultipliers.head_wm3_normal_head_wm3_cheekRaiseUpper_L": "shader_head_shader.maskWeight_29",
- "FRM_WMmultipliers.head_cm3_color_head_wm3_cheekRaiseInner_R": "shader_head_shader.maskWeight_30",
- "FRM_WMmultipliers.head_cm3_color_head_wm3_cheekRaiseOuter_R": "shader_head_shader.maskWeight_31",
- "FRM_WMmultipliers.head_cm3_color_head_wm3_cheekRaiseUpper_R": "shader_head_shader.maskWeight_32",
- "FRM_WMmultipliers.head_wm3_normal_head_wm3_cheekRaiseInner_R": "shader_head_shader.maskWeight_33",
- "FRM_WMmultipliers.head_wm3_normal_head_wm3_cheekRaiseOuter_R": "shader_head_shader.maskWeight_34",
- "FRM_WMmultipliers.head_wm3_normal_head_wm3_cheekRaiseUpper_R": "shader_head_shader.maskWeight_35",
- "FRM_WMmultipliers.head_cm2_color_head_wm2_noseWrinkler_L": "shader_head_shader.maskWeight_36",
- "FRM_WMmultipliers.head_wm2_normal_head_wm2_noseWrinkler_L": "shader_head_shader.maskWeight_37",
- "FRM_WMmultipliers.head_cm2_color_head_wm2_noseWrinkler_R": "shader_head_shader.maskWeight_38",
- "FRM_WMmultipliers.head_wm2_normal_head_wm2_noseWrinkler_R": "shader_head_shader.maskWeight_39",
- "FRM_WMmultipliers.head_cm3_color_head_wm3_smile_L": "shader_head_shader.maskWeight_40",
- "FRM_WMmultipliers.head_wm3_normal_head_wm3_smile_L": "shader_head_shader.maskWeight_41",
- "FRM_WMmultipliers.head_cm1_color_head_wm13_lips_UL": "shader_head_shader.maskWeight_42",
- "FRM_WMmultipliers.head_cm1_color_head_wm13_lips_UR": "shader_head_shader.maskWeight_43",
- "FRM_WMmultipliers.head_cm1_color_head_wm13_lips_DL": "shader_head_shader.maskWeight_44",
- "FRM_WMmultipliers.head_cm1_color_head_wm13_lips_DR": "shader_head_shader.maskWeight_45",
- "FRM_WMmultipliers.head_wm1_normal_head_wm13_lips_UL": "shader_head_shader.maskWeight_46",
- "FRM_WMmultipliers.head_wm1_normal_head_wm13_lips_UR": "shader_head_shader.maskWeight_47",
- "FRM_WMmultipliers.head_wm1_normal_head_wm13_lips_DL": "shader_head_shader.maskWeight_48",
- "FRM_WMmultipliers.head_wm1_normal_head_wm13_lips_DR": "shader_head_shader.maskWeight_49",
- "FRM_WMmultipliers.head_cm3_color_head_wm3_smile_R": "shader_head_shader.maskWeight_50",
- "FRM_WMmultipliers.head_wm3_normal_head_wm3_smile_R": "shader_head_shader.maskWeight_51",
- "FRM_WMmultipliers.head_cm3_color_head_wm13_lips_UL": "shader_head_shader.maskWeight_52",
- "FRM_WMmultipliers.head_cm3_color_head_wm13_lips_DL": "shader_head_shader.maskWeight_53",
- "FRM_WMmultipliers.head_wm3_normal_head_wm13_lips_UL": "shader_head_shader.maskWeight_54",
- "FRM_WMmultipliers.head_wm3_normal_head_wm13_lips_DL": "shader_head_shader.maskWeight_55",
- "FRM_WMmultipliers.head_cm3_color_head_wm13_lips_UR": "shader_head_shader.maskWeight_56",
- "FRM_WMmultipliers.head_cm3_color_head_wm13_lips_DR": "shader_head_shader.maskWeight_57",
- "FRM_WMmultipliers.head_wm3_normal_head_wm13_lips_UR": "shader_head_shader.maskWeight_58",
- "FRM_WMmultipliers.head_wm3_normal_head_wm13_lips_DR": "shader_head_shader.maskWeight_59",
- "FRM_WMmultipliers.head_cm2_color_head_wm2_mouthStretch_L": "shader_head_shader.maskWeight_60",
- "FRM_WMmultipliers.head_wm2_normal_head_wm2_mouthStretch_L": "shader_head_shader.maskWeight_61",
- "FRM_WMmultipliers.head_cm2_color_head_wm2_mouthStretch_R": "shader_head_shader.maskWeight_62",
- "FRM_WMmultipliers.head_wm2_normal_head_wm2_mouthStretch_R": "shader_head_shader.maskWeight_63",
- "FRM_WMmultipliers.head_cm1_color_head_wm1_purse_UL": "shader_head_shader.maskWeight_64",
- "FRM_WMmultipliers.head_wm1_normal_head_wm1_purse_UL": "shader_head_shader.maskWeight_65",
- "FRM_WMmultipliers.head_cm1_color_head_wm1_purse_UR": "shader_head_shader.maskWeight_66",
- "FRM_WMmultipliers.head_wm1_normal_head_wm1_purse_UR": "shader_head_shader.maskWeight_67",
- "FRM_WMmultipliers.head_cm1_color_head_wm1_purse_DL": "shader_head_shader.maskWeight_68",
- "FRM_WMmultipliers.head_wm1_normal_head_wm1_purse_DL": "shader_head_shader.maskWeight_69",
- "FRM_WMmultipliers.head_cm1_color_head_wm1_purse_DR": "shader_head_shader.maskWeight_70",
- "FRM_WMmultipliers.head_wm1_normal_head_wm1_purse_DR": "shader_head_shader.maskWeight_71",
- "FRM_WMmultipliers.head_cm1_color_head_wm1_chinRaise_L": "shader_head_shader.maskWeight_72",
- "FRM_WMmultipliers.head_wm1_normal_head_wm1_chinRaise_L": "shader_head_shader.maskWeight_73",
- "FRM_WMmultipliers.head_cm1_color_head_wm1_chinRaise_R": "shader_head_shader.maskWeight_74",
- "FRM_WMmultipliers.head_wm1_normal_head_wm1_chinRaise_R": "shader_head_shader.maskWeight_75",
- "FRM_WMmultipliers.head_cm1_color_head_wm1_jawOpen": "shader_head_shader.maskWeight_76",
- "FRM_WMmultipliers.head_wm1_normal_head_wm1_jawOpen": "shader_head_shader.maskWeight_77",
- "FRM_WMmultipliers.head_cm2_color_head_wm2_neckStretch_L": "shader_head_shader.maskWeight_78",
- "FRM_WMmultipliers.head_wm2_normal_head_wm2_neckStretch_L": "shader_head_shader.maskWeight_79",
- "FRM_WMmultipliers.head_cm2_color_head_wm2_neckStretch_R": "shader_head_shader.maskWeight_80",
- "FRM_WMmultipliers.head_wm2_normal_head_wm2_neckStretch_R": "shader_head_shader.maskWeight_81",
-}
-
-
-# Methods
-def import_head_shaders(shader_scene_path, shaders_dir_path, masks_dir_path, maps_dir_path):
- import_shader(shader_scene_path, MESH_SHADER_MAPPING)
-
- resolve_scene_shader_paths(SHADERS, shaders_dir_path)
-
- set_mask_textures(MASKS, masks_dir_path)
- set_map_textures(COMMON_MAP_INFOS, maps_dir_path)
- set_map_textures(MAP_INFOS, maps_dir_path)
-
- connect_attributes_to_shader(SHADER_ATTRIBUTES_MAPPING)
-
-
-def import_shader(shader_scene_path, mesh_shader_mapping):
- print("Shader scene imported")
- cmds.file(shader_scene_path, options="v=0", type="mayaAscii", i=True)
- try:
- items = mesh_shader_mapping.iteritems()
- except:
- items = mesh_shader_mapping.items()
- for meshName, shaderName in items:
- for lodLvl in range(0, 8):
- try:
- # Apply shader to all meshes based on LOD level
- resolved_mesh_name = meshName + str(lodLvl) + "_mesh"
- shader = "shader_" + shaderName
- cmds.select(resolved_mesh_name, replace=True)
- mel.eval("sets -e -forceElement " + shader + "SG")
- except:
- print("Skipped adding shader for mesh %s." % meshName)
-
-
-def resolve_scene_shader_paths(shaders, folder_name):
- for shader in shaders:
- node_name = "shader_" + shader
- if not cmds.objExists(node_name):
- continue
- file_shader_name = cmds.getAttr(node_name + ".shader")
- shader_folder_name, shader_file_name = os.path.split(file_shader_name)
- shader_folder_name = folder_name
- cmds.setAttr(
- node_name + ".shader",
- shader_folder_name + "/" + shader_file_name,
- type="string",
- )
-
-
-def set_mask_textures(masks, folder_name):
- for mask in masks:
- node_name = "maskFile_" + mask
-
- if not cmds.objExists(node_name):
- continue
-
- file_texture_name = cmds.getAttr(node_name + ".fileTextureName")
- texture_folder_name, texture_file_name = os.path.split(file_texture_name)
- texture_folder_name = folder_name
- cmds.setAttr(
- node_name + ".fileTextureName",
- texture_folder_name + "/" + texture_file_name,
- type="string",
- )
-
-
-def set_map_textures(map_infos, folder_name):
- for mapInfo in map_infos:
- node_name = "mapFile_" + mapInfo[0]
- if mapInfo[1]:
- node_name = "baseMapFile_" + mapInfo[0]
-
- if not cmds.objExists(node_name):
- continue
-
- file_texture_name = cmds.getAttr(node_name + ".fileTextureName")
- texture_folder_name, texture_file_name = os.path.split(file_texture_name)
- texture_folder_name = folder_name
- cmds.setAttr(
- node_name + ".fileTextureName",
- texture_folder_name + "/" + texture_file_name,
- type="string",
- )
-
-
-def connect_attributes_to_shader(shader_attributes_mapping):
- print("Connecting attributes to shader...")
- try:
- items = shader_attributes_mapping.iteritems()
- except Exception as ex:
- print(f"Error: {ex}")
- items = shader_attributes_mapping.items()
-
- for frm_attribute, shaderAttribute in items:
- if cmds.objExists(frm_attribute) and cmds.objExists(shaderAttribute):
- cmds.connectAttr(frm_attribute, shaderAttribute, force=True)
-
-
-def create_lights(lights_file_path, orient):
- print("Creating lights...")
- cmds.file(lights_file_path, defaultNamespace=True, i=True)
- cmds.xform("Lights", ro=orient)
- cmds.makeIdentity("Lights", apply=True)
-
-
-# Define all paths
-dna_path = f"{DATA_DIR}/mh4/dna_files/Ada.dna"
-gui_path = f"{DATA_DIR}/mh4/gui.ma"
-aas_path = f"{DATA_DIR}/mh4/additional_assemble_script.py"
-ac_path = f"{DATA_DIR}/analog_gui.ma"
-light_scene = f"{DATA_DIR}/lights.ma"
-shader_scene = f"{DATA_DIR}/shader.ma"
-shaders_dir = f"{DATA_DIR}/shaders"
-masks_dir = f"{DATA_DIR}/masks"
-maps_dir = f"{DATA_DIR}/maps"
-output_scene = f"{ROOT_DIR}/output/Ada_rig.mb"
-
-try:
- start_time = time.time()
-
- # open new scene
- cmds.file(new=True, force=True)
-
- # import DNA data
- dna = DNA(dna_path)
-
- config = RigConfig(
- gui_path=gui_path,
- analog_gui_path=ac_path,
- aas_path=aas_path,
- )
- build_rig(dna=dna, config=config)
- import_head_shaders(shader_scene, shaders_dir, masks_dir, maps_dir)
- create_lights(light_scene, ORIENT_Y)
-
- # save scene
- cmds.file(rename=output_scene)
- cmds.file(save=True, type="mayaBinary")
-
- print("--- Import finished in %s seconds ---" % (time.time() - start_time))
-except Exception as ex:
- print("Error building scene", ex)
diff --git a/examples/dna_viewer_export_fbx.py b/examples/dna_viewer_export_fbx.py
deleted file mode 100644
index b5a8ac0..0000000
--- a/examples/dna_viewer_export_fbx.py
+++ /dev/null
@@ -1,300 +0,0 @@
-"""
-This example demonstrates generating functional rig in maya scene and exporting fbx per lod.
-IMPORTANT: You have to setup the environment before running this example. Please refer to the 'Environment setup' section in README.md.
-
-- usage in command line:
- python dna_viewer_export_fbx.py
- mayapy dna_viewer_export_fbx.py
- NOTE: Script cannot be called with Python, it must be called with mayapy.
-
-- usage in Maya:
- 1. copy whole content of this file to Maya Script Editor
- 2. change value of ROOT_DIR to absolute path of dna_calibration, e.g. `c:/dna_calibration` in Windows or `/home/user/dna_calibration`. Important:
- Use `/` (forward slash), because Maya uses forward slashes in path.
-
-- customization:
-- change CHARACTER_NAME to Taro, or the name of a custom DNA file placed in /data/dna_files. If you change name to Taro,
- or some other Masculine character, you need to change BODY_FILE with value f"{BODY_DIR}/masc_skeleton.ma"
- - change ADD_COLOR_VERTEX to True, if you want to import fbx in Unreal Engine with painted vertices for fallowing cases:
- - vertex normals that are going to be updated during import in Unreal Engine, its vertices must be painted with green color.
- - for potential future GeneSplicer usage, skinwights on vertices which will need update in character mixing process, must be painted with blue color.
- - change UP_AXIS in order change up axis, it can be 'z' or 'y', if put any value is put, ValueError will be raised
-
-Expected:
- - script will generate fbx files Ada_lodX.mb where X are values from 0 to 7, in OUTPUT_DIR
- - script will generate workspace.mel in OUTPUT_DIR
-
-NOTE: If OUTPUT_DIR does not exist, it will be created.
-"""
-
-
-from os import makedirs
-from os import path as ospath
-from pathlib import Path
-
-# if you use Maya, use absolute path
-ROOT_DIR = f"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/")
-OUTPUT_DIR = f"{ROOT_DIR}/output"
-EXAMPLES_DIR = f"{ROOT_DIR}/examples"
-ROOT_LIB_DIR = f"{ROOT_DIR}/lib"
-DATA_DIR = f"{ROOT_DIR}/data"
-
-
-# Setting constants that will be used
-FACIAL_ROOT_NAME = "FACIAL_C_FacialRoot"
-CHARACTER_NAME = "Ada"
-
-ADD_COLOR_VERTEX = False
-
-DNA_DIR = f"{DATA_DIR}/dna_files"
-BODY_DIR = f"{DATA_DIR}/body"
-CHARACTER_DNA = f"{DNA_DIR}/{CHARACTER_NAME}.dna"
-
-UP_AXIS = "z"
-if UP_AXIS not in ("z", "y"):
- raise ValueError("UP_AXIS can be 'z' or 'y'")
-
-
-BODY_FILE = f"{BODY_DIR}/fem_skeleton.ma"
-ADD_MESH_NAME_TO_BLEND_SHAPE_CHANNEL_NAME = True
-
-FACIAL_ROOT_JOINTS = ["FACIAL_C_FacialRoot", "FACIAL_C_Neck1Root", "FACIAL_C_Neck2Root"]
-NECK_JOINTS = ["head", "neck_01", "neck_02"]
-ROOT_JOINT = "spine_04"
-
-from dna import (
- BinaryStreamReader,
- BinaryStreamWriter,
- DataLayer_All,
- FileStream,
- Status,
-)
-from dnacalib import DNACalibDNAReader, RotateCommand
-from maya import cmds, mel
-from vtx_color import MESH_SHADER_MAPPING, VTX_COLOR_MESHES, VTX_COLOR_VALUES
-
-from dna_viewer import (
- DNA,
- Config,
- build_meshes,
- get_skin_weights_from_scene,
- set_skin_weights_to_scene,
-)
-
-
-def load_dna_reader():
- stream = FileStream(
- CHARACTER_DNA, FileStream.AccessMode_Read, FileStream.OpenMode_Binary
- )
- reader = BinaryStreamReader(stream, DataLayer_All)
- reader.read()
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error loading DNA: {status.message}")
- return reader
-
-
-def save_dna(reader):
- stream = FileStream(
- f"{CHARACTER_DNA}.rotate.dna",
- FileStream.AccessMode_Write,
- FileStream.OpenMode_Binary,
- )
- writer = BinaryStreamWriter(stream)
- writer.setFrom(reader)
- writer.write()
-
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error saving DNA: {status.message}")
-
-
-def prepare_rotated_dna():
- reader = load_dna_reader()
-
- # Copies DNA contents and will serve as input/output parameter to commands
- calibrated = DNACalibDNAReader(reader)
-
- # Modifies calibrated DNA in-place
- rotate = RotateCommand([90.0, 0.0, 0.0], [0.0, 0.0, 0.0])
- rotate.run(calibrated)
-
- save_dna(calibrated)
- return DNA(f"{CHARACTER_DNA}.rotate.dna")
-
-
-def get_dna():
- if UP_AXIS == "z":
- return prepare_rotated_dna()
- return DNA(CHARACTER_DNA)
-
-
-def cleanup():
- path = Path(f"{CHARACTER_DNA}.rotate.dna")
- if path.exists():
- path.unlink()
-
-
-def build_meshes_for_lod(dna, lod):
- # Create config
- config = Config(
- group_by_lod=False,
- create_display_layers=False,
- lod_filter=[lod],
- add_mesh_name_to_blend_shape_channel_name=ADD_MESH_NAME_TO_BLEND_SHAPE_CHANNEL_NAME,
- )
-
- # Builds and returns the created mesh paths in the scene
- return build_meshes(dna, config)
-
-
-def create_skin_cluster(influences, mesh, skin_cluster_name, maximum_influences):
- cmds.select(influences[0], replace=True)
- cmds.select(mesh, add=True)
- skinCluster = cmds.skinCluster(
- toSelectedBones=True,
- name=skin_cluster_name,
- maximumInfluences=maximum_influences,
- skinMethod=0,
- obeyMaxInfluences=True,
- )
- if len(influences) > 1:
- cmds.skinCluster(
- skinCluster, edit=True, addInfluence=influences[1:], weight=0.0
- )
- return skinCluster
-
-
-def create_head_and_body_scene(mesh_names):
- scene_mesh_names = []
- skinweights = []
-
- for mesh_name in mesh_names:
- if cmds.objExists(mesh_name):
- scene_mesh_names.append(mesh_name)
- skinweights.append(get_skin_weights_from_scene(mesh_name))
- cmds.delete(f"{mesh_name}_skinCluster")
-
- for facial_joint in FACIAL_ROOT_JOINTS:
- cmds.parent(facial_joint, world=True)
- cmds.delete(ROOT_JOINT)
-
- cmds.file(BODY_FILE, options="v=0", type="mayaAscii", i=True)
- if UP_AXIS == "y":
- cmds.joint("root", edit=True, orientation=[-90.0, 0.0, 0.0])
- for facial_joint, neck_joint in zip(FACIAL_ROOT_JOINTS, NECK_JOINTS):
- cmds.parent(facial_joint, neck_joint)
-
- for mesh_name, skinweight in zip(scene_mesh_names, skinweights):
- create_skin_cluster(
- skinweight.joints,
- mesh_name,
- f"{mesh_name}_skinCluster",
- skinweight.no_of_influences,
- )
- set_skin_weights_to_scene(mesh_name, skinweight)
-
-
-def set_fbx_options():
- # Executes FBX relate commands from the imported plugin
- min_time = cmds.playbackOptions(minTime=True, query=True)
- max_time = cmds.playbackOptions(maxTime=True, query=True)
-
- cmds.FBXResetExport()
- mel.eval("FBXExportBakeComplexAnimation -v true")
- mel.eval(f"FBXExportBakeComplexStart -v {min_time}")
- mel.eval(f"FBXExportBakeComplexEnd -v {max_time}")
- mel.eval("FBXExportConstraints -v true")
- mel.eval("FBXExportSkeletonDefinitions -v true")
- mel.eval("FBXExportInputConnections -v true")
- mel.eval("FBXExportSmoothingGroups -v true")
- mel.eval("FBXExportSkins -v true")
- mel.eval("FBXExportShapes -v true")
- mel.eval("FBXExportCameras -v false")
- mel.eval("FBXExportLights -v false")
- cmds.FBXExportUpAxis(UP_AXIS)
- # Deselects objects in Maya
- cmds.select(clear=True)
-
-
-def create_shader(name):
- cmds.shadingNode("blinn", asShader=True, name=name)
-
- shading_group = str(
- cmds.sets(
- renderable=True,
- noSurfaceShader=True,
- empty=True,
- name=f"{name}SG",
- )
- )
- cmds.connectAttr(f"{name}.outColor", f"{shading_group}.surfaceShader")
- return shading_group
-
-
-def add_shader():
- for shader_name, meshes in MESH_SHADER_MAPPING.items():
- shading_group = create_shader(shader_name)
- for mesh in meshes:
- try:
- cmds.select(mesh, replace=True)
- cmds.sets(edit=True, forceElement=shading_group)
- except Exception as e:
- print(f"Skipped adding shader for mesh {mesh}. Reason {e}")
-
-
-def set_vertex_color():
- for m, meshName in enumerate(VTX_COLOR_MESHES):
- try:
- cmds.select(meshName)
- except Exception as e:
- print(f"Skipped adding vtx color for mesh {meshName}. Reason {e}")
- continue
- for v, rgb in enumerate(VTX_COLOR_VALUES[m]):
- cmds.polyColorPerVertex(f"{meshName}.vtx[{v}]", g=rgb[1], b=rgb[2])
-
-
-def export_fbx(lod, meshes):
- # Selects every mesh in the given lod
- for item in meshes:
- cmds.select(item, add=True)
- # Adds facial root joint to selection
- cmds.select(FACIAL_ROOT_NAME, add=True)
- # Sets the file path
- export_file_name = f"{OUTPUT_DIR}/{CHARACTER_NAME}_lod{lod}.fbx"
- # Exports the fbx
- mel.eval(f'FBXExport -f "{export_file_name}" -s true')
-
-
-def export_fbx_for_lod(dna, lod):
- # Creates the meshes for the given lod
- result = build_meshes_for_lod(dna, lod)
- meshes = result.get_all_meshes()
- # Executes FBX relate commands from the imported plugin
- create_head_and_body_scene(meshes)
- set_fbx_options()
- # Saves the result
- if ADD_COLOR_VERTEX:
- add_shader()
- set_vertex_color()
- export_fbx(lod, meshes)
-
-
-if __name__ == "__main__":
- makedirs(OUTPUT_DIR, exist_ok=True)
-
- # Loads the builtin plugin needed for FBX
- cmds.loadPlugin("fbxmaya.mll")
-
- # This fixes warning when calling this script with headless maya Warning: line 1: Unknown object type: HIKCharacterNode
- mel.eval(f"HIKCharacterControlsTool;")
-
- # Generate workspace.mel
- mel.eval(f'setProject "{OUTPUT_DIR}";')
-
- # Export FBX for each lod
- cmds.upAxis(ax=UP_AXIS)
- dna = get_dna()
- for lod in range(dna.get_lod_count()):
- export_fbx_for_lod(dna, lod)
- cleanup()
diff --git a/examples/dna_viewer_grab_changes_from_scene_and_propagate_to_dna.py b/examples/dna_viewer_grab_changes_from_scene_and_propagate_to_dna.py
deleted file mode 100644
index b226f9a..0000000
--- a/examples/dna_viewer_grab_changes_from_scene_and_propagate_to_dna.py
+++ /dev/null
@@ -1,247 +0,0 @@
-"""
-This example demonstrates how to propagate changes from maya scene to dna file.
-IMPORTANT: You have to setup the environment before running this example. Please refer to the 'Environment setup' section in README.md.
-
-Follow the steps:
-
-1. Start Maya
-2. open maya scene (do 2.1 or 2.2)
-2.1. Generate new scene using build_meshes or
-2.2. start DNA Viewer GUI (dna_viewer_run_in_maya.py)
- - Select DNA file that you want to load and generate scene for
- - Select meshes that you want to change
- - Tick joints in Build Options
- - Click Process
- - in Maya scene rig is going to be assembled
-3. Run this script to the part called "load data"
- a. get current vertex positions for all meshes
-
-4. In the scene, make modifications to the neutral mesh and joints (important note:
- if you're rotating joints, be sure to freeze transformations, so they're stored as orientations)
-5. Run this script from the part called "propagate changes to dna" to the end
- a. set new joints translations
- b. set new joints rotations
- c. move all meshes vertices to new positions
-
-After performing this steps, your changes in maya scene will pe propagated to dna.
-
-- usage in Maya:
- 1. copy whole content of this file to Maya Script Editor
- 2. change value of ROOT_DIR to absolute path of dna_calibration, e.g. `c:/dna_calibration` in Windows or `/home/user/dna_calibration`. Important:
- Use `/` (forward slash), because Maya uses forward slashes in path.
-
-- customization:
- - change CHARACTER_NAME to Taro, or the name of a custom DNA file placed in /data/dna_files
-
-Expected:
- - script will generate dna file _modified.dna in OUTPUT_DIR, e.g. Ada_modified.dna
- - script will generate maya scene _modified.mb in OUTPUT_DIR, e.g. Ada_modified.mb
- - script will generate workspace.mel in OUTPUT_DIR
-
-NOTE: If OUTPUT_DIR does not exist, it will be created.
-"""
-
-import maya.OpenMaya as om
-from maya import cmds
-
-from os import makedirs
-from os import path as ospath
-
-CHARACTER_NAME = "Ada"
-
-# If you use Maya, use absolute path
-ROOT_DIR = f"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/")
-OUTPUT_DIR = f"{ROOT_DIR}/output"
-ROOT_LIB_DIR = f"{ROOT_DIR}/lib"
-DATA_DIR = f"{ROOT_DIR}/data"
-DNA_DIR = f"{DATA_DIR}/dna_files"
-CHARACTER_DNA = f"{DNA_DIR}/{CHARACTER_NAME}.dna"
-ANALOG_GUI = f"{DATA_DIR}/analog_gui.ma"
-GUI = f"{DATA_DIR}/gui.ma"
-ADDITIONAL_ASSEMBLE_SCRIPT = f"{DATA_DIR}/additional_assemble_script.py"
-ADD_MESH_NAME_TO_BLEND_SHAPE_CHANNEL_NAME = True
-
-MODIFIED_CHARACTER_DNA = f"{OUTPUT_DIR}/{CHARACTER_NAME}_modified"
-
-from dna import (
- BinaryStreamReader,
- BinaryStreamWriter,
- DataLayer_All,
- FileStream,
- Status,
-)
-from dnacalib import (
- CommandSequence,
- DNACalibDNAReader,
- SetNeutralJointRotationsCommand,
- SetNeutralJointTranslationsCommand,
- SetVertexPositionsCommand,
- VectorOperation_Add,
-)
-
-from dna_viewer import DNA, RigConfig, build_rig, build_meshes
-
-
-def load_dna_reader(path):
- stream = FileStream(path, FileStream.AccessMode_Read, FileStream.OpenMode_Binary)
- reader = BinaryStreamReader(stream, DataLayer_All)
- reader.read()
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error loading DNA: {status.message}")
- return reader
-
-
-def save_dna(reader):
- stream = FileStream(
- f"{MODIFIED_CHARACTER_DNA}.dna",
- FileStream.AccessMode_Write,
- FileStream.OpenMode_Binary,
- )
- writer = BinaryStreamWriter(stream)
- writer.setFrom(reader)
- writer.write()
-
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error saving DNA: {status.message}")
-
-
-def get_mesh_vertex_positions_from_scene(meshName):
- try:
- sel = om.MSelectionList()
- sel.add(meshName)
-
- dag_path = om.MDagPath()
- sel.getDagPath(0, dag_path)
-
- mf_mesh = om.MFnMesh(dag_path)
- positions = om.MPointArray()
-
- mf_mesh.getPoints(positions, om.MSpace.kObject)
- return [
- [positions[i].x, positions[i].y, positions[i].z]
- for i in range(positions.length())
- ]
- except RuntimeError:
- print(f"{meshName} is missing, skipping it")
- return None
-
-
-def run_joints_command(reader, calibrated):
- # Making arrays for joints' transformations and their corresponding mapping arrays
- joint_translations = []
- joint_rotations = []
-
- for i in range(reader.getJointCount()):
- joint_name = reader.getJointName(i)
-
- translation = cmds.xform(joint_name, query=True, translation=True)
- joint_translations.append(translation)
-
- rotation = cmds.joint(joint_name, query=True, orientation=True)
- joint_rotations.append(rotation)
-
- # This is step 5 sub-step a
- set_new_joints_translations = SetNeutralJointTranslationsCommand(joint_translations)
- # This is step 5 sub-step b
- set_new_joints_rotations = SetNeutralJointRotationsCommand(joint_rotations)
-
- # Abstraction to collect all commands into a sequence, and run them with only one invocation
- commands = CommandSequence()
- # Add vertex position deltas (NOT ABSOLUTE VALUES) onto existing vertex positions
- commands.add(set_new_joints_translations)
- commands.add(set_new_joints_rotations)
-
- commands.run(calibrated)
- # Verify that everything went fine
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error run_joints_command: {status.message}")
-
-
-def run_vertices_command(
- calibrated, old_vertices_positions, new_vertices_positions, mesh_index
-):
- # Making deltas between old vertices positions and new one
- deltas = []
- for new_vertex, old_vertex in zip(new_vertices_positions, old_vertices_positions):
- delta = []
- for new, old in zip(new_vertex, old_vertex):
- delta.append(new - old)
- deltas.append(delta)
-
- # This is step 5 sub-step c
- new_neutral_mesh = SetVertexPositionsCommand(
- mesh_index, deltas, VectorOperation_Add
- )
- commands = CommandSequence()
- # Add nex vertex position deltas (NOT ABSOLUTE VALUES) onto existing vertex positions
- commands.add(new_neutral_mesh)
- commands.run(calibrated)
-
- # Verify that everything went fine
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error run_vertices_command: {status.message}")
-
-
-def assemble_maya_scene():
- dna = DNA(f"{MODIFIED_CHARACTER_DNA}.dna")
- config = RigConfig(
- gui_path=f"{DATA_DIR}/gui.ma",
- analog_gui_path=f"{DATA_DIR}/analog_gui.ma",
- aas_path=ADDITIONAL_ASSEMBLE_SCRIPT,
- )
- build_rig(dna=dna, config=config)
-
- cmds.file(rename=f"{MODIFIED_CHARACTER_DNA}.mb")
- cmds.file(save=True)
-
-
-makedirs(OUTPUT_DIR, exist_ok=True)
-
-dna = DNA(CHARACTER_DNA)
-##################################
-# This is step 2 sub-step 1
-# use this block only if you need to assemble of scene from step 2.1
-# config = RigConfig(
-# gui_path=f"{DATA_DIR}/gui.ma",
-# analog_gui_path=f"{DATA_DIR}/analog_gui.ma",
-# aas_path=ADDITIONAL_ASSEMBLE_SCRIPT,
-# )
-# build_meshes(dna=dna, config=config)
-# This is end of step 2 sub-step 1
-##################################
-
-
-# This is step 3 sub-step a
-current_vertices_positions = {}
-mesh_indices = []
-for mesh_index, name in enumerate(dna.meshes.names):
- current_vertices_positions[name] = {
- "mesh_index": mesh_index,
- "positions": get_mesh_vertex_positions_from_scene(name),
- }
-# Loaded data - end of 3rd step
-##################################
-
-##################################
-# Modify rig in maya, 4th step
-##################################
-
-##################################
-# Propagate changes to dna, 5th step
-reader = load_dna_reader(CHARACTER_DNA)
-calibrated = DNACalibDNAReader(reader)
-
-run_joints_command(reader, calibrated)
-
-for name, item in current_vertices_positions.items():
- new_vertices_positions = get_mesh_vertex_positions_from_scene(name)
- if new_vertices_positions:
- run_vertices_command(
- calibrated, item["positions"], new_vertices_positions, item["mesh_index"]
- )
-save_dna(calibrated)
-assemble_maya_scene()
diff --git a/examples/dna_viewer_run_in_maya.py b/examples/dna_viewer_run_in_maya.py
deleted file mode 100644
index bffb2f2..0000000
--- a/examples/dna_viewer_run_in_maya.py
+++ /dev/null
@@ -1,17 +0,0 @@
-"""
-This example demonstrates Maya UI Window for simple and non-programmatic creation the scene with the creating functional rig.
-IMPORTANT: You have to setup the environment before running this example. Please refer to the 'Environment setup' section in README.md.
-
-- usage in command line:
- NOTE: Script cannot be called with Python or mayapy, it must be called in Maya Script Editor.
-- usage in Maya:
- Expected: Maya will show UI.
-
-"""
-
-
-# This example is intended to be used in Maya
-
-import dna_viewer
-
-dna_viewer.show()
diff --git a/examples/dnacalib_clear_blend_shapes.py b/examples/dnacalib_clear_blend_shapes.py
deleted file mode 100644
index 9d8f996..0000000
--- a/examples/dnacalib_clear_blend_shapes.py
+++ /dev/null
@@ -1,144 +0,0 @@
-"""
-This example demonstrates how to remove all blend shape data from a DNA.
-IMPORTANT: You have to setup the environment before running this example. Please refer to the 'Environment setup' section in README.md.
-
-- usage in command line:
- python dnacalib_clear_blend_shapes.py
- mayapy dnacalib_clear_blend_shapes.py
-- usage in Maya:
- 1. copy whole content of this file to Maya Script Editor
- 2. change value of ROOT_DIR to absolute path of dna_calibration, e.g. `c:/dna_calibration` in Windows or `/home/user/dna_calibration`. Important:
- Use `/` (forward slash), because Maya uses forward slashes in path.
-
-- customization:
- - change CHARACTER_NAME to Taro, or the name of a custom DNA file placed in /data/dna_files
-
-Expected: Script will generate Ada_output.dna in OUTPUT_DIR from original Ada.dna.
-NOTE: If OUTPUT_DIR does not exist, it will be created.
-"""
-
-from os import makedirs
-from os import path as ospath
-
-# if you use Maya, use absolute path
-ROOT_DIR = f"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/")
-OUTPUT_DIR = f"{ROOT_DIR}/output"
-
-CHARACTER_NAME = "Ada"
-
-DATA_DIR = f"{ROOT_DIR}/data"
-CHARACTER_DNA = f"{DATA_DIR}/dna_files/{CHARACTER_NAME}.dna"
-OUTPUT_DNA = f"{OUTPUT_DIR}/{CHARACTER_NAME}_output.dna"
-
-
-from dna import DataLayer_All, FileStream, Status, BinaryStreamReader, BinaryStreamWriter
-from dnacalib import (
- DNACalibDNAReader,
- ClearBlendShapesCommand
-)
-
-
-def load_dna(path):
- stream = FileStream(path, FileStream.AccessMode_Read, FileStream.OpenMode_Binary)
- reader = BinaryStreamReader(stream, DataLayer_All)
- reader.read()
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error loading DNA: {status.message}")
- return reader
-
-
-def save_dna(reader, path):
- stream = FileStream(path, FileStream.AccessMode_Write, FileStream.OpenMode_Binary)
- writer = BinaryStreamWriter(stream)
- writer.setFrom(reader)
- writer.write()
-
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error saving DNA: {status.message}")
-
-
-def validate_geometry(dna):
- mesh_count = dna.getMeshCount()
- for mesh_index in range(mesh_count):
- bs_tgt_count = dna.getBlendShapeTargetCount(mesh_index)
- for bs_tgt_index in range(bs_tgt_count):
- bs_tgt_delta_count = dna.getBlendShapeTargetDeltaCount(mesh_index, bs_tgt_index)
- if bs_tgt_delta_count != 0:
- raise RuntimeError("Blend shape target deltas not removed properly!")
-
-
-def validate_animation_data(dna):
- bs_channel_lods = dna.getBlendShapeChannelLODs()
- bs_channel_input_indices = dna.getBlendShapeChannelInputIndices()
- bs_channel_output_indices = dna.getBlendShapeChannelOutputIndices()
-
- if len(bs_channel_lods) != dna.getLODCount():
- raise RuntimeError("Blend shape animation data not removed properly! Number of blend shape LODs does not match LOD count!")
-
- for lod in bs_channel_lods:
- if lod != 0:
- raise RuntimeError("Blend shape animation data not removed properly!")
-
- if (len(bs_channel_input_indices) != 0) or (len(bs_channel_output_indices) != 0):
- raise RuntimeError("Blend shape animation data not removed properly!")
-
-
-def calibrate_dna(input_path, output_path):
- dna = load_dna(input_path)
-
- # Copies DNA contents and will serve as input/output parameter to commands
- calibrated = DNACalibDNAReader(dna)
-
- mesh_count = calibrated.getMeshCount()
- print(f"Number of meshes: {mesh_count}")
-
- for mesh_index in range(mesh_count):
- bs_tgt_count = calibrated.getBlendShapeTargetCount(mesh_index)
- print(f"Number of blendshape targets for mesh {calibrated.getMeshName(mesh_index)}({mesh_index}): {bs_tgt_count}")
- for bs_tgt_index in range(bs_tgt_count):
- bs_tgt_delta_count = calibrated.getBlendShapeTargetDeltaCount(mesh_index, bs_tgt_index)
- print(f"Number of blendshape target deltas for mesh {calibrated.getMeshName(mesh_index)}({mesh_index}), blend shape target {bs_tgt_index}: {bs_tgt_delta_count}")
-
- print(f"Blend shape channel LODs: {calibrated.getBlendShapeChannelLODs()}")
- print(f"Blend shape channel input indices: {calibrated.getBlendShapeChannelInputIndices()}")
- print(f"Blend shape channel output indices: {calibrated.getBlendShapeChannelOutputIndices()}")
-
- # Clears all blend shapes
- command = ClearBlendShapesCommand()
-
- print("\n\nClearing blend shape data...\n\n")
- # Modifies calibrated DNA in-place
- command.run(calibrated)
-
- validate_geometry(calibrated)
- validate_animation_data(calibrated)
-
- print(f"Number of meshes: {mesh_count}")
-
- for mesh_index in range(mesh_count):
- bs_tgt_count = calibrated.getBlendShapeTargetCount(mesh_index)
- print(f"Number of blendshape targets for mesh {calibrated.getMeshName(mesh_index)}({mesh_index}): {bs_tgt_count}")
- for bs_tgt_index in range(bs_tgt_count):
- bs_tgt_delta_count = calibrated.getBlendShapeTargetDeltaCount(mesh_index, bs_tgt_index)
- print(f"Number of blendshape target deltas for mesh {calibrated.getMeshName(mesh_index)}({mesh_index}), blend shape target {bs_tgt_index}: {bs_tgt_delta_count}")
-
- bs_channel_lods = dna.getBlendShapeChannelLODs()
- bs_channel_input_indices = dna.getBlendShapeChannelInputIndices()
- bs_channel_output_indices = dna.getBlendShapeChannelOutputIndices()
-
- print(f"Blend shape channel LODs: {bs_channel_lods}")
- print(f"Blend shape channel input indices: {bs_channel_input_indices}")
- print(f"Blend shape channel output indices: {bs_channel_output_indices}")
-
- print("\n\nSuccessfully cleared blend shape data.")
-
- print("Saving DNA...")
- save_dna(calibrated, output_path)
- print("Done.")
-
-
-if __name__ == "__main__":
- makedirs(OUTPUT_DIR, exist_ok=True)
- calibrate_dna(CHARACTER_DNA, OUTPUT_DNA)
diff --git a/examples/dnacalib_demo.py b/examples/dnacalib_demo.py
deleted file mode 100644
index 9448b00..0000000
--- a/examples/dnacalib_demo.py
+++ /dev/null
@@ -1,154 +0,0 @@
-"""
-This example demonstrates a few DNACalib's commands.
-IMPORTANT: You have to setup the environment before running this example. Please refer to the 'Environment setup' section in README.md.
-
-- usage in command line:
- python dnacalib_demo.py
- mayapy dnacalib_demo.py
-
-- usage in Maya:
- 1. copy whole content of this file to Maya Script Editor
- 2. change value of ROOT_DIR to absolute path of dna_calibration, e.g. `c:/dna_calibration` in Windows or `/home/user/dna_calibration`. Important:
- Use `/` (forward slash), because Maya uses forward slashes in path.
-
-- customization:
- - change CHARACTER_NAME to Taro, or the name of a custom DNA file placed in /data/dna_files
-
-
-Expected: Script will generate Ada_output.dna in OUTPUT_DIR from original Ada.dna.
-NOTE: If OUTPUT_DIR does not exist, it will be created.
-"""
-
-from os import makedirs
-from os import path as ospath
-
-# if you use Maya, use absolute path
-ROOT_DIR = f"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/")
-OUTPUT_DIR = f"{ROOT_DIR}/output"
-
-CHARACTER_NAME = "Ada"
-
-DATA_DIR = f"{ROOT_DIR}/data"
-CHARACTER_DNA = f"{DATA_DIR}/dna_files/{CHARACTER_NAME}.dna"
-OUTPUT_DNA = f"{OUTPUT_DIR}/{CHARACTER_NAME}_output.dna"
-
-from dna import DataLayer_All, FileStream, Status, BinaryStreamReader, BinaryStreamWriter
-from dnacalib import (
- CommandSequence,
- DNACalibDNAReader,
- RenameJointCommand,
- ScaleCommand,
- SetBlendShapeTargetDeltasCommand,
- SetVertexPositionsCommand,
- VectorOperation_Add,
- VectorOperation_Interpolate,
-)
-
-
-def load_dna(path):
- stream = FileStream(path, FileStream.AccessMode_Read, FileStream.OpenMode_Binary)
- reader = BinaryStreamReader(stream, DataLayer_All)
- reader.read()
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error loading DNA: {status.message}")
- return reader
-
-
-def save_dna(reader, path):
- stream = FileStream(path, FileStream.AccessMode_Write, FileStream.OpenMode_Binary)
- writer = BinaryStreamWriter(stream)
- writer.setFrom(reader)
- writer.write()
-
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error saving DNA: {status.message}")
-
-
-def build_command_list():
- # Abstraction to collect all commands into a sequence, and run them with only one invocation
- commands = CommandSequence()
-
- print("Creating a sequence of commands...")
- # Instantiate command with parameters: scale-factor = 2 , origin-xyz = (0, 120, 0)
- scale_by_two = ScaleCommand(2.0, [0.0, 120.0, 0.0])
- # Alternatively a command can be instantiated empty, and populated with parameters later, e.g.:
- # scale_by_two = ScaleCommand()
- # scale_by_two.setScale(2.0)
- # scale_by_two.setOrigin([0.0, 120.0, 0.0])
- commands.add(scale_by_two)
-
- print("Added command to scale dna")
- # Rename by joint index (faster)
- commands.add(RenameJointCommand(10, "NewJointA"))
-
- # Rename by matching joint name (slower)
- commands.add(RenameJointCommand("OldJointB", "NewJointB"))
-
- print("Added command to rename joint")
- # Interpolate blend shape target deltas between original DNA and below specified deltas
- # ¯\_(ツ)_/¯
- # Deltas in [[x, y, z], [x, y, z], [x, y, z]] format
- blend_shape_target_deltas = [[0.0, 0.0, 2.0], [0.0, -1.0, 4.0], [3.0, -3.0, 8.0]]
- vertex_indices = [0, 1, 2]
- # Weights for interpolation between original deltas and above defined deltas
- # 1.0 == take the new value completely, 0.0 means keep the old value
- # Format: [Delta-0-Mask, Delta-1-Mask, Delta-2-Mask]
- masks = [1.0, 0.0, 0.5]
- set_blend_shapes_m0_b0 = SetBlendShapeTargetDeltasCommand(
- 0, # mesh index
- 0, # blend shape target index
- blend_shape_target_deltas,
- vertex_indices,
- masks,
- VectorOperation_Interpolate,
- )
- commands.add(set_blend_shapes_m0_b0)
- print("Added command to change blend shape target deltas")
-
- # Add vertex position deltas onto existing vertex positions
- # Note the alternative data format, instead of using nested lists, separate all X, Y, Z
- # components into distinct lists (might also be faster)
- position_xs = [1.0, -4.5, 7.2]
- position_ys = [2.0, -5.5, -8.3]
- position_zs = [3.0, -6.5, 9.7]
- # Weights to be multiplied with the above specified delta positions, before adding
- # them onto the original data
- # Format: [Delta-0-Weight, Delta-1-Weight, Delta-2-Weight]
- masks = [1.0, 0.2, 0.4]
- set_vertices_m0 = SetVertexPositionsCommand(
- 0, # mesh index
- position_xs,
- position_ys,
- position_zs,
- masks,
- VectorOperation_Add,
- )
- commands.add(set_vertices_m0)
- print("Added command to change vertex positions")
-
- return commands
-
-
-def calibrate_dna(input_path, output_path):
- dna = load_dna(input_path)
-
- # Copies DNA contents and will serve as input/output parameter to commands
- calibrated = DNACalibDNAReader(dna)
-
- commands = build_command_list()
-
- print("Running command sequence...")
- # Modifies calibrated DNA in-place
- commands.run(calibrated)
-
- print("Saving DNA...")
- save_dna(calibrated, output_path)
-
- print("Done.")
-
-
-if __name__ == "__main__":
- makedirs(OUTPUT_DIR, exist_ok=True)
- calibrate_dna(CHARACTER_DNA, OUTPUT_DNA)
diff --git a/examples/dnacalib_lod_demo.py b/examples/dnacalib_lod_demo.py
deleted file mode 100644
index 9001ecc..0000000
--- a/examples/dnacalib_lod_demo.py
+++ /dev/null
@@ -1,86 +0,0 @@
-"""
-This example demonstrates creation of a new DNA from an existing one by extracting specific lods.
-IMPORTANT: You have to setup the environment before running this example. Please refer to the 'Environment setup' section in README.md.
-
-- usage in command line:
- python dnacalib_lod_demo.py
- mayapy dnacalib_lod_demo.py
-
-- usage in Maya:
- 1. copy whole content of this file to Maya Script Editor
- 2. change value of ROOT_DIR to absolute path of dna_calibration, e.g. `c:/dna_calibration` in Windows or `/home/user/dna_calibration`. Important:
- Use `/` (forward slash), because Maya uses forward slashes in path.
-
-- customization:
- - change CHARACTER_NAME to Taro, or the name of a custom DNA file placed in /data/dna_files
- - change value of LODS to list of lods needed to be extracted
-
-Expected: Script will generate Ada_with_lods_1_and_3.dna in OUTPUT_DIR, from original Ada.
-NOTE: If OUTPUT_DIR does not exist, it will be created.
-"""
-
-
-from os import makedirs
-from os import path as ospath
-
-# if you use Maya, use absolute path
-ROOT_DIR = f"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/")
-OUTPUT_DIR = f"{ROOT_DIR}/output"
-
-from dna import DataLayer_All, FileStream, Status, BinaryStreamReader, BinaryStreamWriter
-from dnacalib import (
- DNACalibDNAReader,
- SetLODsCommand,
-)
-
-# Sets DNA file path
-DNA = f"{ROOT_DIR}/data/dna_files/Ada.dna"
-# Sets new DNA output file path
-DNA_NEW = f"{OUTPUT_DIR}/Ada_with_lods_1_and_3.dna"
-# Sets lods to extract
-LODS = [1, 3]
-
-
-def save_dna(reader: DNACalibDNAReader, created_dna_path: str):
- # Saves the dna
- stream = FileStream(created_dna_path, FileStream.AccessMode_Write, FileStream.OpenMode_Binary)
- writer = BinaryStreamWriter(stream)
- writer.setFrom(reader)
- writer.write()
-
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error saving DNA: {status.message}")
-
-
-def run_SetLODsCommand(reader):
- calibrated = DNACalibDNAReader(reader)
- command = SetLODsCommand()
- # Set a list of LODs that will be exported to the new file
- command.setLODs(LODS)
- # Runs the command that reduces LODs of the DNA
- command.run(calibrated)
- print("Setting new LODs...")
-
- if calibrated.getLODCount() != 2:
- raise RuntimeError("Setting new number of LODs in DNA was unsuccessful!")
-
- print("\nSuccessfully changed number of LODs in ")
- print("Saving ..")
- # Save the newly created DNA
- save_dna(calibrated, DNA_NEW)
- print("Done.")
-
-
-def load_dna_calib(dna_path: str):
- # Load the DNA
- stream = FileStream(dna_path, FileStream.AccessMode_Read, FileStream.OpenMode_Binary)
- reader = BinaryStreamReader(stream, DataLayer_All)
- reader.read()
- return reader
-
-
-if __name__ == "__main__":
- makedirs(OUTPUT_DIR, exist_ok=True)
- reader = load_dna_calib(DNA)
- run_SetLODsCommand(reader)
diff --git a/examples/dnacalib_neutral_mesh_subtract.py b/examples/dnacalib_neutral_mesh_subtract.py
deleted file mode 100644
index 69c8cad..0000000
--- a/examples/dnacalib_neutral_mesh_subtract.py
+++ /dev/null
@@ -1,139 +0,0 @@
-"""
-This example demonstrates how to subtract values from a neutral mesh and transfer those changes to its lower LOD meshes.
-IMPORTANT: You have to setup the environment before running this example. Please refer to the 'Environment setup' section in README.md.
-
-- usage in command line:
- python dnacalib_neutral_mesh_subtract.py
- mayapy dnacalib_neutral_mesh_subtract.py
-- usage in Maya:
- 1. copy whole content of this file to Maya Script Editor
- 2. change value of ROOT_DIR to absolute path of dna_calibration, e.g. `c:/dna_calibration` in Windows or `/home/user/dna_calibration`. Important:
- Use `/` (forward slash), because Maya uses forward slashes in path.
-
-- customization:
- - change CHARACTER_NAME to Taro, or the name of a custom DNA file placed in /data/dna_files
-
-Expected: Script will generate Ada_output.dna in OUTPUT_DIR from original Ada.dna.
-NOTE: If OUTPUT_DIR does not exist, it will be created.
-"""
-
-from os import makedirs
-from os import path as ospath
-
-# if you use Maya, use absolute path
-ROOT_DIR = f"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/")
-OUTPUT_DIR = f"{ROOT_DIR}/output"
-
-CHARACTER_NAME = "Ada"
-
-DATA_DIR = f"{ROOT_DIR}/data"
-CHARACTER_DNA = f"{DATA_DIR}/dna_files/{CHARACTER_NAME}.dna"
-OUTPUT_DNA = f"{OUTPUT_DIR}/{CHARACTER_NAME}_output.dna"
-
-from dna import DataLayer_All, FileStream, Status, BinaryStreamReader, BinaryStreamWriter
-from dnacalib import (
- DNACalibDNAReader,
- SetVertexPositionsCommand,
- VectorOperation_Subtract,
- CalculateMeshLowerLODsCommand
-)
-from math import isclose
-
-
-def load_dna(path):
- stream = FileStream(path, FileStream.AccessMode_Read, FileStream.OpenMode_Binary)
- reader = BinaryStreamReader(stream, DataLayer_All)
- reader.read()
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error loading DNA: {status.message}")
- return reader
-
-
-def save_dna(reader, path):
- stream = FileStream(path, FileStream.AccessMode_Write, FileStream.OpenMode_Binary)
- writer = BinaryStreamWriter(stream)
- writer.setFrom(reader)
- writer.write()
-
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error saving DNA: {status.message}")
-
-
-def calibrate_dna(input_path, output_path):
- dna = load_dna(input_path)
-
- # Copies DNA contents and will serve as input/output parameter to commands
- calibrated = DNACalibDNAReader(dna)
-
- if calibrated.getMeshCount() == 0:
- print("No meshes found in DNA.")
- return
-
- mesh_index = 0
- vtx_count_mesh0 = calibrated.getVertexPositionCount(mesh_index)
- xs = calibrated.getVertexPositionXs(mesh_index)
- ys = calibrated.getVertexPositionYs(mesh_index)
- zs = calibrated.getVertexPositionZs(mesh_index)
-
- # Example values to subtract from original vertex positions for mesh with index 0
- ones = [1.0] * vtx_count_mesh0
-
- # Command used to subtract example values from a specified neutral mesh
- subtract_command = SetVertexPositionsCommand()
- subtract_command.setMeshIndex(mesh_index)
- subtract_command.setOperation(VectorOperation_Subtract)
- subtract_command.setPositions(ones, ones, ones)
-
- # Alternatively, if you wanted to do the opposite, to subtract neutral mesh values
- # from example values, you could do the following:
- # xs_2 = [x * 2 for x in xs]
- # ys_2 = [y * 2 for y in ys]
- # zs_2 = [z * 2 for z in zs]
- # subtract_command.setPositions(xs_2, ys_2, zs_2)
- # # After running the command, the calibrated DNA will contain -xs, -ys, -zs
- # subtract_command.run(calibrated)
- #
- # # Add the example values, which will result in:
- # # ones - xs
- # # ones - ys
- # # ones - zs
- # add_command = SetVertexPositionsCommand()
- # add_command.setMeshIndex(mesh_index)
- # add_command.setOperation(VectorOperation_Add) # remember to add VectorOperation_Add to the list of imports
- # add_command.setPositions(ones, ones, ones)
- # add_command.run(calibrated)
-
- print(f"Subtracting values from neutral mesh \'{calibrated.getMeshName(mesh_index)}\'...")
- # Modifies calibrated DNA in-place
- subtract_command.run(calibrated)
-
- # Command used to recalculate vertex positions of lower LOD neutral meshes of the specified neutral mesh
- calculate_lower_lods_command = CalculateMeshLowerLODsCommand()
- calculate_lower_lods_command.setMeshIndex(mesh_index)
-
- print("Recalculating values for lower LOD meshes...")
- # Modifies calibrated DNA in-place
- calculate_lower_lods_command.run(calibrated)
-
- new_xs = calibrated.getVertexPositionXs(mesh_index)
- new_ys = calibrated.getVertexPositionYs(mesh_index)
- new_zs = calibrated.getVertexPositionZs(mesh_index)
-
- for i in range(vtx_count_mesh0):
- if (not isclose(xs[i] - 1, new_xs[i], rel_tol=1e-7) or
- not isclose(ys[i] - 1, new_ys[i], rel_tol=1e-7) or
- not isclose(zs[i] - 1, new_zs[i], rel_tol=1e-7)):
- raise RuntimeError("Vertex positions were not changed successfully!")
-
- print("\nSuccessfully changed vertex positions.")
-
- print("Saving DNA...")
- save_dna(calibrated, output_path)
- print("Done.")
-
-
-if __name__ == "__main__":
- makedirs(OUTPUT_DIR, exist_ok=True)
- calibrate_dna(CHARACTER_DNA, OUTPUT_DNA)
diff --git a/examples/dnacalib_remove_joint.py b/examples/dnacalib_remove_joint.py
deleted file mode 100644
index 508cb4b..0000000
--- a/examples/dnacalib_remove_joint.py
+++ /dev/null
@@ -1,102 +0,0 @@
-"""
-This example demonstrates a few DNACalib's commands.
-IMPORTANT: You have to setup the environment before running this example. Please refer to the 'Environment setup' section in README.md.
-
-- usage in command line:
- python dnacalib_remove_joint.py
- mayapy dnacalib_remove_joint.py
-- usage in Maya:
- 1. copy whole content of this file to Maya Script Editor
- 2. change value of ROOT_DIR to absolute path of dna_calibration, e.g. `c:/dna_calibration` in Windows or `/home/user/dna_calibration`. Important:
- Use `/` (forward slash), because Maya uses forward slashes in path.
-
-- customization:
- - change CHARACTER_NAME to Taro, or the name of a custom DNA file placed in /data/dna_files
-
-Expected: Script will generate Ada_output.dna in OUTPUT_DIR from original Ada.dna.
-NOTE: If OUTPUT_DIR does not exist, it will be created.
-"""
-
-
-from os import makedirs
-from os import path as ospath
-
-# if you use Maya, use absolute path
-ROOT_DIR = f"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/")
-OUTPUT_DIR = f"{ROOT_DIR}/output"
-
-CHARACTER_NAME = "Ada"
-
-DATA_DIR = f"{ROOT_DIR}/data"
-CHARACTER_DNA = f"{DATA_DIR}/dna_files/{CHARACTER_NAME}.dna"
-OUTPUT_DNA = f"{OUTPUT_DIR}/{CHARACTER_NAME}_output.dna"
-
-from dna import DataLayer_All, FileStream, Status, BinaryStreamReader, BinaryStreamWriter
-from dnacalib import (
- DNACalibDNAReader,
- RemoveJointCommand,
-)
-
-
-def load_dna(path):
- stream = FileStream(path, FileStream.AccessMode_Read, FileStream.OpenMode_Binary)
- reader = BinaryStreamReader(stream, DataLayer_All)
- reader.read()
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error loading DNA: {status.message}")
- return reader
-
-
-def save_dna(reader, path):
- stream = FileStream(path, FileStream.AccessMode_Write, FileStream.OpenMode_Binary)
- writer = BinaryStreamWriter(stream)
- writer.setFrom(reader)
- writer.write()
-
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error saving DNA: {status.message}")
-
-
-def get_joints(dna):
- joints = []
- for jointIndex in range(dna.getJointCount()):
- joints.append(dna.getJointName(jointIndex))
- return joints
-
-
-def calibrate_dna(input_path, output_path):
- dna = load_dna(input_path)
-
- # Copies DNA contents and will serve as input/output parameter to command
- calibrated = DNACalibDNAReader(dna)
-
- original_joints = get_joints(calibrated)
-
- # An example joint to remove
- joint_index = 314
- joint_name = calibrated.getJointName(joint_index)
-
- # Removes joint with specified index
- command = RemoveJointCommand(joint_index)
-
- # Modifies calibrated DNA in-place
- command.run(calibrated)
-
- modified_joints = get_joints(calibrated)
-
- if (len(modified_joints) != (len(original_joints) - 1)) or (joint_name in modified_joints):
- raise RuntimeError("Joint not removed properly!")
-
- print(f"Successfully removed joint `{joint_name}`.")
-
- print("Saving DNA...")
- save_dna(calibrated, output_path)
-
- print("Done.")
-
-
-if __name__ == "__main__":
- makedirs(OUTPUT_DIR, exist_ok=True)
- calibrate_dna(CHARACTER_DNA, OUTPUT_DNA)
diff --git a/examples/dnacalib_rename_joint_demo.py b/examples/dnacalib_rename_joint_demo.py
deleted file mode 100644
index 6fd6d3c..0000000
--- a/examples/dnacalib_rename_joint_demo.py
+++ /dev/null
@@ -1,74 +0,0 @@
-"""
-This example demonstrates rename of a joint.
-IMPORTANT: You have to setup the environment before running this example. Please refer to the 'Environment setup' section in README.md.
-
-- usage in command line:
- python rename_joint_demo.py
- mayapy rename_joint_demo.py
-
- Expected: Script will generate Ada_output.dna in OUTPUT_DIR.
-- usage in Maya:
- 1. copy whole content of this file to Maya Script Editor
- 2. change value of ROOT_DIR to absolute path of dna_calibration, e.g. `c:/dna_calibration` in Windows or `/home/user/dna_calibration`. Important:
- Use `/` (forward slash), because Maya uses forward slashes in path.
-
-- customization:
- - change CHARACTER_NAME to Taro, or the name of a custom DNA file placed in /data/dna_files
-
-Expected: Script will generate Ada_output.dna in OUTPUT_DIR from original Ada.dna.
-NOTE: If OUTPUT_DIR does not exist, it will be created.
-"""
-
-from os import makedirs
-from os import path as ospath
-
-# if you use Maya, use absolute path
-ROOT_DIR = f"{ospath.dirname(ospath.abspath(__file__))}/..".replace("\\", "/")
-OUTPUT_DIR = f"{ROOT_DIR}/output"
-
-CHARACTER_NAME = "Ada"
-
-DATA_DIR = f"{ROOT_DIR}/data"
-CHARACTER_DNA = f"{DATA_DIR}/dna_files/{CHARACTER_NAME}.dna"
-OUTPUT_DNA = f"{OUTPUT_DIR}/{CHARACTER_NAME}_output.dna"
-
-from dna import DataLayer_All, FileStream, Status, BinaryStreamReader, BinaryStreamWriter
-from dnacalib import DNACalibDNAReader, RenameJointCommand
-
-
-def load_dna(path):
- stream = FileStream(path, FileStream.AccessMode_Read, FileStream.OpenMode_Binary)
- reader = BinaryStreamReader(stream, DataLayer_All)
- reader.read()
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error loading DNA: {status.message}")
- return reader
-
-
-def save_dna(reader, path):
- stream = FileStream(path, FileStream.AccessMode_Write, FileStream.OpenMode_Binary)
- writer = BinaryStreamWriter(stream)
- writer.setFrom(reader)
- writer.write()
-
- if not Status.isOk():
- status = Status.get()
- raise RuntimeError(f"Error saving DNA: {status.message}")
-
-
-if __name__ == "__main__":
- makedirs(OUTPUT_DIR, exist_ok=True)
-
- dna_reader = load_dna(CHARACTER_DNA)
- calibrated = DNACalibDNAReader(dna_reader)
- # Prints current joint name
- print(calibrated.getJointName(10))
- # Creates rename command
- rename = RenameJointCommand(10, "NewJointA")
- # Executes command
- rename.run(calibrated)
- # Prints the new joint name
- print(calibrated.getJointName(10))
- save_dna(calibrated, OUTPUT_DNA)
- print('Done.')