Blender中的DNA
DNA是一个生物学名词,DNA是所有生物的遗传物质基础。生物体亲子之间的相似性和继承性即所谓遗传信息,都贮存在DNA分子中。
Blender把所有需要序列化的(可以保存到文件的结构数据)核心结构称之为DNA,这些自定义的数据结构(如Object,ID,bScreen,材料、纹理、几何体:网格、曲线...),这些核心结构就是Blender的遗传物质基础-DNA。因为在Blender的各个版本中这些结构可能有些改进,所以每个版本都保存一份自己特有的DNA,每个Blender保存.blend文件中也保存有一份自身的DNA数据。
在Blender源码中,这些结构都定义在以"DNA_(类型名)_(type).h"类似命名的头文件中,位于source\blender\makesdna目录中。
为了解决这些DNA结构的序列化和相关处理工作,有一个小程序叫makesdna(是一个独立的可执行程序),该程序扫描所有DNA文件,查找要序列化的DNA。生成以下三个文件:dna.c、dna_verify.c、dna_type_offsets.h它将所有DNA序列化到一个数组常量中,用于Blender主程序相关代码中。
dna_type_offsets.h中定义了一个枚举类型,定义了所有DNA结构对应的枚举常量。
#pragma once
#define SDNA_TYPE_FROM_STRUCT(id) _SDNA_TYPE_##id
enum {
_SDNA_TYPE_DrawDataList = 0,
...
_SDNA_TYPE_IDProperty = 7,
...
_SDNA_TYPE_ID_Runtime = 12,
_SDNA_TYPE_ID = 13,
...
_SDNA_TYPE_Object_Runtime = 543,
_SDNA_TYPE_ObjectLineArt = 544,
_SDNA_TYPE_Object = 545,
_SDNA_TYPE_XrActionMap = 801,
SDNA_TYPE_MAX = 802,
};
dna_verify.c中提供了对DNA结构长度及成员在结构中偏移位置的校验。
在DNA_sdna_types.h中定义了存储DNA相关的几个结构,SDNA是用来保存所有DNA结构信息的结构。
在dna.c文件中定义了一个const unsigned char DNAstr[]数组常量,数组中存储了DNA的信息,DNAster包含预先构建的SDNA结构,定义此版本Blender使用的类型布局。也就是说DNAstr中存储的就是SDNA序列化后的数据。
extern const unsigned char DNAstr[];
const unsigned char DNAstr[] = {83, 68, 78, 65, 78, 65, 77, 69, ... 233, 0, };
extern const int DNAlen;
const int DNAlen = sizeof(DNAstr);
如果您希望结构不在DNA文件中:在其上方添加两行标记(#[回车键]#[回车键])
SDNA因此没有编码进入DNAstr中,DNA_sdna_types.h文件虽然也存放在DNA类型文件相同目录,但在定义时,加了标记。
# //注意这二行标记
#
typedef struct SDNA {
/** Full copy of 'encoded' data (when data_alloc is set, otherwise borrowed). */
const char *data;
/** Length of data. */
int data_len;
bool data_alloc;
/** Total number of struct members. */
int names_len, names_len_alloc;
/** Struct member names. */
const char **names;
/** Result of #DNA_elem_array_size (aligned with #names). */
short *names_array_len;
/** Size of a pointer in bytes. */
int pointer_size;
/** Type names. */
const char **types;
/** Number of basic types + struct types. */
int types_len;
/** Type lengths. */
short *types_size;
/** Information about structs and their members. */
SDNA_Struct **structs;
/** Number of struct types. */
int structs_len;
/** #GHash for faster lookups, requires WITH_DNA_GHASH to be used for now. */
struct GHash *structs_map;
/** Temporary memory currently only used for version patching DNA. */
struct MemArena *mem_arena;
/** Runtime versions of data stored in DNA, lazy initialized,
* only different when renaming is done. */
struct {
/** Aligned with #SDNA.names, same pointers when unchanged. */
const char **names;
/** Aligned with #SDNA.types, same pointers when unchanged. */
const char **types;
/** A version of #SDNA.structs_map that uses #SDNA.alias.types for its keys. */
struct GHash *structs_map;
} alias;
} SDNA;
结构DNA数据被添加到每个blender文件和每个可执行文件中,这是为了在.blend文件中检测结构中的新变量、更改的数组大小等。它还用于转换endian和指针大小(32-64位)。此外,Python还使用一个调用来检测运行时blender结构的内容。DNAstr数组中数据编码格式如下:
SDNA (4 字节) (幻数)
NAME (4 字节)
[nr] (4 字节) 名称总数 (int)
[名称字符串1]
[名称字符串2]
...
...
TYPE (4 字节)
[nr] 类型总数 (int)
[类型名字符串1]
[类型名字符串2]
...
...
TLEN (4 字节)下面类型长度项是与上面的类型名称项是一一对应的
[类型1长度] (short)
[类型2长度]
...
...
STRC (4 字节)
[nr] 结构总数(int)
[typenr][nr_of_elems] [typenr][namenr] [typenr][namenr] ...
DNA_genfile.h中定义了相关序列化数据到SDNA的转换函数。
总结一句话:Blender中DNA就是重要的可序列化结构,这些结构信息可包含于SDNA结构变量中,并序列化为数组变量或存储于文件中。Blender软件功能就是基于这些结构展开的。