gamebryo笔记

AcotrManager 取当前动画播放时间的长度. 可以有2中办法.
NiAnimationConstants::GetEndTextKey() 返回字符串 "end"
 float fEndTime = m_spActorManager->GetNextEventTime(
            NiActorManager::TEXT_KEY_EVENT,
            m_spActorManager->GetTargetAnimation(),
            NiAnimationConstants::GetEndTextKey());
 
//这种写法更明确一点. END_OF_SEQUENCE 标识。The end of the sequence was reached. This is equivalent to a TEXT_KEY_EVENT for the string "end".
  NiFixedString kTextKey;
  float fEndTime = m_spActorManager->GetNextEventTime(
            NiActorManager::END_OF_SEQUENCE,
           m_spActorManager->GetTargetAnimation(),kTextKey);
NiApplication 用来隐藏和显示图标。
     void HidePointer();
    void ShowPointer();
如果抽象工厂产生的类对象不能互相替换,则不能使用这个工厂。 
服务器是否需要NiApplication或者其中的某些工程如实体?? 
NiApplication 工程包含winmain 可以设计成主程序。对于window窗口则使用NiWindows类。这样窗口显示注定不能使用wxWidget. 引入太多无用的东西,命名冲突,编译速度等等。如果修改wxWidget又要引入wxWidget工程进入到整个程序工程中。更容易混乱,而且修改wxWidget之后,和服务器的wxWidget又不兼容,出现2套不同的dll。 
gb 2.5 对于一个地形最多4个材质 
默认Input 输入 NiSample 工程设置 m_bUseNavSystem 属性为 true 即可
后台加载

NiGeometryData::STATIC

    The data never changes.

NiGeometryData::MUTABLE

    The data changes infrequently.

NiGeometryData::VOLATILE

    The data changes every frame.

 
NiTriBasedGeom
Abstract base class for all geometry subclasses that base their geometry upon triangles. 
m_bMultiThread  NiApplication 后台成员设置设备为多线程设备,对于2.3 版本及以下是必须的。但指定多线程设备不利于性能。
似乎2.5 有所改善,使用后台加载不再需要多线程设备。有待确定

BackgroundLoad Demo Code Overview

The following NiStream functions are used to perform the background load in this sample:
如下的NiStream 函数展示了如何进行后台加载:
void NiStream::BackgroundLoadBegin(const char* pcFileName);

BackgroundLoadBegin is used to launch the background load.
BackgroundLoadBegin 用来启动后台加载。

NiStream::ThreadStatus NiStream::BackgroundLoadPoll(LoadState* pkState);

BackgroundLoadPoll is used to poll the status of the background load. It returns NiStream::IDLE when the background load has finished. It returns NiStream::LOADING while the background load is in progress. If a non-NULL pointer is passed as the pkState argument to BackgroundLoadPoll and BackgroundLoadPoll returns NiStream::LOADING, the structure pointed to by pkState is filled in with values that indicate the progress of the background load. These values are used in this sample to calculate the values displayed on the screen that indicate the progress of the background load.
BackgroundLoadPoll 用来查询后台加载的情况. 当后台加载完成的时候返回NiStream::IDLE。当后台加载还在进行的时候返回NiStream::LOADING 如果一个非NULL的pkState参数传入BackgroundLoadPoll 并且BackgroundLoadPoll 返回NiStream::LOADING, pkState指向的结构被填充后台加载进度的值。 

bool NiStream::BackgroundLoadGetExitStatus() const;

After BackgroundLoadPoll indicates that the background load has finished, BackgroundLoadGetExitStatus is used to determine whether the background load succeeded. It returns true if the load succeeded and false if it failed.
在BackgroundLoadPoll指示后台加载已经完成。BackgroundLoadExitStatus 用来决定后台加载是否成功,true 代表加载成功,false 表示失败.
加载结束后BackgroundLoadOnExit 函数被调用可以在里面确定是否加载成功.     assert(BackgroundLoadGetExitStatus());

bool NiStream::BackgroundLoadFinish();

BackgroundLoadFinish blocks until a background load runs to completion. In this sample, we call it before allowing the application to exit. If the user quits the application before the background load finishes, calling BackgroundLoadFinish is necessary. It is an error to destroy an NiStream object while a background load is in progress. If the background load has already finished before BackgroundLoadFinish is called, BackgroundLoadFinish will return immediately.
BackgroundLoadFinish 用来阻塞直到后台加载完成。我们可以在应用程序退出前调用这个函数。如果用户在后台加载完成前退出应用程序,调用BackgroundLoadFinish 是必须的。在后台加载正在进行的时候摧毁 NiStream 对象是错误的行为。当后台加载完成时。BackgroundLoadFinish 将马上返回。

On most platforms, a background load will not receive any cycles unless the foreground thread yields the processor by calling NiSleep, a global function declared in NiSystem.h:
在大部分平台 ,后台加载线程不会执行除非前台线程通过调用NiSleep让出处理器,在NiSystem.h 中有一个全局函数NiSleep

void NiSleep(unsigned int uiMilliseconds);

NiSleep puts the calling thread to sleep for the number of milliseconds specified by its uiMilliseconds argument. If a background load has been launched, it will wake up and run while the foreground thread is asleep.

The BackgroundLoad sample loads its NIF files using an NiStream-derived class called CallbackStream. CallbackStream overloads the virtual NiStream function BackgroundLoadOnExit. BackgroundLoadOnExit is called by the background loading code in NiStream when a background load completes. The default implementation, NiStream::BackgroundLoadOnExit, does nothing. The purpose of the function is to allow applications to override it in classes derived from NiStream and do work that should be done in the background thread to avoid frame rate hits that would happen if the work was done in the application's main thread. CallbackStream::BackgroundLoadOnExit creates property states and effect states for the objects extracted from ROOM.NIF and precaches the geometry objects.

性能测试工具

NiVisualTracker(float fMaxValue, unsigned int uiNumDecimalPlaces, NiRect<float> kWindowRect, const char* pcName, bool bShow = true, unsigned int uiNumGraphs = 5)
fMaxValue 设置测量工具Y轴最大值。uiNumDecimalPlaces 右侧标尺数字包含的小数位数。kWindowRect 测量图矩形位置. pcName测量图名称, bShow 是否显示
uiNumGraphs 曲线图初始的个数。如果 AddGraph 个数超过这个数,会自动增加曲线图个数

unsigned int AddGraph(GraphCallbackObject* pkObject, const char* pcName, const NiColor& kColor, unsigned int uiNumSamplesToKeep, float fMinSampleTime, bool bShow);

This adds a GraphCalbackObject to the list of graphs maintained by the NiVisualTracker.  A GraphCalbackObject is the class that maintains the current state of a tracked statistic. pcName is the name of the object as it is to be displayed below the graph.  kColor is the color for both the lines drawn and the displayed name.  uiNumSamplesToKeep is the number of samples to keep in the history for that statistic.  fMinSampleTime is the minimum time that must elapse between samples. bShow is the initial show/hide status for that particular graph.

向NiVisualTracker维护的图形列表添加一个GraphCallbackObject对象。一个GraphCallbackObject 负责维护tracked当前状态的统计信息。pcName 是在图形列表下面显示的曲线图名称。kColor 是统计曲线和显示名称使用的颜色。uiNumSamplesTokeep 统计保存的历史数据包含的采样个数。fMinSampleTime 在2次采样之间流逝的时间。bShow 初始化某个曲线图的显示/隐藏状态。

NiVisualTrackerOutput
This class is a metrics output module designed for easily adding instrumented metrics to an NiVisualTracker graph.
为简化向NiVisualTracker图添加测量工具

//构造函数
NiVisualTrackerOutput(unsigned int uiFramePeriod)

Constructs a visual tracker with the specified frame period. The frame period is how many frames each metric will be calculated for before being displayed to the tracker. This number must be greater than zero.
创建一个执行周期为uiFramePeriod的visual tracker. 这个周期指每次测量之间的帧数。这个数必须大于0

//添加曲线图函数
void AddGraph(NiVisualTracker* pkTracker, const char* pcMetricName, MetricsFunction eFunction = FUNC_MEAN, const NiColor& kColor = NiColor::WHITE, unsigned int uiNumSamplesToKeep = 100, float fMinSampleTime = 0.1f, bool bShow = true, float fScale = 1.0f, bool bAddFunctionSuffix = true, const char* pcAlternateName = NULL)

This function adds a metric by name to an existing visual tracker. eFunction is an enumeration (defined in NiCalculatingOutput) that defines which function of the metric should be graphed (mean, sum, min, max, or count.) kColor, uiNumSamplesToKeep, fMinSampleTime, bShow, and fScale are all passed directly to the NiVisualTracker::AddGraph function.

通过测量名称(如NiApplicationMetrics::ms_acNames[NiApplicationMetrics::FRAMERATE] 存储的帧速率的名称)为一个存在的visual tracker 添加测量信息, eFunction 是在NiCalculatingOutput中的一个枚举,定义采用那个函数处理数据(mean,sum,min,max.count 平均值、总和、最大值、最小值、计数,指一个uiFramePeriod 周期内数据)。

NIMETRICS_ADDVALUE(ms_pcMetricName, 100 * NiUnitRandom());  添加某个测量名称对应的测量数据

//例子
NiVisualTrackerOutput* pkVTOutput = NiNew NiVisualTrackerOutput(uiVTFramePeriod);
NiMetricsLayer::AddOutputModule(pkVTOutput);
pkVTOutput->AddGraph(m_kTrackers.GetAt(0), NiParticleMetrics::ms_acNames[NiParticleMetrics::UPDATED_PARTICLES],
        NiVisualTrackerOutput::FUNC_SUM_PER_FRAME, NiColor(0.0f, 1.0f, 0.0f),100, 0.1f, true, 1.0f, false, "Particles");

使用xml记录数据
const char* pcFilename = "ProfileSampleXMLOutput.xml";

// Add XML output module to metrics layer
NiXMLMetricsOutput* pkXML = NiNew NiXMLMetricsOutput(uiFramePeriod, pcFilename);
NiMetricsLayer::AddOutputModule(pkXML);

NiXMLMetricsOutput
This class calculates instrumented metrics over some user-specified number of frames. It will calculate the mean, sum, min, max, and count for each metric and output them in an XML file. (Count is the number of values that were used to calculate the other four values.)

Labels: NiVisualTracker, NiVisualTrackerOutput
Programming for a Scene Graph

Scene Graph Basics
场景图形基础
A hierarchical scene graph is a rooted, directed, acyclic graph (DAG), consisting of objects that represent the drawable and audible parts of an application's 3D world.  Such a hierarchical scene graph forms the basis of a Gamebryo scene database.
一个分级场景图是包含根、方向、无循环的图形,包含应用程序3d世界中可听或可视的部分。如此的分类场景图形成gamebryo场景数据基础。

All objects in a scene graph are subclasses of NiAVObject, each of which specialize and extend the abstract base class.
场景图中所有对象都是抽象类NiAVObject经过特化或者扩展的子类
A scene graph consists of a root node that has zero or more "children".  Applications may have any number of scene graphs.  The leaves of the tree represent geometric objects, while the internal nodes serve to group and manage parts of the scene graph.  The NiAVObject base class itself does not support the notion of children.  Instead, the NiNode class and its subclasses add this capability.
一个场景图可以包含0个或者更多孩子,应用程序可以有人一个场景图。树叶代表几何图形对象,而其他内在的节点负责场景图的组织和维护。NiAVObject 基类自己并不支持子树的概念,代替的是使用NiNode类和它的子类
Note that the scene graph's geometric parent-child hierarchy should not be confused with the class hierarchy structure that Gamebryo uses.  These two hierarchies are completely independent.  The children of a NiNode in a scene graph may not be a child class (subclass) of NiNode.
注意不要弄混场景几何体父子层次和gamebryo类派生层次。这是2个完全独立的概念。场景图中NiNode的孩子不一定就是NiNode的子类
 
Transformations and Coordinate Systems
变换和坐标系

Conventions
Gamebryo uses a right-handed coordinate system.
No axis is required to be up, although NiCamera defaults to Y as up.
NiMatrix3 rotations are clockwise about an axis, when looking down the axis toward the origin. Also translation vectors are column vectors.
NiQuaternion rotations are counter-clockwise about an axis, when looking down the axis toward the origin.

协定
Gamebryo 采用右手坐标系系统.
没有要求那个轴一定向上,尽管NiCamera 默认Y轴向上.
NiMatrix3 旋转为顺时针为正方向,当由正轴看向原点时。变换矩阵为列向量
NiQuaternion 当由正轴看向原点时,绕轴旋转逆时针为正。
Each NiAVObject has its own set of modeling space to world space transforms, and all direct children of a NiAVObject are defined in their parent's coordinate system.  This organization forms a hierarchy of coordinate systems, useful for articulated bodies and a wealth of other types of object representations.
相对于世界空间变换每个NiAVObject 都有自己的模型空间,所有NiAVObject的直接孩子都定义在其父坐标系中。这样组织形成了坐标系继承关系。对于关节和许多对象表示都很有用。(骨骼动画组织方式就是这样。父坐标改变才能影响子坐标)
More specifically, the transformation from the model space of a given NiAVObject O with parent P to world space is given by:

OM®W = PM®W [ OT OR OS ]  //由模型空间变换到世界坐标系的矩阵表示

where:

PM®W

is the parent object's model to world space transform

OT

is O's translation matrix (which is a pure translation matrix)

OR 

is O's rotation matrix (which is a pure rotation matrix - i.e. orthonormal)

OS

is O's scaling matrix (which is a pure uniform scaling matrix)

                    

Note that each of the three transformation components is not stored as a separate matrix, but rather is stored using as little information as possible.  Specifically, a 3 by 3 matrix for rotation, a vector for translation, and a scalar for scale are used.
注意这三种变换并没有存放成3个分离的矩阵,而是本着占用空间尽可能少的原则。一个3×3矩阵代表旋转,一个矢量代表平移,一个标量代表缩放
This set of transforms defines three distinct coordinate systems for each object:  a Model coordinate system, which is defined by the set of all transforms from the root of the scene graph to the object; a Local coordinate system, which is equivalent to the object's parent's Model coordinate system (i.e. it is the object's Model coordinate system without the object's own transforms); and the World coordinate system, which is the same for all objects in a given scene graph.
这组变换包含三个截然不同的坐标系:模型坐标行。
So, points transform in the following way:
所以点变换如下

vL = [ OT OR OS ] vM

v W = P M ®W v L

vM is the point in the given object's Model coordinate system. 给定对象模型坐标系中的点
vL is the point in the given object's Local coordinate system. 给定对象局部坐标系中的点
vW is the point in the world coordinate system, 世界坐标系中的点

Scene Graph Hierarchy and Hierarchical Coordinate Systems

In order to render an object in world space, it is necessary to transform into additional coordinate systems. For more information on this, including the camera's coordinate system, please see Viewing Geometry.

 
Class Descriptions

NiCamera

NiCamera objects represent virtual cameras for imaging the geometry represented by a scene graph. It is important to note that NiCamera is a descendant of NiAVObject. As a result, a camera may have a parent object that affects the camera's position and orientation. This approach enables cameras to be attached as children of objects in the scene, in order to follow them automatically, as they move. The camera object may operate on a portion of the scene graph that is an ancestor of itself.

For example, a flight simulator scene may contain terrain and several fighter planes. The game may choose to attach a "chase camera" as a child of one of those airplanes, enabling the camera to follow the airplane automatically. This same camera may have as its focus the entire scene graph, enabling the camera to render the terrain and the fighter plane to which the camera is attached.

NiCamera 代表一个虚拟的摄像机。注意:NiCamera 是一个NiAVObject 子类,这很重要。所以一个摄像机可能有父节点影响摄像机的位置和方向。这能够使摄像机可以attach到一个场景中的对象上成为子节点,这样摄像机可以跟随他们自动移动。
例如:例如一个飞行模拟场景包含地形还有战斗机。游戏可以选择这些战斗机中一个attach一个chase camera 到它上面。这使摄像机自动跟随战斗机。

NiDynamicEffect

The subclasses of the abstract class NiDynamicEffect represent time- and geometry-dependent visual effects, such as per-vertex lighting, texture-based fogging, shadows, projected images, etc. These effects fall into two major categories:  per-vertex lights and texture-based effects.

NiDynamicEffect is a subclass of NiAVObject, so objects of this type have a concept of a model space coordinate system. The positions and directions of subclassed effects are defined in the object's model coordinate system, so effects may be attached as children of other scene graph objects. This approach enables the effects to be attached to characters or objects in the scene, such as headlights being attached to a car.

NiDynamicEffectList contains a list of affected objects – objects whose appearances are modified by the effect. This list of affected objects enables effects to have fixed "scope". Applications can increase performance greatly by adding only objects that need to be modified by an effect to that effect's scope list. All other objects will avoid any computations required by the effect.

抽象类NiDynamicEffect 子类描述随时间和几何相关的效果,如 per-vertex lighting,texture-based fogging, shadows, projected images 等等,这些效果分为2个主要的范畴:per-vertex lights 和 texture-base effects

NiDynamicEffect 是NiAVObject 的子类,所以这个类型的对象也有模型空间坐标系的概念。子类effects的位置和方向定义在对象的模型坐标系中,所以effects可以attach到其他的场景图对象上作为子节点。这样effect可以attach到角色上或者场景中的其他对象上。

NiLight

The subclasses of the abstract NiLight are used to create dynamic, per vertex lighting effects on objects in the scene graph. Because NiLights are themselves NiDynamicEffects, they may be "attached" to other objects in the scene graph, in order to move with them, automatically. Also, by virtue of being children of NiDynamicEffect, they have "scope" – i.e., the specific set of scene graph objects that they affect. Dynamic lighting and the subclasses of NiLight are described in more detail later in this manual.

抽象类NiLight的子类用来为场景图中对象创建动态的、逐顶点光照效果。他们可能attached到场景图的其他对象上,由于做为NiDynamicEffect的子类。他们拥有范围,如他们影响的场景图对象的集合。在手册后面动态光和NiLight的子类有更详细的描述

NiTextureEffect

The subclasses of the abstract NiTextureEffect are used to create texture-based effects. These effects may be striking and eye-catching. The effects include complex spotlights, slide projectors, shadows, overhead clouding, and fogging. Texture-based effects are described in detail in Texturing Basics.

抽象类NiTextureEffect用来创建纹理效果. 这些效果比较显著和吸引眼球。效果包括复杂的聚光灯、幻灯片效果、阴影、云、雾。这些在Texturing Basics里面有详细描述。

NiGeometry

NiGeometry objects contain the vertex coordinates, normals, vertex colors and texture coordinates that describe geometric shapes.  NiGeometry is an abstract class because it does not contain any information about how vertices are organized into drawable objects.

NiGeometry 对象用顶点坐标、法线、顶点颜色、纹理坐标来描述几何图形数据。NiGeometry 是一个抽象类因为他不包含任何顶点被组织到渲染对象的信息

NiLines

NiLines objects add vertex colors and texture coordinates to the data contained in a NiGeometry object, as well as the notion of a line-segment basis for the representation. NiLines also include an array of Boolean values that represent whether or not each pair of adjacent points in the array is connected by a line segment.

NiLines 对象添加顶点颜色和纹理坐标到NiGeoMetry对象数据中。用来表示线段的概念,NiLines 还包含一个Boolean数组用来表示是否每对邻接点连接成为一个线段

NiTriBasedGeom

NiTriBasedGeom objects add the notion of triangles to the representation of geometry. All subclasses of NiTriBasedGeom are drawn using triangles. NiTriBasedGeom is still an abstract class because it does not contain any information about how the vertices are actually organized into triangles.

NiTriBasedGeom 对象为几何体表示添加三角形的概念。所有NiTriBasedGeom子类使用三角形来渲染。NiTriBasedGeom 是一个抽象类因为他不包含顶点如何组织成三角形的信息
Note that all triangles in Gamebryo are assumed to be single-sided and oriented counter-clockwise.
注意gamebryo中所有的三角形都是单边逆时针导向的

NiParticles

NiParticles are a subclass of NiGeometry, which treats its list of vertices as independent points. This capability is useful for dynamic particle systems, as well as other effects.
NiParticles 是NiGeometry 的子类,他视顶点的集合为独立的点。这个能力对动态粒子系统很有用。
 
Updating the Scene Graph Geometry

更新场景图几何数据
An application may change the local transformations of a node as needed. The computation of the world transformation for the node and any transformations of descendants of that node are deferred until the application makes a call to an update routine.

应用程序可以改变一个节点的的本地变换。计算节点的世界变化以及其子孙的变换知道应用程序调用update时才执行
The update is efficient in that it does a single depth-first traversal of the subgraph to compute world transformations and world bounding spheres, thereby minimizing the number of nodes visited. While recursing down a path, the transformations are updated. Once a node's transformations are updated, the recursion continues to each child of the node. After updating the matrices, the world bounding spheres are updated on the upward return from the recursive calls.

update 执行过程:它沿子图进行深度优先访问,计算世界变换矩阵和包围球,因子最小化可视节点的数量。在更新完矩阵之后。沿着递归调用返回,更新世界包围球
In summary, transformations are updated while recursing down a path, and bounding spheres are updated while returning up a path.
总的来说,递归一个路径时变换操作被更新,而返回时包围球被更新
 
Usually most objects in a world are not moving, so the updates are restricted to only a few moving objects. To initialize the processing of a scene graph, the update routine must be called at least once at the root of the graph before an application uses the scene graph.  This approach guarantees that all the local and world information at the nodes is up-to-date.

通常世界中大部分对象并不移动,所以更新至限制在少数移动的对象上面。为了初始化场景图处理。update必须在应用程序使用场景图之前在root上调用一次。这个操作保证节点上本地信息和世界信息都被更新

During frame-to-frame application runtime, applications must call Update on an object "O" if any of the following criteria are met:

  • O is attached to or detached from a parent (direct parent only – not a "grandparent", etc)

  • O has a new child attached or a current child detached (direct children only – not "grandchildren", etc)

  • Any of O's transforms are changed

在应用程序每2帧中间,如果一个对象o发生下面的变化必须调用Update
    O 从一个父节点(直接父节点不是祖父节点等等)attached 或者 detached
    O 有一个子节点 attached 或者 detached (直系子节点而不是孙节点)
    任何O的变换矩阵被改变
Note that a call to Update on the current parent or any current ancestor can substitute for a call to Update on the object itself. For example, if object A attaches children B and C, then a call to A->Update will suffice. It is not necessary to call Update on all three objects. Applications can and should "batch" calls to update in this way.

注意任何在父节点或者祖节点的Update调用,可以代替对象自己的Update调用。例如一个对象A attach 子B 和 C,然后调用A->Update即可。不需要对三个对象调用Update操作,应用程序调用Update时能执行批次更新
For example, if an application makes changes to all of the "joint" transforms of an articulated character, it should defer calling update until all changes are made. It can then call Update once, at the root node of the character.

例如:如果一个应用程序改变了有关节的角色所有连接点变换矩阵,他应该推迟update的调用知道所有改变完成。可以在角色的root节点调用一次Update即可
However, note that Update should be called as low on the scene graph as possible.  Calling Update on the root of the scene graph every frame when only a single leaf has changed is excessive, and will lower performance.

但是,注意在场景图中Update应该尽量少调用。仅仅因为一个叶节点变化每帧都在场景图上调用Update将会降低性能
2008-06-05

Cloning Internals
Cloning是产生对象的拷贝的一种方法。应用程序调用下面的的函数来克隆对象。第一个函数使用缺省值来克隆对象名称,这在后面讨论。第二个版本允许通过NiClonigProcess来实现局部控制,这是为多线程情况下设计的函数。
NiObject* NiObject::Clone();
NiObject* NiObject::Clone(NiCloningProcess& kCloning);
使用克隆而不是通过例如从NIF文件中重复加载场景图的优点是这一类型的对象往往要耗费很多的内存,通过克隆来像NiGeometryData中的顶点数据可以被多个克隆对相共享,而通过单个NIF文件加载多次时她的顶点数组却是重复的。
为了得到一个对象的一个彻底的深拷贝可以使用
NiObjectPtr NiObject::CreateDeepCopy
这个调用使用流系统将对象保存到一个内存块中,然后加载这个内存快到一个新的对象。请小心使用深拷贝。有大量模型数据和纹理关联的对象应该尽可能使用共享数据。深拷贝不共享任何的东西。
下面的一些静态NiObjectNet中的静态函数用来决定存储在NiObjectNET中的对象名称在克隆的时候得缺省设置。
static void SetDefaultCopyType(CopyType eCopyType);
static CopyType GetDefaultCopyType();
static void SetDefaultAppendCharacter(char cAppendCharacter);
static char GetDefaultAppendCharacter();
The possible values of NiObjectNET::CopyType, the enumerated type that specifies the copy mode, are:
指定复制模式的NiObjectNET::CopyType枚举类型的可能值如下:
枚举 描述
COPY_NONE 不复制名字字符串,新的克隆对象的名字设置为NULL。
COPY_EXACT 新的克隆对象的名字字符串直接从原来的对象的名字中复制过来。
COPY_UNIQUE 新的克隆对象的名字字符串是原来对象的名字添加一个字符。添加的字符通过NiObjectNET的静态函数SetAppendCharacter和GetAppendCharacter来访问。
通过SetDefaultCopyType和GetDefaultCopyType访问的变量的缺省值是COPY_NONE。通过SetDefaultAppendCharacter和GetDefaultAppendCharacter访问的变量的缺省值是‘$’。

多线程时的克隆
单线程程序调用NiObject的Clone()成员不用考虑其他线程的影响。而多线程时,从GetDefaultCopyType和GetDefaultAppendCharacter的返回值可能在另外的一个线程通过调用SetDefaultCopyType和SetDefaultAppendCharacter时发生变化。这个函数不是线程安全的。在多线程应用程序中应用程序克隆的时候应该在NiCloningProcess对象中设置一个局部的复制类型和添加字符,如下所示:
NiCloningProcess kCloning;
kCloning.m_eCopyType = NiObjectNET::COPY_EXACT;
kCloning.m_cAppendChar = '%';
NiObject* pkClone = pkNode->Clone(kCloning);

Names

The class NiObjectNET supports character string names to facilitate identifying objects and searching for objects in a hierarchy. The following functions are used to access the name of an object:
类NiObjectNET 支持字符串名字来鉴别对象,下面的函数用来访问名字

void SetName(const NiFixedString& kName);

const NiFixedString& GetName() const;

SetName increments the reference to kName.

The function NiAVObject::GetObjectByName can be used to recursively traverse scene graphs in search of an object with a specific name. Its prototype is as follows:

NiAVObject::GetObjectByName 用来递归访问场景图来查找拥有指定名字的对象。函数如下:

NiAVObject* GetObjectByName(const NiFixedString& kName);

Note that when cloning an NiObjectNET, the clone's objects will have NULL names by default. This behavior can be changed, and is described in the cloning section of this manual. 

注意:当我们cloneing 一个NiObjectNET 的时候,克隆对象默认名字为NULL,这个行为可以改变

模板类
Gamebryo提供了一序列基本的模版容器类。在Gamebryo内部这些容器类在库的内部普遍使用。这些基本的容器类在下面描述;特们的特定用处和成员函数将在后面的章节中描述。

列表
NiTPointerList对象用来可以用来容纳和管理指针、智能指针或者其他等于指针类型大小或更小的元素。这个类允许在任意的位置有效地插入或删除元素,以及有效地前向和后向迭代所有元素。这个类也可用来查找给定值的元素的存在和位置。NiTPointerList的项从共享内存池中按块分配,这使得这个类快速和内存高效。NiTList已经不赞成使用,应用程序应该使用NiTPointerList代替。对于大小大于指针大小的对象,可以使用NiTObjectList。

数组
NiTArray对象实现动态数据的功能,几乎可以容纳任意类型的对象。数组可以增长和收缩,还可以根据需求进行压缩(通过转移元素来删除空的空间)。对于基本类型(char*,float,int等)请使用NiTPrimitiveArray。对于从NiMemObject派生的类型,请使用NiTObjectArray。注意NiTArray有65535个元素的限制,对于更大数目的数组请使用NiTLargeArray派生的类,例如:NiTLargePrimitiveArray或NiTLargeObjectArray。

映射
NiTPointMap对象实现哈希表(也叫“字典”)的功能,允许任意类的键映射到一个指针、智能指针或者其他等于指针类型大小或更小的元素。它们能够进行键/值对的快速存储和查找。不要使用它来作为字符串键的哈希表,对于这样的哈希表请使用专门为之设计的NiTStringPointerMap对象。NiTPointerMap和NiTStringPointerMap的项从共享内存池中按块分配,这使得这些类快速和高效。对于大小大于指针大小的对象可以使用NiTMap和NiTStringMap。

StringMap
字符串映射
NiTStringMap和NiTStringPointerMap对象在某种程度上功能上类似于NiTMap和NiTPointerMap对象,但是它们接受字符串作为键并使用字符串比较作为键哈希。
FixedStringMap
固定字符串映射
NiTFixedStringMap对象的功能在某种程度上类似于NiTMap对象,但它接受NiFixedString对象作为键。

Queue
队列
NiTQueue为几乎任何类型的对象实现一个先进先出(FIFO)的队列。但不支持智能指针。
集合
NiTSet为几乎任何类型的对象实现一个无序的集合。但不支持智能指针。对于基本类型(char*,float,int等)请使用NiTPrimitiveSet。对于NiMemObject派生的对象请使用NiTObjectSet。对于对象的智能指针请使用NiTObjectPtrSet和NiPrimitivePtrSet,它们能正确地处理引用计数。

内存池
NiTPool实现小对象的内存池。使得应用程序可以一次分配大量小对象并通过内存池重用它们,而不是单个地分配和释放小对象。
 
在任何可能的情况下,Gamebryo都避免使用全局常量和枚举类型,取而代之是使用类的枚举类型。类的枚举类型都使用大写加下划线分割词的方式,例如:NiAlphaProperty::ALPHA_SRCALPHA 

Type

Prefix

Example

character

c

char cVariable;

short

s

short sVariable;

integer

i

int iVariable;

long

l

long lVariable;

unsigned character

uc

unsigned char ucVariable;

unsigned short

us

unsigned short usVariable;

unsigned integer

ui

unsigned int uiVariable;

unsigned long

ul

unsigned long ulVariable;

enumeration

e

NiFogProperty::FogFunction eFunction;

float

f

float fVariable;

double

d

double dVariable;

class, struct

k

NiPoint3 kVariable;

array

a

unsigned int auiVariable[2];

pointer

p

float* pfVariable;

pointer to pointer

pp

float** ppfVariable;

pointer to void

pv

void* pvVariable;

pointer to function

pfn

int (*pfnVariable)();

size_t

st

size_t stVariable;

ptrdiff_t

dt

ptrdiff_t dtVariable;

NiInt32

i32

NiInt32 i32Variable;

NiUInt32

ui32

NiUInt32 ui32Variable;

NiInt64

i64

NiInt64 i64Variable;

NiUInt64

ui64

NiUInt64 ui64Variable;

 指向类指针 pk,智能指针 sp

Labels: 命名规范
2008-06-04

在Gamebryo中通过使用智能指针实现引用计数的半自动化。这通过NiPointer来实现,这个模板类重载了操作符,使得它的实例表现出来像一个标准的指针。然而,
智能指针自动地增加和减少它指向对象的引用计数,从而应用程序不在直接调用NiRefOjbect的引用计数函数。例如在函数中如果声明一个局部智能指针变量并指向对象A,那么对象A的引用技术在赋值的时候将会增加1。当函数返回的时候,这个局部的智能指针被摧毁(超出了作用域),对象A 的引用计数将会减少1。
约定俗成,每个从NiRefObject派生的Gameroy类都有一个方便的智能指针声明,它表现在类型名称上加“Ptr”(NiNodePtr、NiTriShapePtr等)。

NiNodePtr spParent = <some node>;

NiNodePtr spChild = NiNew NiNode; 
//spChild points to new object. Reference count is 1.

spParent->AttachChild(spChild); 
//Reference count of object pointed to by spChild is now 2, since NiNode objects use smart pointers to refer their children.
 
spParent->DetachChild(spChild); 
//Reference count of object pointed to by spChild decreases  to 1.
 
spChild = 0; 
//Reference count of object decreases to 0. Object is deleted.
做为NiRefObject 派生类对象的应用程序指针在交叉调用会减少某个对象智能指针引用计数的时候,这个对象也应该是个智能指针。例如,如果你从父节点中detach一个NiAVObject子对象时,但不想对象在被父结点detach的时候删除,那么你的代码中指向子对象的指针也应当是个智能指针。
 
永远不要对智能指针作delete调用,这一点非常重要。这是标准堆上的指针对象和智能指针对象的唯一的行为区别。在智能指针对象上调用delete操作,
那么不论这个智能指针指向的指针对象的引用计数是多少,该对象都会被删除。如果想释放一个智能指针对指向对象的引用(在智能指针因超出作用域被摧毁之前),将智能指针赋值为0即可 这样确保对象引用计数减少到0的时候摧毁,类似的永远不要对一个NiRefObject对象指针作delete操作,这将也会永久摧毁这个对象。
 
正如在NiRefObject中讨论的那样,智能指针智能指向在堆上动态分配的对象。永远不要将智能指针指向一个在栈上的对象(局部变量)。永远不要将智能指针指向一个静态的对象。

为了区别指针和智能指针,Gamebryo对常规指针使用“pk”前缀,对智能指针使用“sp”前缀
 
如果一个函数使用智能指针作为参数,那么不要把一个没有被其他智能指针引用的对象常规指针作为参数传入到函数中。如果这样做,那么这个对象指针将会被摧毁掉。接下来是这个问题详细描述:
    1 常规指针pkObject指向一个动态分配的对象,其引用计数为0。
    2 传输pkObject到一个智能指针参数,编译器隐式调用智能指针的构造函数将pkObject转换到一个临时的智能指针,并将对象的引用计数增加到1。
    3 在函数调用的作用域,这个临时智能指针通过调用智能指针的拷贝构造函数复制到一个局部智能指针中,并将对象的引用计数增加到2。
    4 当函数调用返回的时候,局部智能指针被摧毁,并将对象的引用计数减少到1。
    5 在调用完成的时候,临时智能指针对象也被摧毁,并将对象的引用计数减少到0,这导致对象被释放掉。
当处理引用计数对象的时候智能指针不是必须的,智能指针是一种简易的工具。NiRefObject包含IncRefCount函数和DecRefCount,可以直接通过这些函数添加和释放引用。智能系统是这些调用的一个简单包装。应用程序可以混合使用智能指针和手工修改引用计数。
智能指针系统提供了两个宏,一个永远定义智能指针类型另一个用来智能指针类型转换。类型定义的宏是NiSmartPointer(classname)。例子如下
NiSmartPointer(NiNode)
类型转换宏是NiSmartPointerCast(classname, pkObject)。如下是典型的使用:
NiAVObjectPtr spChild = <some pointer known to be an NiNode>;
NiNodePtr spNode = NiSmartPointerCast(NiNode, spChild);
注意类型转换时操作是静态的不是动态的,所以我们应当在知道要转换的指针是正确的类型的时候使用NiSmartPointerCast。

Labels: NiPointer, 智能指针, NiSmartPointer, NiSmartPointerCast
Gamebryo通过NiInit()函数以及相关类的NiStaticDataManager的来初始化和分配存在于整个应用程序生命周期的对象。通过NiShutdown()函数来释放所有Gamebryo资源。 
应用程序必须确认NiInit()函数是在任何Gamebryo相关操作之前调用。
应用程序必须在退出main函数前删除所有创建的Gamebryo对象之后调用NiShutdown()函数。
这样的话程序不应该创建静态Gamebryo对象(不是指针),以免错误的内存泄漏提示。
同样静态分配的智能指针在退出main之后不应该还指向Gamebryo对象。可赋值NULL可使智能指针析构(引用计数为0)
注意:每个Gamebryo库的静态数据管理器在该库的头文件被包含后才能激活。例如:除非应用程序包含了NiAnimation.h文件否则用于NiAnimation库的静态数据管理器将不会初始化。在流NIF和GSA文件时也需要包含这个库的顶层头文件。

NiAlloc, NiMalloc, NiFree, NiRealloc, NiAlignedMalloc...

Gamebryo direct allocation routines are used for intrinsic types (floats, ints, chars, etc) and types that do not need constructors or destructors. Much like malloc, free, and realloc, these routines simply allocate the memory that you requested. They perform no initialization of that memory. Calls to NiMalloc and NiRealloc must be paired with calls to NiFree for deallocation to occur properly. Similarly, calls to NiAlignedMalloc and NiAlignedRealloc must be paired with calls to NiAlignedFree for deallocation to occur properly.


Gamebryo

If an application does not use these allocation routines, the memory will not be tracked or managed by Gamebryo. This can cause a mismatch if the memory was allocated externally and then freed by Gamebryo routines. Please see Memory Management Troubleshooting for more details on common memory management issues.

The routines NiAlloc, NiMalloc, NiFree, etc are actually macros that call internal versions of these functions. The macro allows the engine to generate file, line, function information automatically in memory tracking builds.

 

NiMemObject, NiNew, and NiDelete

Objects requiring constructors and destructors in Gamebryo are allocated using NiNew and NiDelete and must be derived from a common base class, NiMemObject. These macros, like NiAlloc,  NiFree, and others listed above encapsulate the need to store the file, line, and function information for memory tracking.

NiMemObject overrides the global new and delete on a class level. All derived classes will inherit these allocation overrides. Note that inheriting from NiMemObject requires no additional per-object memory overhead.  Additionally, NiMemObject overrides new[] and delete[] on a class level. The only overhead for array allocations is a few bytes that the compiler generates in order to call the destructor for each element in the array. Most objects will have this data generated automatically, so the overhead should not be a concern.

Labels: 静态对象, 内存管理
2008-06-03

获取当前系统流逝时间 NiGetCurrentTimeInSec() 从名字可以看出是秒
Labels: 系统时间
弄到了一个 Gamebryo for cegui  的render. 本来还想要写的,现在省事了。支持unicode 的NiFont 也搞定了
下载战锤OL 看看资源是否能用.还有没开发出来 
2008-06-01

#define NiSmartPointer(classname) class classname; typedef NiPointer<classname> classname##Ptr
设置某个类型的智能指针变量p,classname 必须从NiRefObject 继承而来,p 需要用 NiNew 赋值.
当赋值NULL 给 p 时,p 自动删除。
NiImageConverter::SetImageConverter(NiNew NiDevImageConverter);
设置图形转换接口,设置之后才能实现纹理的读取和转换
NiDevImageConverter 支持标准像素格式和部分非标准格式之间的转换

The NiDevImageConverter supports the following formats for ReadImageFileInfo and ReadImageFile:

  • Windows BMP – see the NiBMPReader documentation for details.

  • Gamebryo NIF – see the NiNIFImageReader documentation for details.

  • SGI's INT, INTA, RGB, RGBA – see the NiSGIReader documentation for details.

  • Truevision Targa TGA – see the NiTGAReader documentation for details.

  • DirectX Compressed Textures, DDS – see the NiDDSReader documentation for details. Note that this format is Win32-specific.

Valid Format Conversions

The NiDevImageConverter functions ConvertPixelData and ConvertPixelDataFormat are capable of converting among the following formats. Note that PAL8, PALA8, RGB24, RGBA32, BUMP16, BUMPLUMA32, all refer to the NiPixelFormat-scoped standard format static objects of the same name, and DXT1, DXT3, DXT5 refer to the compressed formats:

Source Formats

Valid Destination Formats

RGB24, RGBA32

Any 16 or 32-bit RGB, RGBA, BUMP, or BUMPLUMA format RGB24 or 24-bit BGR (in that order)

PAL8, PALA8

PALA8, PAL8 Any 16 or 32-bit RGB or RGBA format RGB24 or 24-bit BGR (in that order)

BUMP16, BUMPLUMA32

Any 16 or 32-bit BUMP or BUMPLUMA format

DXT1, DXT3, DXT5

Any 16 or 32-bit RGB or RGBA format RGB24 or 24-bit BGR (in that order)

Any 16 or 32-bit RGB or RGBA format

RGB24, RGBA32

24-bit BGR (in that order)

RGB24, RGBA32

gamebryo  标准像素格式见:
NiPixelFormat 文档

Labels: NiDevImageConverter
场景管理器和摄像机使用之前必须使用Update函数初始化
    m_spScene->Update(0.0f);
    m_spScene->UpdateProperties();
    m_spScene->UpdateEffects();
    m_spCamera->Update(0.0f);

注意Update 不包含 UpdateProperties 、UpdateEffects 功能必须分开调用。 
 
 Calls Update on the list of properties attached to the object. Predecessors of Gamebryo updated the properties each time Update was called, but since the properties do not necessarily change each frame, updating properties is not necessary all the time. This function should be called at or above an object after any properties are attached or detached (but not if only the values in a property attached to the object are changed) or when the object's parent is attached or detached. See the "Notes" below for a discussion of Update, correctness, and efficiency. Also, see the programming manual for a detailed discussion of the  UpdateProperties call.
调用UpdateProperties() 或者 UpdateEffects() 当初始化时,或者一个properties attachec 到对象上,或者从对象 detached

Gamebryo Update Slowdowns
The Update function in Gamebryo performs a variety of tasks and is often a source of slowdown for developers. Understanding what Update does can help you optimize around some of the more expensive operations. This document outlines some of the things you can do to speed up Update.
GameBryo 中的 Update执行各种任务对于开发者来说通常是效率低下的原因,理解Update做什么有利于优化昂贵的操作。

What does Update do?
At it's core, Update prepares the scene graph for rendering. However, Update performs several operations during this process such as updating the transforms on NiAVObject based classes, updating NiTimeController objects and updating the bounds on objects. Because of this, Update can become a very expensive function call and should be used only where necessary. Listed below are several ways to optimize calls to Update.

Update 做什么
作为核心,Update 为图形场景渲染做准备,在这期间Update执行几个操作,如更新NiAVObject对象的变换操作,更新NiTimeController对象,更新对象的包围盒。因此Update是一个非常昂贵的操作,只有在需要的时候才调用,下面有几种操作优化对Update的调用

Don't Call Update
It doesn't make much sense at first, but the fastest way to speed up a call to Update is not to call it. Update handles changes to transforms, bounds, and time controllers. If some subsection of your scene graph never has any of these changes, consider updating it separately from the dynamic portion of your scene graph. In general, this means that scenery in a game that never moves and has no animations can be updated once and rendered every frame from a new camera angle. Separate your scene graph into static and dynamic components. Update the static component once and update the dynamic component as needed.
分离场景成为动态和静态组成2个部分,只更新静态部件1次,根据需要更新动态部件

Use UpdateSelected
UpdateSelected is a variant on Update that tries to avoid expensive calculations when they are unnecessary. For example, UpdateSelected may skip the work of updating transforms if there are no NiTimeController objects attached that could change the transform. Assets exported from the art plugins should already be configured for use with UpdateSelected. In general, using UpdateSelected will give some but not all of the benefits of segmenting a scene graph into components and updating only the dynamic components as suggested in the "Don't Call Update" section. It is also important to note that if every NiAVObject in a hierarchy is animated such as a character with skeletal animation, UpdateSelected can sometimes actually be more expensive than Update since it must perform branching operations based off of the data for each object.

UpdateSelected 可以检测一个物体变换矩阵是否改变,未变则不执行update,这样可以提高性能,适合场景图形。但对于人物模型不太适合,因为对于人物动画或者骨骼动画,UpdateSelected 可能浪费性能。所有这个函数适合场景。而骨骼动画,mesh最好不要attach 到场景上,作为单独单元存在

Simplify the Scene Graph Hierarchy
Every node inserted into the scene graph costs some CPU time to update. Removing unnecessary nodes can increase the speed of Update operations. By default, the optimization plugin tries to do this coming out of the art packages. If there are NiNode objects in a scene graph that only serve to hold a name and a single child, they can easily be removed by pushing the name and the transform down to that child.

Use Linear Animation Keys
There are several types of animation keys in the Gamebryo animation system, but linear keys are the simplest to interpolate between and take the least amount of CPU time. If possible, consider exporting art with linear keys to increase performance.

Use Fewer Bones
Characters with skeletal animation often represent the most expensive portion of a scene graph because each NiNode represents a bone that has to be animated and then updated correctly. Consider reducing the number of bones in a character either permanently in the art package or dynamically using the Bone LOD system. The Bone LOD system allows you to turn off animation of subtrees which will decrease the amount of time needed in Update. Bone LOD is further discussed in the NiAnimation documents for NiBoneLODController and documents for the 3ds max and Maya plugins.

 
 

Gamebryo 采用右手坐标系系统.
没有要求那个轴一定向上,尽管NiCamera 默认Y轴向上.
NiMatrix3 旋转为顺时针为正方向,当由正轴看向原点时。变换矩阵为列向量
NiQuaternion 当由正轴看向原点时,绕轴旋转逆时针为正。
Labels: 坐标系, NiMatrix3, NiQuaternion, 旋转
图形场景管理中NiNode的子节点,并不一定是NiNode的子类型。NiAVObject 才是图形场景对象中的基类,如下为其继承关系。但场景管理有NiNode负责。子节点可以是NiAVObject 子类
。可以通过名称查找一个NiNode节点GetObjectByName()

NiAVObject
      NiCamera
      NiDynamicEffect
            NiLight
                  NiAmbientLight
                  NiDirectionalLight
                  NiPointLight
                        NiSpotLight
            NiTextureEffect
      NiGeometry
            NiLines
            NiParticles
                  NiParticleMeshes
            NiTriBasedGeom
                  NiTriShape
                  NiTriStrips
      NiNode
            NiBillboardNode
            NiBSPNode
            NiSortAdjustNode
            NiSwitchNode
                  NiLODNode
Labels: NiNode
NiStream 对gamebryo 内在的文件格式提供流支持,用来从磁盘加载场景图形和其他 gamebryo 对象或者保存到磁盘,还可以从内存加载gamebryo 对象。
主要有一个函数 RemoveAllObjects() 这个需要注意。当NiStream在NiShutDown() 之前析构则不需要调用这个函数。因为NiStream析构函数中调用了这个函数,如果在NiShutDown()之后析构,则需要主动调用RemoveAllObjects().防止因为引用计数错误,NiShutDown() 调用时会触发断言。主动调用这个函数只在几个例子中存在
Labels: NiStream, RemoveAllObjects
2008-05-31

NiColor   r 、g、b 三种颜色
NiColorA r、g、b、a 四种颜色
也可以用来作为矢量,如height map 之类纹理中存放的并不是颜色。
Labels: NiColor, NiColorA
NiCamera对象代表场景中的摄像机,
NiCameraPtr spCamera = NiNew NiCamera;
spCamera->SetTranslate(-100.0f, 0.0f, 0.0f);          //设置摄像机位置
NiMatrix3 mat;
mat.MakeXRotation(-NI_PI/2);                              //逆时针旋转90度
spCamera->SetRotate(mat);                                //设置摄像机旋转
//设置视截体左右视角30度。上下长度与左右长度对比为 3/4 ,宽屏可以设16/9 或者 16/10 之类,1.近裁切面,1000远裁切面。最后bool表示透视投影矩阵还是正交投影矩阵
NiFrustum kFrustum(-0.25f, 0.25, 0.1875f, -0.1875f, 1.0f, 1000.0f);   //
//视口范围
NiRect<float> kPort(0.0f, 1.0f, 1.0f, 0.0f);                                         //
//设置投影矩阵
spCamera->SetViewFrustum(kFrustum);             //
//设置视口范围
spCamera->SetViewPort(kPort); 
 

camera

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

投影面中点(观察点)是摄像机模型空间中心点

投影面垂直于摄像机模型空间x轴方向.默认情况:
NiCamera 模型空间Y方向作为上方向, NiCamera 模型方向Z方向作为右方向
  一般导出的场景里面有摄像机的设置。而这个设置并不一定要和默认设置相同。
 

frustum

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
//设置视截体,Ortho 为false设置透视投影,为true 设置平行投影
构建视截体结构
NiFrustum (float vl, float vr, float vt, float vb, float vn, float vf, bool bOrtho = false)
输入参数代表不同的矢量 vectors <1,0,vl> (左边), <1,0,vr> (右边), <1,vb,0> (下边), and <1,vt,0> (上边). 组合成可视矩形
The final two values ( vf , vn )
Labels: NiCamera, NiFrustum
NiWireframeProperty 画几何体时为应用程序提供线框模式和实体模式之间切换的功能。
默认构造的对象不使用线框模式。
//设置使用线框模式。设置之后画的物体都采用线框模式。
void SetWireframe(bool bWireframe)
由于很多平台使用线框模式时性能会急剧下降,主要用来debug 和 工具目的。

spScene->AttachProperty(gs_spWireframe);
Labels: NiWireframeProperty
2008-05-30

NiRenderedTexture 负责创建 RenderTarget 对象.  其纹理对象内容由renderer对象渲染场景时动态产生
m_spRenderer 为NiApplication 中的 NiRenderer 成员变量
//输入纹理的宽度、高度和渲染对象来产生一个NiRenderedTexture 对象
m_spTexture = NiRenderedTexture::Create(256,256, m_spRenderer); 
//还需要创建render target group 。 负责维护 z-buffer 和 模板
//最后2个参数为模板设置标志
m_spRenderTargetGroup = NiRenderTargetGroup::Create(m_spTexture->GetBuffer(), m_spRenderer, true, true);
 //渲染rendertarget流程
 m_spRenderer->BeginUsingRenderTargetGroup(m_spRenderTargetGroup, NiRenderer::CLEAR_ALL);
 NiDrawScene(m_spExtraCamera, m_spMainScene, m_kCuller);
 m_spRenderer->EndUsingRenderTargetGroup();
........
 m_spExtraCamera = FindCamera(pkHeli);   //为模型上的摄像机.

 NiCullingProcess m_kCuller
Labels: NiRenderedTexture
gamebryo  Object System 对象系统

                           NiMemObject
                                    |
                                     |


NiMemObject 负责处理全局new 和 delete 操作符,所有从其派生的类从NiMemManager 对象分配和回收内存。在外部必须使用NiNew 和NiDelete 来操作,而不能使用new 和 delete

NiRefObject – 支持引用计数和智能指针.所有NiRefObject的派生的Gamebryo对象都支持引用计数。这就是说这些对象存储了对其引用的次数。在编程的时候必须声明一个引用来引用这样的对象,并且在使用完这个对象的时候释放掉这些引用。在这样的系统中,对象会在最后一个引用被释放的时候(即:引用计数为零)删除自身。手工操作引用计数系统的时候可能会有些繁琐——Gamebryo通过使用所谓的“智能指针”来避免这些繁琐。
需要注意的是,像NiRefOjbect子类的引用技术类型的实例必须在堆上使用new分配,而不能作为静态对象或者栈对象(局部变量)。这是因为在NiRefObject的引用技术降为零的时候,对象将会被删除——删除一个栈对象或静态对象将导致内存故障和崩溃。由于Gamebryo内存管理系统的存在,要使用NiNew来分配内存。
智能指针可以设置为静态的,但在应用程序退出前必须设置他为NULL.
永远不要对一个NiRefObject对象指针(无论是智能指针还是普通的指针)作delete操作,这将永久摧毁这个对象。

对于gamebryo 大部分类都从NiObject 派生而来:
NiObject 支持对象的引用计数来安全的释放对象以及运行时类型信息来安全的向下转换指针。
NiAvObject 主要负责图形对象的旋转、缩放、平移等操作,在库中所有可见到或可听到的场景对象都从NiAVObject派生而来。
NiOjbectNET(丛NiObject派生)-支持名字、额外的数据、以及时间控制器。

Labels: object system, NiAVObject
GameBryo 游戏引擎特性说明:
 

Gamebryo 支持mmorpg fps 类型游戏。即同时支持 室内场景渲染(主要可能是mesh + protal)和室外场景渲染,对于目前工具来讲,能更好的支持室内环境。对于室外地形还不是太好。可能2.5的地形编辑器能提高这部分的能力

优点:,
1
面向对象设计、插件式结构,场景图体系表示,和主流的3D建模工具集成,强大的艺术工具链集成,有效的可视对象裁减,在所有平台上支持高级的3D硬件加速,高端的纹理贴图和渲染效果
动态碰撞检测,支持3D音效,Level-of-detail 表示,灵活的渲染、排序、裁减方法
分为NiApplication Corelib 两部分
corelib
负责图形渲染功能,图形方面基本拥有流行商业引擎的全部功能。部分特性如下:
Lighting
Per-vertex, Per-pixel, Gloss maps

ShadowsShadow Mapping 

Texturing Basic, Multi-texturing, Bumpmapping, Mipmapping, Projected

Shaders:  Vertex, Pixel, High Level.支持 rendermonkey,cgfx,HLSL
Scene Management
General, Portals, Occlusion Culling, PVS, LOD

AnimationIK, Forward Kinematics, 关键帧动画, 骨骼动画, Animation Blending

Meshes Mesh Loading, Skinning, Progressive: • Level of detail, including Bone LODs

Special Effects Environment: Mapping, Lens Flares, Billboarding, Particle System, Sky, Fire, Explosion, Decals, Fog:  Environment maps (spherical environment maps are supported on all platforms, with cubic environment maps supported on DX8 and Xbox).

Rendering Fixed-function, Render-to-Texture

NiApplication
官方建议由开发人员修改来改善性能,相当于主工程。封装了 Winmain 消息处理函数,以及FPS 控制,输入输出控制、游标、实体等功能
而客户端、服务器逻辑可以制作成dll, 由主工程调用。
2
支持的第三方工具
Audio:Miles,Sensaura,FMOD,wwise(这个有辅助工具)
Video:bink,Smacker

AI: AI Implant
Networking:butterfly.net,quazal
Physics:
physx
Trees:Speedtree    这个可能需要另外花钱
Facial Animation: OC3 Impersonator

3
拥有线程安全的内存分配跟踪管理系统、RTTI 动态类型识别、profile 性能测试。运行时刻性能分析工具,渲染每个对象的时间,每个对象渲染的三角形数据,内存使用分析。后台多线程资源读取,不影响前台的渲染流程。

4 支持众多平台,而且源码开放,有简单疑惑的地方可能通过阅读部分源码及时解决。

缺点:
Gamebryo 2.5
才有地形编辑器,工具还不算特别完善。
没有脚本、 UI 系统(有共享的cegui gamebryo render)
无网络系统,不知道对 butterfly.net quazal 支持度有多高
中文、英文资料都相对较少。
不支持中文文字,需要修改 Font 工具。论坛有修改的NiFont

拥有简单的renderstate 切换控制,初始化设置了系统默认的属性,可以不考虑。因为Reset时需要这样设置
(角色扮演)游戏《上古卷轴3》和网络游戏《卡米洛特的黑暗年代》都使用了NetImmerse引擎,
而且这些资源都是不打包的。只是有部分修改
Labels: 引擎特性
 NiScreenTexture 实现屏幕2D贴图. quake 的 HUD. ogre 的 overlay 都是这个概念。以像素为精度。可以制作游标, "Heads-up display" 指示器, dials, gauges, text, 
 and other overlay objects. NiScreenTexture 不支持多纹理和shader.动态光。没有深度值.
 NiSourceTexture 负责加载纹理贴图。调用静态函数 NiSourceTexture::Create 来创建纹理对象
 NiSourceTexture* pkTexture = NiSourceTexture::Create(NiApplication::ConvertMediaFilename("emergentlogo.tga"));
 //创建屏幕HUD
 NiScreenTexture* pkScreenTexture = NiNew NiScreenTexture(pkTexture);
 屏幕以左上角为原点设置显示区域的位置x,y , 宽度和长度。 (注意这个是显示区域,不会影响纹理造成拉伸)纹理坐标位置(注意这个也是像素级的),
 最后参数是纹理反射光颜色,默认为白色
 NiScreenTexture::AddNewScreenRect(32, 32,pkTexture->GetWidth(), pkTexture->GetHeight(), 0, 0); 
 //添加NiScreenTexture对象到纹理管理类中,这样NiScreenTexture才能显示出来:
 m_kScreenTextures.Add(pkScreenTexture);   

据内部消息,这个类在新版本中被废弃了。
对于游标用NiCursor 而不是这个类
Labels: NiScreenTexture
2008-05-29

使用NiTransform 类做矩阵变换操作。因为为了加速计算没有使用 4*4 矩阵。是 3*3 矩阵表示旋转、中心点矢量表示旋转半径、目标矢量表示平移
的目标、缩放矢量表示缩放大小
Gamebryo 使用右手坐标系,这样和3dmax坐标系是相同的,而坐标系的y朝上还是z朝上是无所谓的。大不了设置的view 视图变化一下就可以了。
使用的是矩阵列向量。对一个矢量点进行变化。 T(变换矩阵) * V (矢量) 而且变换顺序和行向量是相反的。如 旋转 A 移动到 B 缩放 C
行向量变化为 V * A * B * C 
列向量则为 C * B * A * V
右手坐标系:由负端看向正端:顺时针旋转为正,逆时针旋转为负
Labels: 行向量, 列向量, 坐标系
NiAVObject 场景图形内所有对象必须继承的基类 。维护本地或世界坐标的变换矩阵
NiAVObject的->SetTranslate() 用来设置平移矩阵
SetRotation() 用来设置旋转矩阵
Labels: NiAVObject
 运行时类型信息
基于几个底层的管理类Gamebryo设计成一个类的层次结构。下面的图展示了从NiObject派生的类的一个类层次结构的小子集。
以NiObject作为根节点的Gamebryo对象使用单继承的方式编写。这样NiObject的子类形成了一个类型树(注意这是类型之间的关系树不是指对象实例之间的关系)。运行时类型信息(RTTI)系统使得应用程序可以快速判断任何NiObject或其子类的直接类型或祖先类型
RTTI支持三个基本的操作:
    1.判断一个对象的是不是严格的指定类型
    2.判断一个对象是不是一个指定类型的派生类
    3.动态转换一个类对象的指针到派生类的指针

所有的NiObject 派生类必须使用NiDeclareRTTI宏来定义静态RTTI 数据成员。  用来在运行时刻检测类类型。要实现动态类型识别非常简单,只需类似如下操作
因为c++开启运行时刻类型识别是非常浪费效率的行为,不是一个商业程序应该做的。而很多库都提供了自己的类型识别。Gamebryo 也提供了这样一个快速的
类型检测类型。几乎所有的类都是从其派生的
// NiNewClass.h
class NiNewClass : public NiAVObject 
{
    NiDeclareRTTI;
    // <other stuff>
};

// NiNewClass.cpp
NiImplementRTTI(NiNewClass, NiAVObject);

常用函数:
  NiIsKindOf           判断类对象是否是一个类型或者该类型的父类型
  NiIsExactKindOf      判断一个类对象是否为某种类型。但不包含其父类型 
  NiDynamicCast        动态转换一个类为其原类型或者父类型
示例:
NiNode* pkNode = NiNew NiNode;
bool bResult;
bResult = NiIsExactKindOf(NiNode, pkNode);     // bResult is true
bResult = NiIsExactKindOf(NiAVObject, pkNode); // bResult is false
bResult = NiIsKindOf(NiAVObject, pkNode);      // bResult is true
bResult = NiIsKindOf(NiSwitchNode, pkNode);    // bResult is false
 
NiObject* pkObject = pkNode;
NiAVObject* pkDynAVObj = NiDynamicCast(NiAVObject, pkObject);   // pkDynAVObj == pkNode
NiNode* pkDynNode = NiDynamicCast(NiNode, pkObject);            // pkDynNode == pkNode
NiSwitchNode* pkDynSw = NiDynamicCast(NiSwitchNode, pkObject);  // pkDynSw == 0

 应该避免类似下面的代码:
void Function(NiAVObject* pkObject)
{
    if (NiIsKindOf(NiNode, pkObject))
    {
        NiNode* pkNode = NiDynamicCast(NiNode, pkObject);
        // do something with pkNode
    }
}

NiDynamicCast 判断转换是否安全实质上重复了NiIsKindOf的工作。在NiIsKingOf已经判断对象是确定的类型时,静态转换到这个类型就是安全的。上面函数更好的写法如下:
void Function(NiAVObject* pkObject)
{
    if (NiIsKindOf(NiNode, pkObject))
    {
        NiNode* pkNode = (NiNode*) pkObject;
        // do something with pkNode
    }
}
The following code shows how NiObject is set up and how derived classes are set up.

// NiObject.h

class NiObject : public NiRefObject
{
    NiDeclareRootRTTI(NiObject);
    // <other NiObject stuff goes here>
};

 

// NiObject.cpp

NiImplementRootRTTI(NiObject);

 

// NiObjectNET.h

class NiObjectNET : public NiObject
{
    NiDeclareRTTI;
    // <other NiObjectNET stuff goes here>
};

 

// NiObjectNET.cpp

NiImplementRTTI(NiObjectNET, NiObject);

 

// NiAVObject.h

class NiAVObject : public NiObjectNET 
{
    NiDeclareRTTI;
    // <other stuff>
};
 
// NiAVObject.cpp
NiImplementRTTI(NiAVObject, NiObjectNET);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Labels: NiDeclareRTTI, RTTI
NiTimeConTroller  时间控制器基类。必须实现纯虚函数:
virtual bool TargetIsRequiredType () const; 用来诊断目标是否是自己想要的类型。
virtual void Update(float fTime);   按照流逝时间来更新目标对象
使用SetTarget 来设置需要时间控制器的目标对象。由Target目标对象负责回收NiTimeConTroller 内存
 
Labels: NiTimeConTroller
NiTransformController 是gamebryo提供的时间控制器。一般用来实现点光源或者摄像机来跟踪一个角色。提供随时间变化的变换操作 。需要一个interpolator 对象来负责管理如何进行变换操作
Labels: NiTransformController
NiLookAtInterpolator 旋转一个对象使其一只面向另一个对象,一般用来参数1 指定对象的点,2指定旋转轴x、y、z,3 是否翻转(即看向完全相反的方向) 
2.3 似乎参数2为看向的方向作为什么轴。这样原来是教程6中的z轴变成了x轴。默认为x轴
Labels: NiLookAtInterpolator
NiInputKeyboard 使用dinput 来处理键盘输入消息。属于Application 工程范畴。 获取方法
NiApplication 对象调用 GetInputSystem()->GetKeyboard()
获取键盘输入:
NiInputKeyboard::KeyIsDown(NiInputKeyboard::KEY_LEFT)  //判断左方向键是否按下
Labels: NiInputKeyboard
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值