找回密码
 注册
查看: 8813|回复: 20

计算机图形学与Blender阅读/翻译计划

[复制链接]
发表于 2006-1-11 00:34:49 | 显示全部楼层 |阅读模式
元月中旬准备组织很多人阅读Blender的源代码,所有成果公开.这个Blender是现在公认最好的开源三维软件,工业级别.
代码阅读的前期准备已经完成,阅读完成也准备做些小的项目.如果看完下面这篇文章对阅读代码感兴趣,请pm我.thx
 楼主| 发表于 2006-1-11 00:35:54 | 显示全部楼层

blender 之构架(type_error译)

Blender Architecture

By Ton Roosendaal
赵正雄译


译者:本文介绍了blender的构架。细节方面并没有给出,请参照开发者文档。有什么问题可以问我。译者邮箱:[email protected]。欢迎大家复制并交流,复制务必标明出处,作者,译者。
-所见即所需,所做即所得-
Blender严格按照“面向数据”结构,就像一个资料库,但是加了一些的面向对象的观念。全部代码是用c写的。开发blender的时候,对于执行一些数据工作的所有的3D表示和所有的普通工具都试图一尘不变地定义结构。这种结构有意让开发者和用户使用blender快速和灵活。
这个图

表示了blender最基本的结构,”数据-显示-编辑”环是blender的核心,他们与GUI(图形使用者界面)分离并分别在不同级别上工作。
Data-select:一个用户选择了“数据”。这意味着用户指定了一个他想工作的3D资料库的一部分。它被组织成一个树形结构。Blender的数据系统的底层寄存在文件中,而文件直接映射出它们是怎么在内存中组织的。Blender数据可以包括多种“场景”,每一个场景分别包括了3D物体,材质,动画系统和描绘系统。
Visual-select:被指定的数据可以用Zbuffer描绘出的3D线框,按纽或者是概要图标来显示。Blender提供一个非常灵活的允许任何不重叠,不阻塞层次类型的窗口系统。
Edit-select:基于选择的显示数据,用户可以选择许多工具。编辑通常直接地在数据上进行,而不是在可见的数据显示上。这一点很有逻辑性,但是很多的软件这样做在交互性和直觉性上做得不够而失败。反过来,速度是一个很重要的因素;当用3d的方式显示,用户在看见书如命令后的很长一段时间内才能看到效果。这也是一个“反向矫正(翻译的不对,请向后看)”的问题:用户只意识到了视觉,而不是实际的数据结构。因为是3d软件,视觉和实际的数据会偏差很大,往往会带来反效果。
-用户界面设计的决定
用户需要有很多而且可行的方法去进行3D建模,许多程序基于把如动画,材质编辑,模块化而把工作流程分开导致终止开发。决定如下:
1.        基于无重叠无覆盖的用户界面的窗口系统。
2.        允许blender中的每一个子窗口可以与任何一个显示选择的数据的“编辑器”相连。
3.        执行唯一的热键和鼠标动作,不会因为子窗口的不同而不同。
4.        因为是一个室内软件,使用速度因素大于学习难度因素。
用户界面的实现最初是用库去尝试,但是因为速度问题彻底失败。创建整个新的窗口管理器,完全基于IrisGL(openGL的前身)使得blender到现在还是很小巧。
数据结构
设计blender的大部分时间花在定义一个正确的数据组织的方式和数据之间有怎样的关系。牢记“实现根据设计”的概念,所有的设计决定都应该限制功能去使用。
基于我们的工程从内部需要3D的方式,决定在高的抽象级别设计数据结构,有以下几点需求:
1.        允许多人共同工作
2.        允许在一个工程内创建许多动画工程。
3.        允许数据被高效率地重用。
4.        允许模版。
这导致了设计不是标准的“数据资料库”,不像传统的“场景作图”(当时的基于理解/显示),但是基于创建通用的3d”数据世界”,在这你可以根据需要构建不同的场景绘画(显示,图形,动画)。这种数据结构的设计对初学者来说很不容易。
在blender中数据块是用户的建筑块:他们可以被拷贝,修改,根据需求连接到另一个上。
创建一个连接实际上上是建立了一种关系。这是一个块的用处。这可以制造一个快的实例,或者得到一个特殊的用处。
比方说一个“物体(object的数据结构在DNA_object_types.h文件中)”块类型使得一个“网状(mesh的数据结构在DNA_mesh_types.h中)”块在3d场景中显示。“物体”表示决定了精确定位,旋转,和网状的大小。而网状只存储了节点的定位和朝向。可以有一个或者多个的“物体”连接同一个“网状”。其他的一些块类型比如材质可以连接到网状结构上去得到块属性。
每一个这样的快在blender中以一个ID结构(在DNA_ID.h中)开始,ID结构包括了这个块的唯一的名字,在某些情况下也包括了块所属的库(Library),ID结构使得blender的数据可以被唯一的表示和操作,而不需要知道具体的类型或者其他信息。
这些ID也使得blender以一种文件结构去在内部组织文件;它就像一些文件的目录。
当组合blender文件或者以“库”方式使用他们的时候这种组织变得很重要。
Blender中所有的数据储存在一个主结构(main tree 的数据结构在BKE_main.h中)中,它只不过是一块目录(a block of lists),数据都存储在这里,与用户是怎么样把他们连接起来的无关。图


你可以看出一个“场景”是怎样由一些在主结构的数据构建起来的。(译者主:在主结构中没有组织的方式!!)。
在主目录中存储的数据要进一步地由场景块(scene block在DNA_scene_types.h中)所显示出来。场景块有一个基结构(base structs在DNA_scene_types.h中)的列表,这可以使一个场景连接许多的物体而不把它们从主结构中移出。(基结构同样有一些属性,比如图层和选择,这样允许许多场景都能通过这样不同的属性来使用一个物体)
当使用blender的时候,库块(library block在DNA_ID.h中)经常不会自己释放,而是断开了连接。他们继续在主结构中。只有当用户计数为0时,它才会不被写入文件中。
图中黄色是表示两个主全局变量,当前场景(也表示活动场景)和活动物体。
数据块结构
所有在主结构中的块叫做库块(library blocks)(译者:物体,网状都叫做库块),有时候也叫做库数据(libdata)。库块以一个ID结构开始:
[code:1]typedef struct ID {
        void *next, *prev;    /* for inserting in lists */
        struct ID *newid;      /* temporal data for finding new links when copying */
        struct Library *lib;  /* pointer to the optional Library */
        char name[24];    /* unique name, starting with 2 bytes identifier */
        short us;   /* amount of users of the block */
        short flag;  /* bitwise flags to indicate special types */
} ID;[/code:1]
让我们进一步地看一个库块

:网状结构。当然这样的块包括许多其他的块,以数组或者是链表存储。这里我们存储了节点(Mvert),朝向(faces),UV材质坐标(翻译不准)等在图中以蓝色表示的。这些块叫做直接数据(direct data)。这些数据经常与网状结构一同被写入或是一同从文件中读出。
除了这些永恒的数据,还有一些临时数据可以连接到网状结构上,比如显示列(display list)。这些数据即时生成,而不是写入文件,从文件读取数据的时候被设为null。因为所有的库数据和直接数据都存储在文件中,所以应该紧凑地设计它们,而临时数据留在外部。

现在我们得到了一条很重要的设计原则:blender的块之间指针的使用被限定为对库数据的指针。这意味着指向物体或者网状的指针可以在任何地方(比如在一个节点处),但是指向指定的节点的指针不能在任何地方存储。
这条原则使得有一个一致,可预知的结构,这种结构可以被blender代码的任何部分所使用(尤其是数据库管理和文件)。如果你想把一些东西变为库数据或者你想把它在blender的任何地方重用,它也可以使你做出决定。(译者:意思是:可以在任何地方使用库数据,对复制等操作很方便)

当一个文件被存储的时候,直接数据与库数据在一起。存储的数据读取的时候的指针需要被还原。这里的指针规则帮助我们快速地还原指针所指向的直接数据,因为这里的指针只存储了一些单独的有关内容。只有一些指向直接数据的指针被存储在一个全局列表中,对lib_link_***的函数调用中全部还原。
外部库数据
设计的一则需求是从别的文件中导入数据,或者以一类模版去动态连接它。在当时评价其他3d程序的时候我注意到他们使用操作系统的文件系统,以内部的一个目录树和每一个数据块对应的一个单独的文件去创建工程目录。除了复杂,笨拙,我怀疑速度也很慢(译者:作者也太嚣张了吧!)。

然而,blender用这种方法至少有一点好处。Blender数据名字的使用与文件名可以紧密结合。

当动态地使用别的文件的数据,很明显地只有库数据块可以被连接。Blender自动地读取与它有关的直接数据。可是为了使读取外部文件更有用,它同样要扩展它的所连接的树。比如说,读取一个被连接的物体,同样会自动读取它有关的网状结构,材料和材质。被扩展的数据叫做“间接数据”。在接口中你可以以红色的库图标去识别它。当存入到一个文件时,这样的扩展(间接数据)不被完全写入,这需要外部文件的编辑者改变对物体的连接,就像增加一个Ipo或者其他的材料。

一个种种特性的典型使用就是从别的文件动态链接一个场景。不管有什么在场景内都将被读取。
当存取链接库数据,只有它的ID组件被写入。这些ID包括一个指向被使用的“库”(=外部文件)。有唯一名字的ID被正确存储。
文件存取和读取
文件存取大体上是过一遍主结构,然后以raw binary dump格式存取用户的所有的块到磁盘上,每一个被存储的块有一个头(struct Bhead)它存储了其余的一些信息,比如内存中块的原始地址。

文件读取首先读取全部文件到内存中。Blender读取代码然后过一遍所有的Bhead,再处理库数据和间接数据,创建出一整份拷贝。最后所有的文件都可以从内存中删除。

写入动态链接的库数据:
因为blender的主结构只是另一种可列表结构,它使用多个主结构为了可以高效地存取和写动态链接数据。这个可以用split_main()这个函数的调用完成,创建每个文件所属的分离的数据的主结构。

对于存档,当前的主结构可以被正确地处理;对于其他的主结构,它只存入了所有的ID(就像ID_ID类型),用一个分离者表示它从哪一个文件而来

然后,它调用call_main()函数去合并成一个主结构。

读取动态链接库数据:
这可能有一点复杂,带有递归。
1.        当从文件读取数据,blender遇到一个库结构,它创建一个新的主结构去存储后来的ID_ID。这些ID被标记LIB_READ.
2.        然后检查所有新的主结构的被标记LIB_READ的块。
3.        如果LIB_READ块被找到:
3.1 它检查包含这个数据的文件是否已经被读取,如果没有则加载内存中的整个文件再把他们存储到主结构下。
3.2 按正常的步骤读取块,链接所有间接数据。新的数据块被链接上,旧的则被移出。
3.3 根据块的类型,调用expand_doit()函数,这个函数强制读取像3.2所说的块,或者检测已经正确读取得数据。注意:当这样的扩展数据再次从别的文件被读取,它只读取ID这一部分,把它连接到正确的主结构上并标记为LIB_READ。
4.只要LIB_READ被找到,回到第2步。
5.最后合并主结构并恢复所有正确的库数据指针。
正如你所看到的,这个系统需要很多指针魔法(不准确的翻译),指针必须映射到新的指针上面去,再到新的指针上面去,直到正确的指针指向的数据被分配。

结构DNA(SDNA)
在选择二进制存储文件,blender的结构会一直在变或者扩展,我想到设计一个系统可以照顾到低级别的版本的改变。这就是blender DNA。
基本上,SDNA是一种blender包含文件(include file)的精确二进制预处理版本,包括可以被存储进文件的数据。SDNA系统可以得到内容的结构信息:大小,元素类型和名称。

在每一个编译的blender有一个SDNA在内和一个保存的.blender文件内,都有SNDA被加入。而且,对于文件中的每一个Bhead,它保存着序列号表示结构类型。

这一切允许结构中的改动被检测和解决。举一个从int到short,char到float,数组或多或少的得到一些元素的例子。新的变量最好归0,移除变量被简单地忽略。当做一个到endian系统的输出,最好有一些正确的类型转换。用SDNA使得即使输出到64位的系统照样成功。

此外,它还允许后退和前进兼容。1997年的二进制在现在依旧运行,反过来也是。

主要的限制是当真实版本需要改变时。比如加入一些新的变量需要给定值初始化,更糟的是,一些变量会改变值。
源代码层次
现在的代码层次仍然是当时还是一个公司时的制作时的一个快照。在图表中你可以找到目录名称

.
Blender的用户接口框架
在源代码的source/blender/src/目录下你可以找到与用户接口(UI)和blender的工具有关的文件。结构虽然明显,但是在目录结构上可以反映地更好。
回复

使用道具 举报

发表于 2006-1-11 10:47:25 | 显示全部楼层
我只用blender,源代码看不动
回复

使用道具 举报

发表于 2006-1-11 10:49:10 | 显示全部楼层
哪里有源代码下载
回复

使用道具 举报

发表于 2006-1-11 10:53:40 | 显示全部楼层
用不好blender,觉得自己在艺术上面没有前途。。
看不动代码,觉得自己在技术上也没前途了。
回复

使用道具 举报

发表于 2006-1-11 13:59:28 | 显示全部楼层
改了楼主贴子的题目,楼主不介意吧
回复

使用道具 举报

 楼主| 发表于 2006-1-11 18:20:20 | 显示全部楼层
[quote:5a712a3067="yuyulvxian"]哪里有源代码下载[/quote]
cvs啊.这样能够看到最新的代码.
你也可以在这里下载 http://www.blender.org/cms/Source_Code.12.0.html
回复

使用道具 举报

 楼主| 发表于 2006-1-11 18:22:04 | 显示全部楼层
[quote:9dc7052113="kakuyou"]改了楼主贴子的题目,楼主不介意吧 [/quote]
感谢版主厚爱
回复

使用道具 举报

 楼主| 发表于 2006-1-11 18:29:52 | 显示全部楼层
翻译是我代别人帖出来的.下面也有我自己翻译的
Blender中国对Blender这个软件已经比较有深入了解了.不管是制作3维图形还是源码方面.更多的可以到www.blendercn.org查看.
还有我们最近准备将半年来翻译的手册公开,喜欢blender和3维制作但又不喜欢看英文的朋友可以到我们wiki去看看.
回复

使用道具 举报

 楼主| 发表于 2006-1-11 18:32:29 | 显示全部楼层

Blender源程序文件夹结构初探

Blender源码文件夹的三个主要部分就是

/extren /intern /source

/extern 四个外部库 包括ogl字体,ode,solid,quickhull.

/intern 较多 ../moto Motion toolkit ../csg construction solid geometric

等等 共17个库.

/source主要就是../blender ../kernel ../gameegine 这三个重要的文件夹

/extren
../qhull 快速凸包算法库,一个开放源代码的工具,专门用于根据点云生成包含该点云的凸多边形外壳。不过使用有些复杂。如果是非凸的可以先分割成为多个。
www.qhull.org

../SOLID 一个碰撞检测库,需要qhull库支持.有本游戏编程的书使用它来讲解
http://solid.sourceforge.net/

../ode Open Dynamics Engine 模拟刚体动力学的库
http://www.ode.org/

../bFTGL 可以在opengl程序中中读取turetype字体
http://gltt.sourceforge.net/index.html

../bullet 新的刚体可能会代替以前所有用的库比如ode
rigid body&Bullet Collision Detection and Rigid Body Dynamics Library. MIT license, free for commercial use, mainly for games and animation. Discrete (GJK) and Continuous Collision Detection (Time of Impact), Constraint solvers, modular C++ framework.
http://www.continuousphysics.com/Bullet/

/intern

../moto
Motion toolkit

../csg
construction solid geometric

../memutil

../action

../bmfont

../boolop boolen

../bsp

../container

../decimation

../elbeem
Fuild sim lib
http://elbeem.sourceforge.net/

../ghost

../guardedalloc

../iksolver

../img

../keymaker

../memutil

../opennl

../SoundSystem

../string
回复

使用道具 举报

 楼主| 发表于 2006-1-12 12:10:37 | 显示全部楼层

Blender 窗口管理器

Blender 窗口管理器(typeErr翻译)

译者:本文介绍了blender的构架。细节方面并没有给出,请参照开发者文档。有什么问题可以问我。译者邮箱:[email protected]。欢迎大家复制并交流,复制务必标明出处,作者,译者。
屏幕/区域/窗口(screens/areas/windows)
Blender有它自己的多功能窗口管理器。Blender正是基于这样系统的所需求而开发的。窗口管理器的最高级别是“屏幕”,场景正是操作系统环境里面的“窗口”。场景再被分为“区域”,区域是子窗口。(我大部分地选择了场景和区域来避免使用容易混淆的“窗口”)。
在很早的blender1.0中,对区域的绘制留给了Irix窗口管理器提供的“子窗口”特性。过了一段时间我决定放弃它,把部分的原因是速度太慢,速度在一个需要开10-20个窗口的程序中是一个重要的考虑的因素,不能过多地增加系统的负担,比如刷新一次屏幕要用上几秒钟(在有些软件中)。
我发现了一种方法:用openGL特性完全最小化子窗口。同时使用glScissor()和glViewPort()方法可以高效地完成。对应得代码在src/myWindow.c文件中。注意你仍然可以在以前的子窗口中找到wrappers,引进“bwindow”层。
所以在这里,把“区域”特性和“BWindow”的混淆已经介绍了。。,为了使整个系统更有吸引力,对Gltu的端口被加到系统之上,然后才是Ghost。从“BWindow”到GhostWindow的封装在“ghostwinlay.c”内。所以现在我们感兴趣的是这一系列的封装:
System Window(操作系统指定)<->GHOST window(GhostLib)<->Window(ghostwinlay。c)<->bWindow(mywindow。c)<->ScrArea(editscreen。c)
如何渲染系统的窗口至今还是一个噩梦,重建工作从未完成过。
比较明显的封装是像这样的一个东西:
System window<->Ghost window<->Screen

区域和空间(Areas and Spaces)
在blender内“活动窗口”就是一个活动区域,这一在屏幕内的区域是输入和输出的地方。Editscreen.c管理这些东西,定义了哪些区域是当前输入窗口,哪些区域应该被重绘,还有在哪些情况下应该完成全部或部分的交换缓冲。
由于这些原因,区域必须有它自己的事件队列,和(方程指针)返回去控制和描绘队列。屏幕系统去读取主队列,再分配到区域,执行队列,对于恰当的交换缓冲仍可以执行重绘。
这所有一切很平衡,缓冲队列重载可以防止执行100个程序用100个重绘命令。
Blender的“空间”(spaces)是另外一个新的定义以区别“窗口”(window)。决定是:完全从屏幕/区域系统中分离在区域内运行的应用程序。这一点允许了每一个区域明显地运行任何一个程序,这一点在blender中很重要,(可以改变window的类型),一个空间被简单地定义成一下几项:
-一个spacexxx结构(在DNA_xxx_type.h内)持有永久变量,为了拷贝和存储,这些数据与保存进文件有关。
-分配,撤销,拷贝Spacexxx的方程。
-一个winhandle()调用去处理区域事件
-一个windraw()调用去(重)绘
-一个winchange()调用去重新初始化窗口大小或者是其他改动。
每一个区域对于每一个space 类型存储一个Spacexxx结构(在列表内),当应用程序在区域内改动的时候就会进行存储。据一个例子:当你调用某一个SpaceFile,它可以安全地返回到原先的SpaceView3d 类型而不去做任何改动。
另外重要的一点是任何一个空间(space)都是在本地内部运行,它不会(也不应该)意识到其他编辑器的打开与否,也不会从它上面读取文件,也不会进入他们去改变他们的数据。空间(space)被当作一个独立的应用程序,在它的结构内部去存储数据,只在blender所提供的数据库工作,或者是屏幕指定的活动内容(就象活动的场景,物体)。
(读blender architecture获得更多这方面的知识)
现在仍然没有一个好的协定和文档去写出如何加一个新的space 类型,但是通过这种方式在理论上它可以与任意一个应用程序挂钩。使用调用结构可以使应用程序插入到space内。。。设想一个例子:加一个internet浏览器或者是文字编辑器或者是中端会发生什么情况。你自己的桌面环境!!
Blender远没有完美,所有你可以看到有许多的古老的对系统得滥用,尤其是全局变量。。编辑模式和面选择就是这样。在按键面板中的一些工具的执行是另外一个例外,工具本应在3d窗口下工作,但是另外一些的space类型进入了这些工具。消除这些问题是2.3版本工程的一部分,试图保持使用的内容尽量易懂。
丑陋的全局结构
任何一个好的结构的程序是去限制使用全局变量而得到绝对最小化。一个惩罚就是重新编译,还会有一些意外发生。
现在因为是只有使用一个屏幕或者一次只用一个屏幕,blender的屏幕管理在G结构中有许多“有用的”全局变量。
纵观代码你可以看见“G.vd”和”G.sipo”等的使用。有一些指向*活动*Space结构的指针,他们由屏幕管理器在鼠标移动和区域处理队列或重绘的时候设置。用这一些变量的任何代码100%的属于它自己的space类型。没有一个G.vd(View3D)在按键,文件选取,脚本space等的地方被允许进入,因为没有被定义(或者可以甚至为0)。这是一个在blender的代码中普遍的错误而且经常导致bug和crash的发生。Python窗口模块也使用了它,它应该被移出掉。
如何继续
在以下的一些地方还需要有工作要做:
-移除荒谬的5层窗口封装的概念
-对space设计一个新的方法去处理队列(用动态事件处理器)
-设计一个新的方法让Python能连接到每一个space上面(可以变为事件处理器)
(译者:有些可能在新版本中已经得到解决)。
回复

使用道具 举报

 楼主| 发表于 2006-1-12 12:11:41 | 显示全部楼层
译者:本文介绍了blender的构架。细节方面并没有给出,请参照开发者文档。有什么问题可以问我。译者邮箱:[email protected]。欢迎大家复制并交流,复制务必标明出处,作者,译者。

任何一个想给blender内核加入一些新功能的时候,都会面对这一个很奇怪的系统--在代码中我叫它SNDA或者是struct-dna。这个核心的内容早就应该写出文档了,但现在还不晚。

这个系统是为了支持blender的文件格式和内部库/数据库的系统。有了它blender可以进行运行时检查结构数据的内容。这样可以增加很多好的特性:
-你可以增加或者移除结构的变量,甚至增加或者移除整个结构体而不需要考虑blender的版本兼容性。
-你可以把它使用在blender的Python或是smart Button中,运行时检查提供了哪一些的变量和结构体。

Blender中所有的可以存储到文件中的结构体都被描述为SDNA。这是一长串的包含结构体,变量名,变量类型的代码。“sdna”管理这些,它有一个内建的.h头文件的列表,读取他们然后转换成SDNA文件。

当一个文件被存储了,写结构体的函数察看结构体代码,然后把它写入一个块(struct BHead,writefile.c)。在这个文件的末尾,完整描述SDNA的文件添加到.blender文件中,使文件前后版本兼容。

每一份编译的blender都也有一份SDNA描述。当一个文件被读取,它的SDNA结构与可执行的blender的SDNA进行比较。不同的结构被标记,然后读取得时候转换。
允许的转换(变化)有:

-如果名字是一样的但是类型不同,它就要试图转换。只有可能的转换才会发生(比如short->int,int->float),不然就置0。
-新的变量会被初始化为0。
-确定数组的大小(比如[3][3],[4][4])。
-纠正指针大小(比如32bit,64bit)。
-char到float:被255分割。
-结构体中的结构体的改变正常工作。

早些时候,我没有在系统中包含自动的“padding”…,在结构体中包含一些空位,这是面对数据对齐是编译器的系统依赖习惯。比如说:在SGI中一个int一直是以一个可以被4整除的地址开始。当你设计这样一个结构体的时候:
[code:1]struct XYZ {
char x_flag;
float x;
char y_flag;
float y;
char z_flag;
float z;
}[/code:1]
实际的结构体长度应该是6*4=24byte。更糟的是:向一个这样的结构体:
[code:1]struct ABC {
char a;
}[/code:1]
在ALPHA机器上是8位,在32位机器上是4位。

所以为了有正确的SDNA结构和所有支持的操作系统,你应该设计一个非填空的结构体,下面是一些规则:
-设计SDNA结构最主要的目的是在64位机器上以8位对齐的在32位系统上自动的会变成4位对齐。
-有意义的指针是8位长,在32位机器也是一样。
-结构的大小应该一直是8位的倍数。
-在结构体内的结构体应该从一个可以被8整除的地址开始。
-指针从可以被8整除的地址考试,除非它指向的变量也是一个指针。
-int/float从可以被4整除的地址开始。
-shorts从可以被2整除的地址开始。

如果你不能够较好地管理它,那么在结构体中加入“pad”变量。你会在blender中看到更多这样的用法,它表示了在以后可以使用的空的空间。但是在blender中不要用pad变量干什么事!!![/code]
回复

使用道具 举报

 楼主| 发表于 2006-1-12 12:14:54 | 显示全部楼层
kidux 翻译

译者:本文介绍了blender的构架。细节方面并没有给出,请参照开发者文档。有什么问题可以问我。译者邮箱:[email protected]。欢迎大家复制并交流,复制务必标明出处,作者,译者。
Blender file reading:
http://www.blender3d.org/cms/Blender_file_reading.498.0.html
Currently four different levels of routines for .blend file reading exist;
.blender文件的阅读有四个不同级别的例程;

/* interface level */
/*接口级别*/
1) BIF_init() -> calls 3
2) BIF_read_file() -> calls 11, optional 4
3) BIF_read_homefile() -> calls 11 or 12, and then 4
4) init_userdef_file()

/* kernel level */
/*内核级别*/
11) BKE_read_file() -> calls 21, and then 14
12) BKE_read_file_from_memory() -> calls 22, and then 14
13) BKE_read_file_from_memfile() -> calls 23, and then 14
14) setup_app_data()

/* loader module level */
/*加载模块级别*/
21) BLO_read_from_file() -> calls 24
22) BLO_read_from_memory() -> calls 24
23) BLO_read_from_memfile() -> calls 24

/* loader module, internal */
/*加载模块,内部*/
24) blo_read_file_internal()


Note:
- BIF_read_homefile() has additional UI initialize calls, like windows fullscreen and executing commandline options
-BIF_read_homefile()是额外的ui初始化调用,比如全屏的窗口和执行命令行选项

- Reading from memory (12) only happens for the compiled-in .B.blend
-从memory (12)读取仅仅发生在编译进的.B.blend

- The "memfile" here is a name I gave to the undo "file" structure. Which is constructed out of memory chunks with basic compression features.
-"memfile"是我为undo "file" 结构取的名。可以在内存块中构造出基本的压缩特性。

- the kernel function setup_app_data() sets globals like "current screen" and "current scene".
- 内核函数 setup_app_data() 设置全局的如"current screen" 和 "current scene"

So far, so good. The levels as mentioned here clearly distinguish UI from kernel, and should enable for example game loading (runtime) or background (no UI) loading. In the past years however, 'bad level' dependencies were added, and especially the patches for 'file versions' were added in too many places. The latter is evidently a result of the problem that the "UserDef" struct cannot be initialized/patched if there's not a need for a UI.
这里提到的这个级别直接的从内核中识别ui,而且可以允许加载game(runtime)运行,或者后端(无ui)的加载。
过去的日子里,“坏级别”依赖关系被添加,特别是'文件版本'的补丁到处都有。这样的直接后果是
如果没有ui的需要就不可以为"UserDef"结构初始化/打补丁

Here's how the flow goes in four different cases:
这里:在四个不同的例子中的流程

----- Starting up Blender, in foreground with UI --------------------
-----在前端的ui中打开blender,-----------

- creator/creator.c, main() -> calls 1
- If the commandline contains a filename, it calls 11

----- Starting up Blender, in background without UI --------------------
-----在后端不需要ui 打开blender----------------------

- creator/creator.c, main() -> calls 11 if the commandline has a filename

Note: no Userdef is read, nor initialized. Please note that this was already an existing problem for using Yafray, not setting proper file paths in background mode. The Yafray paths don't belong in the User menu.
注意:没有Userdef被读取,或者初始化。请注意这也是yafray中存在的问题,不能在后端模式中设置正确的文件路径。yafray路径没有在用户菜单中。

----- Starting up Blender as a runtime executable --------------------
------可执行运行环境中启动blender-----------------------

This only has calls to 22

----- Loading a file from within the UI (with F1, CTRL+O, using pulldowns) -----
------在ui中装载一个文件(用f1键,CTRL+O,用 pulldowns)

Only calls allowed to 2. It detects if a UserDef has been read too, and in that case the init_userdef_file() will be executed.
只有调用才允许到2。它也可以检测出UserDef是否被读取,在这个用例中init_userdef_file()会被执行

Hope this is understandable Smile
希望能被读懂。
回复

使用道具 举报

 楼主| 发表于 2006-1-31 19:41:41 | 显示全部楼层
makesdna.c 的相关原理分析

Makesdna的作用就是,生成一个很长的字符串的.c文件,这个c文件是生成blender文件格式的模板,是一个二进制文件非常的快。连续扫描所有的结构体,找到所有成员的名字和类型,然后计算需要多少存储空间来存放这个结构体,和找到一个模块所需要的偏移量。在程序当中有一个很实用的debug工具,debugSNDA,分为4个等级,由底到高,在终端输出调试信息。

char *includefiles[] 存储所有头文件为字符串,备后来的程序使用。



文件中的所有函数如下,基本功能就是文件和字符串的操作:最终生成的dna.c文件就是一张表文件,通过它blender可以迅速地在blender文件当中找到需要的模块进行加载。

int add_type(char *str, int len);



/**

* Add variable <str> to 添加 str 变量

*/

int add_name(char *str);



/**

* Search whether this structure type was already found, and if not,

* add it.寻找结构体的类型,如果没有便添加

*/

short *add_struct(int namecode);



/**

* Remove comments from this buffer. Assumes that the buffer refers to

* ascii-code text.屏蔽所有注释,确保缓存里的文件以ascii码保存的文本

*/

int preprocess_include(char *maindata, int len);



/**

* Scan this file for serializable types. 按顺序扫描所有类型

*/

int convert_include(char *filename);



/**

* Determine how many bytes are needed for an array.决定某一数组的字节量

*/

int arraysize(char *astr, int len);



/**

* Determine how many bytes are needed for each struct.计算每一结构体所需字节数

*/

int calculate_structlens(void);



/**

* Construct the DNA.c file 生成dna.c文件

*/

void dna_write(FILE *file, void *pntr, int size);



/**

* Report all structures found so far, and print their lenghts.报告所有找到的结构体的,然后打印他们的长度

*/

void printStructLenghts(void);



/**

*打印结构体长度被上一函数调用

*/

int make_structDNA(FILE *file);



/**

*生成dna.c文件,被main函数调用

*/

int main(int argc, char ** argv);



main函数如下:作用就是调用make_structDNA函数,读写文件,并在终端输出错误报告。

[code:1]

int main(int argc, char ** argv)

{

     FILE *file;

     int return_status = 0;



     if (argc != 2) {

         printf("Usage: %s outfile.c\n", argv[0]);

         return_status = 1;

     } else {

         file = fopen(argv[1], "w");

         if (!file) {

              printf ("Unable to open file: %s\n", argv[1]);

              return_status = 1;

         } else {

              fprintf (file, "unsigned char DNAstr[]= {\n");

              if (make_structDNA(file)) {

                   // error

                   fclose(file);

                   make_bad_file(argv[1]);

                   return_status = 1;

              } else {

                   fprintf(file, "};\n");

                   fprintf(file, "int DNAlen= sizeof(DNAstr);\n");

     

                   fclose(file);

              }

         }

     }



         

     return(return_status);

}[/code:1]
回复

使用道具 举报

 楼主| 发表于 2006-3-12 23:00:55 | 显示全部楼层
http://bbs.blendercn.org/viewtopic.php?t=205
[quote:44c84ee7c9="mokt2001"]乱翻译了几个词,错的话帮指正

  • GEN: General stuff (c++)  
  • SM: SuMo (Solid Uses Moto), the physics engine (c++)  game物理引擎
  • KX: Ketsji, the game engine (c++)game物理引擎
  • MT: MaTh, mathematics module (c++)  数学模块
  • RE: Render, static rendering (c)  渲染
  • PR: Portable Runtime, a Netscape library (external code, c)  一个Netscape库
  • PRB: PR-Blender, our own extensions to PR (c)  
  • SND: SouND, our (currently OpenAL) wrapper and extensions (c)  声音模块,包装并扩展了OpenAL
  • RAS: RASterizer, our low level 3D polygon abstraction layer (c++)  Blender自己的多边形低阶抽象层
  • NET: NETworking. Currently our Terraplay CNI wrapper.  网络模块
  • BLI: Blender low-level LIbrary.  Blender低阶库
  • BKE: Blender KErnel.  Blender核心
  • BIF: Blender Interface Framework.  Blender界面框架
  • BSE: Blender Space Editor.  
  • BDR: Blender DRawing.  
  • DNA: struct DNA, the types definitions of serializable data, and the construction of DNA.o, which encodes this data. 特定Blender版本的数据特征-DNA。
  • AVI: conversion of AVI format files.  AVI格式转换
  • IMB: IMage Buffer, all kind of operations on images. 图像缓冲
    [/list:u][/quote]
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2025-2-7 04:16 , Processed in 0.056656 second(s), 15 queries .

© 2001-2025 Discuz! Team. Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表