NiAnimationConstants::GetEndTextKey() 返回字符串 "end"
NiActorManager::TEXT_KEY_EVENT,
m_spActorManager->GetTargetAnimation(),
NiAnimationConstants::GetEndTextKey());
NiActorManager::END_OF_SEQUENCE,
m_spActorManager->GetTargetAnimation(),kTextKey);
void HidePointer();
void ShowPointer();
NiGeometryData::STATIC |
The data never changes. |
NiGeometryData::MUTABLE |
The data changes infrequently. |
NiGeometryData::VOLATILE |
The data changes every frame. |
似乎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.
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.)
场景图形基础
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经过特化或者扩展的子类
一个场景图可以包含0个或者更多孩子,应用程序可以有人一个场景图。树叶代表几何图形对象,而其他内在的节点负责场景图的组织和维护。NiAVObject 基类自己并不支持子树的概念,代替的是使用NiNode类和它的子类
注意不要弄混场景几何体父子层次和gamebryo类派生层次。这是2个完全独立的概念。场景图中NiNode的孩子不一定就是NiNode的子类
变换和坐标系
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.
协定
没有要求那个轴一定向上,尽管NiCamera 默认Y轴向上.
NiMatrix3 旋转为顺时针为正方向,当由正轴看向原点时。变换矩阵为列向量
NiQuaternion 当由正轴看向原点时,绕轴旋转逆时针为正。
相对于世界空间变换每个NiAVObject 都有自己的模型空间,所有NiAVObject的直接孩子都定义在其父坐标系中。这样组织形成了坐标系继承关系。对于关节和许多对象表示都很有用。(骨骼动画组织方式就是这样。父坐标改变才能影响子坐标)
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) |
注意这三种变换并没有存放成3个分离的矩阵,而是本着占用空间尽可能少的原则。一个3×3矩阵代表旋转,一个矢量代表平移,一个标量代表缩放
这组变换包含三个截然不同的坐标系:模型坐标行。
所以点变换如下
vL = [ OT OR OS ] vM
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.
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.
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.
抽象类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
NiTextureEffect
抽象类NiTextureEffect用来创建纹理效果. 这些效果比较显著和吸引眼球。效果包括复杂的聚光灯、幻灯片效果、阴影、云、雾。这些在Texturing Basics里面有详细描述。
NiGeometry
NiGeometry 对象用顶点坐标、法线、顶点颜色、纹理坐标来描述几何图形数据。NiGeometry 是一个抽象类因为他不包含任何顶点被组织到渲染对象的信息
NiLines
NiLines 对象添加顶点颜色和纹理坐标到NiGeoMetry对象数据中。用来表示线段的概念,NiLines 还包含一个Boolean数组用来表示是否每对邻接点连接成为一个线段
NiTriBasedGeom
NiTriBasedGeom 对象为几何体表示添加三角形的概念。所有NiTriBasedGeom子类使用三角形来渲染。NiTriBasedGeom 是一个抽象类因为他不包含顶点如何组织成三角形的信息
注意gamebryo中所有的三角形都是单边逆时针导向的
NiParticles
更新场景图几何数据
应用程序可以改变一个节点的的本地变换。计算节点的世界变化以及其子孙的变换知道应用程序调用update时才执行
update 执行过程:它沿子图进行深度优先访问,计算世界变换矩阵和包围球,因子最小化可视节点的数量。在更新完矩阵之后。沿着递归调用返回,更新世界包围球
总的来说,递归一个路径时变换操作被更新,而返回时包围球被更新
通常世界中大部分对象并不移动,所以更新至限制在少数移动的对象上面。为了初始化场景图处理。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
O 从一个父节点(直接父节点不是祖父节点等等)attached 或者 detached
O 有一个子节点 attached 或者 detached (直系子节点而不是孙节点)
任何O的变换矩阵被改变
注意任何在父节点或者祖节点的Update调用,可以代替对象自己的Update调用。例如一个对象A attach 子B 和 C,然后调用A->Update即可。不需要对三个对象调用Update操作,应用程序调用Update时能执行批次更新
例如:如果一个应用程序改变了有关节的角色所有连接点变换矩阵,他应该推迟update的调用知道所有改变完成。可以在角色的root节点调用一次Update即可
但是,注意在场景图中Update应该尽量少调用。仅仅因为一个叶节点变化每帧都在场景图上调用Update将会降低性能
Cloning是产生对象的拷贝的一种方法。应用程序调用下面的的函数来克隆对象。第一个函数使用缺省值来克隆对象名称,这在后面讨论。第二个版本允许通过NiClonigProcess来实现局部控制,这是为多线程情况下设计的函数。
NiObject* NiObject::Clone();
NiObject* NiObject::Clone(NiCloningProcess& kCloning);
为了得到一个对象的一个彻底的深拷贝可以使用
NiObjectPtr NiObject::CreateDeepCopy
这个调用使用流系统将对象保存到一个内存块中,然后加载这个内存快到一个新的对象。请小心使用深拷贝。有大量模型数据和纹理关联的对象应该尽可能使用共享数据。深拷贝不共享任何的东西。
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来访问。
多线程时的克隆
NiCloningProcess kCloning;
kCloning.m_eCopyType = NiObjectNET::COPY_EXACT;
kCloning.m_cAppendChar = '%';
NiObject* pkClone = pkNode->Clone(kCloning);
Names
类NiObjectNET 支持字符串名字来鉴别对象,下面的函数用来访问名字
void SetName(const NiFixedString& kName);
const NiFixedString& GetName() const;
SetName increments the reference to kName.
NiAVObject::GetObjectByName 用来递归访问场景图来查找拥有指定名字的对象。函数如下:
NiAVObject* GetObjectByName(const NiFixedString& kName);
注意:当我们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。
字符串映射
NiTStringMap和NiTStringPointerMap对象在某种程度上功能上类似于NiTMap和NiTPointerMap对象,但是它们接受字符串作为键并使用字符串比较作为键哈希。
FixedStringMap
固定字符串映射
NiTFixedStringMap对象的功能在某种程度上类似于NiTMap对象,但它接受NiFixedString对象作为键。
Queue
队列
NiTQueue为几乎任何类型的对象实现一个先进先出(FIFO)的队列。但不支持智能指针。
NiTSet为几乎任何类型的对象实现一个无序的集合。但不支持智能指针。对于基本类型(char*,float,int等)请使用NiTPrimitiveSet。对于NiMemObject派生的对象请使用NiTObjectSet。对于对象的智能指针请使用NiTObjectPtrSet和NiPrimitivePtrSet,它们能正确地处理引用计数。
内存池
NiTPool实现小对象的内存池。使得应用程序可以一次分配大量小对象并通过内存池重用它们,而不是单个地分配和释放小对象。
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; |
|