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序列化注意事项可参考官方文档

DNA_genfile.h中定义了相关序列化数据到SDNA的转换函数。

总结一句话:Blender中DNA就是重要的可序列化结构,这些结构信息可包含于SDNA结构变量中,并序列化为数组变量或存储于文件中。Blender软件功能就是基于这些结构展开的。

 

posted @ 2022-09-30 23:22  平凡人  阅读(326)  评论(0编辑  收藏  举报