wild magic3的Scene graph结构和Geometric State更新体系(转载)

WildMagic4 Source 著名的《3D+Game+Engine+design》第二版所附带的引擎,wildMagic第四版。这个版本是基于可编程管线的,与之前版本有很大不同,是学习3D引擎设计的极好材料。 立即下载

刚看了《3D Game Engine Architecture》第3章“Scene graphs and renderers"的前两节,很精彩,暂且不拿wild magic 3和其他引擎相比较,只是作为读书笔记,记录一下书中的核心内容。

我觉得第3章是此书的核心部分,全部内容就是scene graph的更新和渲染,其中第一节描述了wild magic3中的scene graph架构,第二节重点讲解了scene grapha的Geometirc State 更新体系(updateGS)。

1)wild magic3 scene graphs

包括几个核心类: Spatial, Node, Geometry
其中Spatial是Node和Geometry的父类,Spatial包含了local transform和world transform,以及world bound(世界空间的包围体)。并且Spatial拥有上一层Spatial的指针(parent spatial)。

Node包含一组子节点(注意,子节点使用Spatial指针,而不是Node指针,因为子节点可能是Node也可能是Geometry,或者他们的子类),通过Spatial和Node组成了scene 的树形结构。

而Geometry是有mesh的几何实体,包括索引数组,模型空间的顶点数组,模型空间的法线数组,以及模型空间的包围体,还有模型级的scale值。
同时他也是继承自Spatial的,所以也可以变换,也被放置到scene grapha中,但是在wild magic3中,Geometry只能作为叶子节点(没有子节点了,只有Node有子节点)

从这儿看,Node的作用就是一个group, Node不是实体,实体只能是叶子节点,一般是Node的子节点中有Geometry。
另外,对于共享模型数据,wild magic3是在low level实现的,即Geometry的子类可以共享模型数据。

2)wild magic3中的transform
Transformation 这个类,包含一个3X3 rotation matrix, 一个 vector3f translate,和一个vector3f表达的non-uniform scale。他为了减少计算量,没有像irrlicht那样直接用一个4X4 matrix。Transformation类中的Product(const Transformation& rkA, const Transformation& rkB)方法相当于矩阵相乘,用于在scene grapha更新时从上到下更新节点的世界变换。

3)wild magic3的geometric updates

为了方便看,把相关代码列到一起

class Spatial: public Object
{
    public:
        Transformation Local, World;
        bool WorldIsCurrent;

        BoundingVolumePtr WorldBound;
        bool WorldBoundIsCurrent;

        void UpdateGS(double dAppTime=-Mathd::MAX_REAL, bool bInitiator=true)
        {
            UpdateWorldData(dAppTime);
            UpdateWorldBound();
            if(bInitiator)
            {
                PropagateBoundToRoot();
            }
        }

        void UpdateBS()
        {
            UpdateWorldBound();
            PropagateBoundToRoot();
        }

    protected:
        virtual void UpdateWorldData(double dAppTime)
        {
            UpdateControllers(dAppTime);//control可能直接修改local或world transform
            if(!WorldIsCurrent)
            {
                if(m_pkParent)
                    World.Product(m_pkParent->World, Local);
                else
                    World = Local;
            }
        }

        virtual void UpdateWorldBound() = 0;

        void PropagateBoundToRoot()
        {
            if(m_pkParent)
            {
                m_pkParent->UpdateWorldBound();
                m_pkParent->PropagateBoundToRoot();
            }
        }
};

class Geometry: public Spatial
{
    public:
        //省略其他数据,如indices, vertices, normals..
        BoundingVolumePtr ModelBound;

        void UpdateMS();
    protected:
        virtual void UpdateModelBound();
        virtual void UpdateModelNormals();
        virtual void UpdateWorldBound()
        {
            ModelBound->TransformBy(World, WorldBound);
        }
};

class Node: public Spatial
{
    protected:
        virtual void UpdateWorldData(double dAppTime)
        {
            Spatial::UpdateWorldData(dAppTimie);
            for(int i=0; i
            {
                Spatial* pkChild = m_kChild[i];
                if(pkChild)
                    pkChild->UpdateGS(dAppTime, false);
            }
        }

        virtual void UpdateWorldBound()
        {
            if(!WorldBoundIsCurrent)
            {
                bool bFoundFirstBound = false;
                for(int i=0; i
                {
                    Sptial* pkChild = m_kChild[i];
                    if(pkChild)
                    {
                        if(bFoundFirstBound)
                        {
                            //Merge current world bound with child world bound
                            WorldBound->GrowToContain(pkChild->WorldBound);
                        }
                        else
                        {
                            //set world bound to first nonull child world bound
                            bFoundFirstBound = true;
                            WorldBound->CopyFrom(pkChild->WorldBound);
                        }
                    }
                }
            }
        }
};

scene grapha的update主要做两件事情,一是从上到下更新world transform,二是从下往上更新world bound。其中包围体是要包括所有子节点的包围体的,而只有Geometry类型的节点需要计算自己的包围体(从顶点数据计算)。

wild magic3中,更新不是自动的,必须手工调用,而且要选择从哪一个节点开始更新,一般是某节点需要更新(比如local transform变了)并且他上面没有需要更新的父节点,那么就要调用该节点的UpdateGS,这样的节点有几个就调用几次UpdateGS。 UpdateGS里面通过遍历和递归,做了上面说的两件事情。UpdateGS的参数bInitiator 表明这个node是更新的起点,只有这个node的UpdateGS里面才会向上更新world bound volume直到root,而其他的node只会更新自己的world bound不会向上传播,这是为了提高效率。(因为这是在transform和world bound更新完成之后才调用的,所以只要更新的起点node向上更新包围体就足够了,下层的node没必要向上传播,否则也是被覆盖,浪费计算)

计算transform是在UpdateWorldData 里面做的,对于spatial的UpdateWorldData,主要就是把自己的local transform和parent的world transform级联起来,得到自己的world transform,但是这之前首先会使用controller进行更新,controller可能对transform系统产生影响也可能不影响,使用 controller时通过设置WorldIsCurrent来决定是否controller已经更新了world transform而不需要级联的更新方式。(比如skin controller)。而另外一些controller如普通key frame和IK,只是改变了local transform,还是需要使用级联的方式更新world transform的,他就不会设置WorldIsCurrent。另外一些controller没有影响到transform,也不会设置 WorldIsCurrent,比如morphe controller,但是他需要调用Geometry的UpdateMS来更新模型的一些数据(ModelBound).
Geometry没有override UpdateWorldData,所以和Spatial是一样的。
Node 的UpdateWorldData里面首先是直接调用了Spatial的UpdateWorldData来更新自己的world transform,然后对于他的所有子节点(Spitial,可能是Node或Geometry)遍历调用UpdateGS(bInitiator参数为false,因为子节点肯定不需要传播bound更新到root)。这就形成了UpdateGS的递归调用。这是一个深度优先的树遍历。树的每一层都是先计算好自己的transform然后让子节点去UpdateGS,所有子节点的调用都完成后才会计算自己的world bound,最终所有层次的UpdateGS都执行完毕,回到调用的起点节点那儿,接着执行那个节点的UpdateWorldBound。因为起始调用的节点的bInitiator是true,所以会执行PropagateBoundToRoot,向上更新world bound直到root。

更新UpdateWorldBound在spatial里面是个纯虚函数,Geometry的实现就是使用world transform变换model bound得到world bound,而Node里面则是计算一个包含所有子节点的world bound的总包围体。其中WorldBoundIsCurrent的作用是,当某个node的world bound可以通过其他途径得到时避开正常的计算流程,比如一个房间是固定的可以预先计算好一个world bound不再改变,不管其中的子节点怎么动怎么变都不再计算这个房间的world bound了。

整个过程就是这样的:
三个类(Spatial, Node, Geomotry)
三个主要函数(UpdateWorldData,UpdateWorldBound,以及PropagateBoundToRoot)
三个重要标志的设置(UpdateGS的bInitiator参数,Spatial的成员WorldIsCurrent和WorldBoundIsCurrent)
node/spatial的遍历,UpdateGS的递归
完成了world transform和world bound的更新。

另外UpdateBS是另外一个公开的接口,当model bound变化时,而transform没变化时,就只要调用UpdateBS就可以了。

WildMagic4 WildMagic4 3D GameEngine Design 立即下载

相关推荐

Wild Magic

一个简单的游戏引擎, 可以适合初次学习引擎开发的开发人员参考。

2014技术目标

引擎层次: 从代码级别上熟练掌握wildMagic引擎的架构、代码的组织以及引擎各方面效果的实现。(1,3,5,7) 从项目级别上熟悉ogre的使用方法;(工作时间,2, 6) 从项目级别上熟悉coco2d的使用方法;( 2, 3, 6) 渲染效果: (半个月一个效果) shadow mapping算法(csm, vsm, pcf等阴影算法总结); hdr; dof(Depth_o

smsmn的专栏 776

wild magic 最新代码3

wildmigic 的最新源代码 支持windows linux mac

wild magic3 渲染状态更新和scene绘制

基本上是《3D Game Engine Architecture》第3章的剩余内容,说实话我有点后悔看这个了,应该直接看《3D Game Engine Design 2nd》,不过好歹记录一下,有些“亮点”我第一次看到还是不错的。1 wild magic3 render state主要包括global state, lights, texture, effects1) global s

聚焦游戏和图形引擎开发技术 1943

3D游戏引擎WildMagic5.11源代码及安装文档

开源的3D游戏引擎,可以配合3D Game Engine Desgin的书来学习

WildMagic4.8最新游戏引擎源代码(内含Game Engine 安装文档)(1)

游戏引擎 源码 wildMagic 4.8,压缩卷1 Wild Magic 4.2 and later is now Open Source, using the GNU Lesser General Public License (LGPL). The WildMagic4p8.zip file has the full distribution of version 4.8 of the engine. You should unzip this archive to a new directory tree; that is, do not unzip this on top of an older version of Wild Magic. You may unzip the top-level folder to any location you prefer on your hard drive. The projects all use relative paths and do not rely on the top-level directory being located at the root of the drive. The Macintosh distribution has some script files (.sh extension) that must be assigned the correct permissions. These will be discussed later in the section on compiling.

Wildmagic笔记

声明一下,为了省事,文章的部分内容是从n5的博客里面直接摘抄过来的 1:关于只能指针的,我仿照他写的: class obj { public: obj() { count=0; cout<<"obj is constructed"<<endl; } ~obj() { cout<<"obj is destructed" << endl; } void In

qq960885333的专栏 1558

Wild Magic 4.0 source code part1(3D game engine design 2nd)

两个part, 3d game engine design 第二版对应的源码 有兴趣的同学可以看看

wild magic3的Scene graph结构和Geometric State更新体系

刚看了《3D Game Engine Architecture》第3章“Scene graphs and renderers"的前两节,很精彩,暂且不拿wild magic 3和其他引擎相比较,只是作为读书笔记,记录一下书中的核心内容。我觉得第3章是此书的核心部分,全部内容就是scene graph的更新和渲染,其中第一节描述了wild magic3中的scene graph架构,第二节重

聚焦游戏和图形引擎开发技术 2378

WildMagic4引擎源码

与《3d game engine design,second edition》配套的wild magic4源代码,可与该书配套学习。

TC8测试TCP-UNACCEPTABLE-04/006

TC8测试TCP-UNACCEPTABLE-04/006

WildMagic 简单图元(一)

#include <Wm5WindowApplication3.h> #include <Wm5VisualEffectInstance.h> using namespace Wm5; class MyFrame : public WindowApplication3 { WM5_DECLARE_INITIALIZE; WM5_DEC...

weixin_34112030的博客 253

PSIM-串联谐振半桥LLC开关电源+PFM变频闭环控制【仿真+计算书+参考文献】

内容概要:本文档系统性地整合了电力电子与控制系统仿真领域的丰富资源,聚焦于基于PSIM和Simulink平台的串联谐振半桥LLC开关电源建模与仿真,深入探讨PFM变频闭环控制策略的设计与实现。内容涵盖LLC谐振变换器的工作原理、关键参数设计、开环与闭环仿真模型构建、软开关技术(ZVS/ZCS)、恒压恒流双竞争控制机制以及调频控制等核心技术,配套提供完整的仿真文件、计算书和参考文献,有助于深入理解高频开关电源系统的动态响应特性与稳定性分析方法。此外,文档还汇集了大量拓展性仿真资源,涉及双向DC-DC变换器、PWM整流器、PFC电路、储能系统、微电网优化、DAB变换器、并网逆变器等多个方向,构成一套完整的科研与工程实践参考资料体系。; 适合人群:适用于电力电子、电气工程及其自动化等相关专业的高校本科生、研究生,以及从事开关电源设计、新能源系统开发、电力变换器研发等工作的工程技术人员。; 使用场景及目标:①深入学习LLC谐振变换器的拓扑结构与闭环控制原理;②掌握PSIM/Simulink在电力电子系统中的高精度建模与仿真技能;③为科研项目、学位论文或产品开发提供可复用的技术方案与代码基础;④深化对PFM控制、软启动过程、ZVS/ZCS实现机制及系统稳定性的理解; 阅读建议:建议结合文档中提供的仿真模型与计算书进行同步操作,优先剖析主电路拓扑与控制逻辑架构,再逐步开展参数调节与仿真验证实验,同时可参考所列相关资源拓展技术视野,提升综合设计能力。

各大开源引擎比较 OGRE vs WildMagic5 vs irrlicht vs KlayGE

OGRE   1.杰出的设计模式应用,可拓展性非常强。二次开发的上好选择。 Irrlicht   1.简单精悍,容易上手 WildMagic5   1.注重数学原理、资源回收调度,学术气息浓厚。更新缓慢 KlayGE   1.运用大量最先进的技术,boost库,...国内大牛作品,你可以在opengpu.org 上和他交流 转载于:https://www.cnblo...

weixin_30326515的博客 504

vLLM 多机多卡推理测试与验证(Kubernetes)vLLM 多机多卡推理 Kubernetes 验证

本文记录在两台 L20 机器,每台机器 4 块 L20 显卡(46G)的环境下,使用 vLLM 部署 Qwen2.5-32B-Instruct-GPTQ-Int4 模型并提供多节点多卡推理服务的过程。服务(Serving)模型服务是指将模型部署到生产环境中,通过 API 或其他接口提供预测服务的过程。【分布式推理与服务】(Distributed Inference and Serving)是指在多个机器或设备之间部署和管理机器学习模型,以高效地处理推理请求并满足大规模服务需求。3、启动 vLLM 服务。

流水_鱼鱼的博客 3459

SAP公司间外协业务流程以及配置说明

SAP公司间外协业务流程以及配置说明

竹大的博客 7160

开源3d引擎WildMagic4p7编译方法

<br />用firefox翻墙才跑到其官网上http://www.geometrictools.com,在中国生活真是幸福啊!能体验到其他国家的人民不需要体验的东东!万岁!<br /><br />看这个文件就行 WildMagic4p7/GeometricTools/WildMagic4/Wm4p7InstallationRelease.pdf<br /><br />1.环境变量(1.3 Environment Variables)<br /><br />   WM4_PATH     我的是     

记忆的小甜饼 2160

stm32教程之三重ADC交错采样

ps:本文基于stm32F407ZGT6单片机 stm32F4单片机单通道采集的最大采样率为2.4M,所以有时会难以满足较高频率的采样,于是查阅芯片手册,发现stm32F4支持多重ADC采集,利用每个通道的转换时间,错位采样,从而提高采样率,最大把采样率开到2.4*3=7.2M. (去年初学ADC时研究的,基于cube和HAL库的三重ADC交错采样参考资料不多,我也是研究了一段时间,写下这篇博客希望可以帮助到更多人。) 示意图如下: 以下是官方例子的说明, In this ex...

weixin_52178036的博客 8873

读wildmagic和ogre源码的感受

1。类命名不当会极大地影响系统的可理解性,自认为这一点ogre比wildmagic比差了好多。wildmagic中的类和对象的意义都非常容易理解。而ogre中的类名往往与类的功能相矛盾。比如按MovableObject这个类名理解这个类应该定义有关移动的信息,比如位置,方向,速度等。然而这个类的设计目的却是作为挂接在Node节点的内容和可显示的对象如Entity的父类。而Renderable接口首

Per Pixel Lighting 3589

DMR对讲机的基本概念理解

刚刚入手DMR对讲机,尚未成功联通。国内互联网上能找到的资料很少,大多数也都是一些DMR协议介绍之类的玩意,对实际操作没有指导意义。以下全部是这几天在网上研究各种资料得出的个人思考,如有错误请斧正。 相比与模拟通讯系统,DMR将语音信号转换为包的形式进行收发。将DMR对比成TCP/IP系统会更容易理解。 一般DMR对讲机都支持模数双通,说明DMR应该使用了跟FM同样的无线AP组件,只在解码上有区别。对讲机先使用DMR进行数字解码,解码成功则说明是数字信号,不成功则使用模拟方式再次进行解码。可以对等理解为

1万+

【LaTeX】IEEE会议模板中使用BibTex插入文献(解决报错:Something‘s wrong--perhaps a missing \item. \end{thebibliography}

使用IEEE会议论文LaTeX模板时遇到的一个错误,问题描述为:使用Texstudio编译LaTeX模板报错,报错信息提示为。出现的原因为IEEE会议论文模板自带的参考文献引用方式为手动插入,即不使用格式的参考文献,手动将参考文献调整为合适格式,然后粘贴到文本中,我准备将其换成方法引用参考文献。我的替换步骤为删除原始参考文献对应内容,即模板中的: 将以下函数添加到原始参考文献对应位置,对应上文新建的文件。 再次编译出现报错 删除文件夹中的文件 修改模板中的引用名称 引用方法为: 将 替换为 再次编译——

TangPlusHPC的博客 9900
上一篇: More Effective C++:不同new和delete
下一篇: wild magic3 渲染状态更新和scene绘制(转载)
Hashmat
博客等级 码龄16年 14粉丝 62原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值