当前位置:网站首页>Blender 源码解析(1)
Blender 源码解析(1)
2022-07-29 17:23:00 【tianyapai】
由于Blender代码量很大,涉及的业务面比较广,本人从目前的了解中大概说一下对Blener的认识,如有错误,请指正,十分感谢。
Blender是一个的功能十分强大,并且跨平台,目前只是从window下对模型的处理过程中对其介绍,包括UI部分和数据部分。
(一)、Blender的UI部分,Blender的UI是基于GHOST类库开发的主窗口以及一些弹出的子窗口,对于主窗口,GHOST的作用主要是创建主窗口界面、监听系统IO操作、提供GPU上下文、消息循环过程等。而对于主窗口内的布局、工作区、各种面板、小部件等UI以及UI的消息传递都是自定义的,主窗口中的UI都是使用Opengl绘制的,UI类的基础类库的封装是C++开发并对Python开放UI类库的操作接口,而每个界面的UI组织是通过python处理的(脚本便于业务组织)。
(二)、Blender的数据部分,Blender的核心数据是DNA相关的数据结构,以及RNA基于DNA数据进行业务封装,本人感觉Blender对源码中的核心数据结构处理比较复杂,整个源码中会包含很对的预处理程序,像makesdna.exe、makesrna.exe等,其中makesdna.exe会将rna_*.h文件中的数据结构转换成内存结构,例如:DNA_listBase.h文件的处理,makesdna.exe会将该文件按照字符
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/** Generic - all structs which are put into linked lists begin with this. */
typedef struct Link {
struct Link *next, *prev;
} Link;
/** Simple subclass of Link. Use this when it is not worth defining a custom one. */
typedef struct LinkData {
struct LinkData *next, *prev;
void *data;
} LinkData;
/** Never change the size of this! dna_genfile.c detects pointer_size with it. */
typedef struct ListBase {
void *first, *last;
} ListBase;
/* 8 byte alignment! */
#ifdef __cplusplus
}
#endif串进行解析,并将解析的结果存储到如下结构中:
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). */
// 每一个名字的字母个数,例如“*next”个数为5
short *names_array_len;
/** Size of a pointer in bytes. 指针大小*/
int pointer_size;
/** Type names. 所有的类型,包括结构体、普通类型(int\float\string等)*/
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. */
// 临时内存当前仅用于版本修补DNA
struct MemArena *mem_arena;
/** Runtime versions of data stored in DNA, lazy initialized,
* only different when renaming is done. */
// DNA中存储的数据的运行时版本,延迟初始化,仅在重命名完成时不同
// 查找别名并存储在sdna->alias.types中于sdna->types位置上对应
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;比如将ListBase这个类型名存储到SDNA中的types中,同时这个types中还存储着int、float、string等基本类型,还有将结构体的成员变量名称存储在SDNA中的names中, SDNA_Struct **structs;中则存放当前Blender中所有的dna_*.h的结构体信息,SDNA_Struct代码如下:
// 结构体和它们的成员的信息
typedef struct SDNA_Struct {
/** This struct must not change, it's only a convenience view for raw data stored in SDNA. */
/** 这个结构不能改变, 只是方便查看 */
/** An index into SDNA->types. 结构体的类型(如link、baselist等) */
short type;
/** The amount of members in this struct.结构中的成员数量(如link、baselist等)成员变量的数量 */
short members_len;
/** "Flexible array member" that contains information about all members of this struct. */
// 结构体成员变量的信息(如link、baselist等的成员变量)
SDNA_StructMember members[];
} SDNA_Struct;结构体的SDNA_Struct的type则是SDNA中types的索引,SDNA_Struct的SDNA_StructMember members[];中存储的是结构体的成员变量列表,SDNA_StructMember的代码如下:
// 结构体成员信息
typedef struct SDNA_StructMember {
/** This struct must not change, it's only a convenience view for raw data stored in SDNA. */
/** 这个结构不能改变, 只是方便查看 */
/** An index into SDNA->types. 类型 */
short type;
/** An index into SDNA->names. 名称 */
short name;
} SDNA_StructMember;SDNA_StructMember的type是指向SDNA中types的索引,而SDNA_StructMember的name是指向SDNA中names的索引,Blender将很多的基础结构存储到SDNA的内存结构中,并将这个结构序列化成一个文件dna.c中,这个文件在工程目录下,是自动创建的。
而对于于RNA相关的处理是使用makesrna.exe处理的,例如:
// RNA中需要处理的文件( 文件名,对应的这个.c文件里的入口函数 )
static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_rna.c", NULL, RNA_def_rna}, // 文件名,对应的这个.c文件里的入口函数
{"rna_ID.c", NULL, RNA_def_ID}, // 定义ID
{"rna_texture.c", "rna_texture_api.c", RNA_def_texture}, // 定义纹理
{"rna_action.c", "rna_action_api.c", RNA_def_action}, // 定义动作
{"rna_animation.c", "rna_animation_api.c", RNA_def_animation}, // 定义动画
{"rna_animviz.c", NULL, RNA_def_animviz},
{"rna_armature.c", "rna_armature_api.c", RNA_def_armature}, // 定义骨骼
{"rna_attribute.c", NULL, RNA_def_attribute},
{"rna_asset.c", NULL, RNA_def_asset},
{"rna_boid.c", NULL, RNA_def_boid}, // 定义实体
{"rna_brush.c", NULL, RNA_def_brush}, // 定义画刷
{"rna_cachefile.c", NULL, RNA_def_cachefile},
{"rna_camera.c", "rna_camera_api.c", RNA_def_camera}, // 定义相机
{"rna_cloth.c", NULL, RNA_def_cloth}, // 定义布料
{"rna_collection.c", NULL, RNA_def_collections}, //
{"rna_color.c", NULL, RNA_def_color}, // 定义颜色
{"rna_constraint.c", NULL, RNA_def_constraint},
{"rna_context.c", NULL, RNA_def_context}, // 定义上下文
{"rna_curve.c", "rna_curve_api.c", RNA_def_curve}, // 定义曲线
{"rna_dynamicpaint.c", NULL, RNA_def_dynamic_paint}, // 定义绘制
{"rna_fcurve.c", "rna_fcurve_api.c", RNA_def_fcurve},
{"rna_gpencil.c", NULL, RNA_def_gpencil}, // 定义油笔
#ifdef WITH_HAIR_NODES
{"rna_hair.c", NULL, RNA_def_hair}, // 定义毛发
#endif
{"rna_image.c", "rna_image_api.c", RNA_def_image}, // 定义图像
{"rna_key.c", NULL, RNA_def_key},
{"rna_light.c", NULL, RNA_def_light}, // 定义灯
{"rna_lattice.c", "rna_lattice_api.c", RNA_def_lattice}, // 定义栅格
{"rna_layer.c", NULL, RNA_def_view_layer}, // 定义视图层
{"rna_linestyle.c", NULL, RNA_def_linestyle}, // 定义线样式
{"rna_main.c", "rna_main_api.c", RNA_def_main},
{"rna_fluid.c", NULL, RNA_def_fluid},
{"rna_material.c", "rna_material_api.c", RNA_def_material}, // 定义材质
{"rna_mesh.c", "rna_mesh_api.c", RNA_def_mesh}, // 定义网格
{"rna_meta.c", "rna_meta_api.c", RNA_def_meta},
{"rna_modifier.c", NULL, RNA_def_modifier}, // 定义修改器
{"rna_gpencil_modifier.c", NULL, RNA_def_greasepencil_modifier},
{"rna_shader_fx.c", NULL, RNA_def_shader_fx}, // 定义特效
{"rna_nla.c", NULL, RNA_def_nla},
{"rna_nodetree.c", NULL, RNA_def_nodetree}, // 定义节点树
{"rna_object.c", "rna_object_api.c", RNA_def_object}, // 定义对象
{"rna_object_force.c", NULL, RNA_def_object_force},
{"rna_depsgraph.c", NULL, RNA_def_depsgraph}, // 定义依赖图
{"rna_packedfile.c", NULL, RNA_def_packedfile}, // 定义打包文件
{"rna_palette.c", NULL, RNA_def_palette},
{"rna_particle.c", NULL, RNA_def_particle}, // 定义粒子
#ifdef WITH_POINT_CLOUD
{"rna_pointcloud.c", NULL, RNA_def_pointcloud}, // 定义点云
#endif
{"rna_pose.c", "rna_pose_api.c", RNA_def_pose}, // 定义骨骼姿态
{"rna_curveprofile.c", NULL, RNA_def_profile},
{"rna_lightprobe.c", NULL, RNA_def_lightprobe}, // 定义灯光探头
{"rna_render.c", NULL, RNA_def_render}, // 定义渲染
{"rna_rigidbody.c", NULL, RNA_def_rigidbody}, // 定义刚体
{"rna_scene.c", "rna_scene_api.c", RNA_def_scene}, // 定义场景
{"rna_screen.c", NULL, RNA_def_screen}, // 定义屏幕
{"rna_sculpt_paint.c", NULL, RNA_def_sculpt_paint}, // 定义雕刻绘制
{"rna_sequencer.c", "rna_sequencer_api.c", RNA_def_sequencer},
#ifdef WITH_SIMULATION_DATABLOCK
{"rna_simulation.c", NULL, RNA_def_simulation}, // 定义仿真
#endif
{"rna_space.c", "rna_space_api.c", RNA_def_space},
{"rna_speaker.c", NULL, RNA_def_speaker},
{"rna_test.c", NULL, RNA_def_test},
{"rna_text.c", "rna_text_api.c", RNA_def_text}, // 定义文本
{"rna_timeline.c", NULL, RNA_def_timeline_marker}, // 定义时间轴
{"rna_sound.c", "rna_sound_api.c", RNA_def_sound}, // 定义声音
{"rna_ui.c", "rna_ui_api.c", RNA_def_ui}, // 定义ui
{"rna_userdef.c", NULL, RNA_def_userdef},
{"rna_vfont.c", "rna_vfont_api.c", RNA_def_vfont}, // 定义字体
{"rna_volume.c", NULL, RNA_def_volume}, // 定义体积
{"rna_wm.c", "rna_wm_api.c", RNA_def_wm}, // 定义窗口管理
{"rna_wm_gizmo.c", "rna_wm_gizmo_api.c", RNA_def_wm_gizmo}, // 定义小部件
{"rna_workspace.c", "rna_workspace_api.c", RNA_def_workspace}, // 定义工作空间
{"rna_world.c", NULL, RNA_def_world}, // 定义世界
{"rna_movieclip.c", NULL, RNA_def_movieclip}, // 定义影视剪辑
{"rna_tracking.c", NULL, RNA_def_tracking},
{"rna_mask.c", NULL, RNA_def_mask},
{"rna_xr.c", NULL, RNA_def_xr}, // 定义混合现实
{NULL, NULL},
};makesrna.exe会将这些列表中的文件按照后面的函数在内存中定义对SDNA数据的处理,因为SDNA中定义的都是数据结构,没有对数据的处理过程(函数),同时是按照Blender的业务需要生成rna_*_gen.c文件,这个封装过程会将c++的基本数据类型进行封装,例如float在Blender中会被重新封装成FloatPropertyRNA结构体,这些结构体按照业务需要会重新定义,例如矩阵的定义:
FloatPropertyRNA rna_Mesh_transform_matrix = {
{(PropertyRNA *)&rna_Mesh_transform_shape_keys, NULL,
-1, "matrix", 3, 0, 1, 0, 0, "",
"Matrix",
0, "*",
PROP_FLOAT, PROP_MATRIX | PROP_UNIT_NONE, NULL, 2, {4, 4, 0}, 16,
NULL, 0, NULL, NULL, rna_property_override_diff_default, rna_property_override_store_default, rna_property_override_apply_default,
0, -1, NULL},
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, 1.0f, 3, 0.0f, rna_Mesh_transform_matrix_default
};感觉这个封装过程于使用脚本有很大的原因,因为python是一种任何类型都定义成对象的语言,是也可能是反射的需要。
边栏推荐
- 休息天的早晨感觉不到在休息
- [网络]WAN技术 PPP
- 浅析无人机发展趋势以及如何实现EasyDSS+无人机视频推流?
- 数学分析_证明_两个重要极限(同济版本)
- JupyterNotebook安装插件管理包过程中报错( AttributeError module ‘tornado.web‘ has no attribute ‘asynchronous‘ )
- Batch_Normalization 、Layer_Normalization 、Group_Normalization你分的清楚吗
- 字典树(Trie)
- flink cdc source支持redis 和es吗
- go的堆内存结构分析
- HMS Core Discovery第16期回顾|与虎墩一起,玩转AI新“声”态
猜你喜欢

解析正则表达式(一)

leetcode53 -- 最大数组和

"Hardcore" labelme shows the label in the picture

针不戳!腾讯云架构师出品的《MySQL性能优化和高可用架构实践》

Which is better, traditional render farm or cloud render farm?

Chicken and rabbit in the same cage

Out of breath!After 23 years of operation, the former "China's largest e-commerce website" has turned yellow...

“大龄”裸辞的“孤勇者”们

地球超2亿蛋白质结构全预测,AlphaFold引爆「蛋白质全宇宙」

Babbitt | Metaverse Daily Must Read: Seven consecutive quarters of losses, Meta Metaverse division Q2 loss of $ 2.8 billion, Zuckerberg said this situation may continue for years ...
随机推荐
js模拟白云慢慢出现js特效
mysql存储过程 实现全量同步数据并自动创建表
【高并发】我用多线程进一步优化了亿级流量电商业务下的海量数据校对系统,性能再次提升了200%!!(全程干货,建议收藏)
unity-shader-游戏渲染效果逆向分析
回帖免责声明-转载
周末分享-关于微信生态变化和5G
crontab执行定时任务报错的问题
管理层换血,魏建军求变,长城能告别“命悬一线”吗?
HER2-2-ME-BSANPs单抗特异性的2-甲氧基雌二醇白蛋白纳米粒的研究与制备
多线程顺序运行的 4 种方法,面试随便问!
【Mysql系列】01_查询+排序
提高编程效力的5大VS Code Extensions
unbuntu18.04-----bilibili网页端无法播放视频
GRE MGRE
清道夫受体-A靶向脂肪酸修饰白蛋白纳米粒/银耳多糖修饰白蛋白微球的制备
【码蹄集新手村600题】pow()函数详解
解决报错Unsupported field: HourOfDay
[网络]路由路由策略
lua-调试技巧
JupyterNotebook安装插件管理包过程中报错( AttributeError module ‘tornado.web‘ has no attribute ‘asynchronous‘ )