Betajaen’s shortguide to NxOgre

Betajaen的NxOgre简短教程——宝爷译

Alpha and Omega — A bit of everything

整个世界中的所有东西

 

World就像我们的宇宙,漫无边际而且只有唯一的一个。我们在world里面的东西叫做Scene,它们是有大小的。Scene和Scene之间不会有交集

The World is like our universe, it’s infinite in size and there can be only one of them.Inside the world we have things called a Scene. They could be considered like dimensions in our world, we inhabit one dimension and ghosts and monsters inhabit another. Things in one scene cannot interact with things with another.

在场景中,所有的物体都有精确单元大小的RigidBodies,就像一支铅笔,一具尸体,一匹马,一个油桶

Inside the scenes is the matter itself, it is divided into units or RigidBodies such as a pencil, a corpse, a house or a oil canister.

RigidBodies有四种类型,Actor,KinematicActor,SceneGeometry,Volume这四种类型。每一种类型都是基于一些函数来进行与其他各种对象的动态碰撞检测,在这一点上,我们可以把他们当作同一个东西。每一个RigidBody 都是由一个或者多个形状Shapes组成的。当一个RigidBody 的Shapes和另一个RigidBody 的Shapes碰撞的时候,我们需要通过它的Material属性来知道它们碰撞之后会产生怎样的效果。

There are four types of RigidBodies; An Actor, a KinematicActor,SceneGeometry and a Volume, each different type is based on the method of movement it has and how it interacts with each other. But for now; let’s just call treat them as one.

Each RigidBody is made from one or more Shapes. When a shape collides with another shape from another RigidBody, it’ll need to know how to react properly this defined by a few properties called a Material.

The World and a fitting Description of it — The infamous ’Verse

World和对它的恰当描述——无名的诗

 

上帝说World* mWorld = World::createWorld(),World在NxOgre中属于最顶层类了,它负责处理所有的场景Scenes,并间接地做一些其他工作,是一个单例类Singletons,通常,第一个创建的就是World,而最后一个销毁的也是它。当我们创建一个World的时候,我们一般会给他一个Description对象,用来描述一些信息,例如它是哪一种冰淇淋,它喜欢什么颜色,像这些东西。我们把Description传递给World以及其他的一些类用来描述相关信息,例如Scene,Actor等。每种类都有相应的Description对象

The World is the top-most class of NxOgre; it is responsible for handling of all the Scenes and indirectly working with it’s friends; the Singletons. World is normally the first to be created, and most always the last destroyed.

When we create the World, we normally give it a Description. A bit like a mug shot; What kind of  ice-cream it likes?, What’s it’s favourite colour?, Where it get’s hair done?, things like that. We give the description to the World or any other class that likes descriptions for it to read and pretend to be that class you stole the description from.

WorldDescription description;  description.mNoHardware = true;  World* mWorld = World::createWorld(description);

At this point, World seems very boring. Because it is, it’s always out there but there are more important things in life. So lets move on, to time!

Father Time — Controlling time with your time machine

时光老人——用你的时间机器来控制时间

TimeController 负责时间的控制,它控制事件的发生,它控制事件的起因和结果,他就是你!因为时间是一个非常奇怪的东西(如果我们没有它可能会更好,个人观点),所有东西都需要在一个时间维度之中,他们需要继承TimeListener对象

TimeController is the second one in charge, he makes things happen, he makes the whole cause and event thing go, he’s the man.

TimeController* mTimeController = mWorld->getTimeController();

Because Time is a strange thing (and personally I think we would do better without it), anything that needs to be in the time dimension must be a TimeListener. We can do that by inheriting from the TimeListener class;

class myClock : public TimeListener {   bool advance(const TimeStep& step, const Enums::Priority&) {    std::cout << "My word! " << step.mActual << " seconds have passed.\n";   }  };
在BloodyMess中,很多对象都是TimeListener,例如Scene,一些单例,Renderables,甚至World!通过TimeController的advance函数来施展我们的时间魔法,让时间前进。

Lot’s of things in Bloody Mess are TimeListeners; Scenes, some Singletons, Renderables, even the World – although you ask him about it, he’ll deny everything.

With our now time controlling superpowers we can exercise our will to advance time forward as much as we want, as many times as we like!

TimeController* mr_timey_wimey = TimeController::getSingleton();  mr_timey_wimey->advance(100.0f);

With the universe advanced 100 seconds into the future and we did not age a day, our quest for being an evil mastermind is coming to an end.

The Singletons — Download all six seasons for $29.95!

单例用29.95美元来下载六个季节?

Singletons 是NxOgre的手下,是好人,不是坏人。这里总共有5个Singletons,尽管第五个家伙没有在下面这张图片中显示出来。他们是ErrorStream,TimeController,ResourceSystem,MeshManager以及HeightFieldManager。虽然他们是World的手下,但他们可以在World创建之前被创建。以及在World销毁之后再销毁。单例对象可以在任何地方被调用。

The Singletons are the underlings of NxOgre, not the bad underlings kind, the good ones really. Well, almost. There are five singletons; although the isn’t fifth not shown (He joined us in season 3, and I couldn’t find a more recent screengrab).

They are; ErrorStreamTimeControllerResourceSystemMeshManager and HeightFieldManager. I’ll let you guess who’s the one in pink.

Although they are the underlings of the World, they can be created before the world, and after the world has perished – If your evil bidding desires it.

World::precreateSingletons();        //预创建单例 World* mWorld* = World::createWorld();      //创建世界 World::destroyWorld(false);         //销毁世界 World::destroySingletons();           //销毁单例

Singletons can be accessed any where, and there is only one of their kind – sadly.

ErrorStream::getSingleton()->throwAssertion("I've broken it!!!", __FILE__, __LINE__);

The ResourceSystem — Gather ye resources

The greatest achievement of the human spirit is to live up to one’s opportunities and make the most of one’s resources. — Vauvenargues

资源系统——聚集所有资源

我们开始ResourceSystem这一课,它是一个单例类,用于管理World的外部资源,例如纹理,模型和高位图。一些简单的文本文件也可以被使用。ResourceSystem是一个大懒虫,它从来不上学,也不去了解不同的文件类型,操作系统结构….但他有很多朋友。调用ResourceProtocol来处理ResourceSystem的资源。FileResourceProtocol和MemoryResourceProtocol你可能永远都不会看到它们,因为它们是不可见而且娇羞的。我们说的这些ResourceProtocol调用UniformResourceIdentifier像跳着原始舞蹈一样快速地展示他们自己。打开他们装满好东西的魔法包或者打开你的Archive,给出你的文件名和路径,然后调用openArchive打开它们,开始我们的舞蹈~。

We start our lesson with the ResourceSystem. A singleton designed to handle any external resources to our world. Meshes or Heightfields are commonly used with the ResourceSystem, but other less complicated files such as text files can be used – if you so wish.

ResourceSystem* sparky = ResourceSystem::getSingleton();

The ResourceSystem is typically a very lazy creature, it never went to school and read about different file types, operating system structures or the exact placement of a block header should be. Instead the ResourceSystem has lots of friends calledResourceProtocols which the ResourceSystem has bribed them to handle any resources for him.

Two examples are the FileResourceProtocol and MemoryResourceProtocol which you’ll never meet because they are invisible and really shy. We talk to these ResourceProtocols using an ancient tribal dance called a UniformResourceIdentifier to quickly reveal themselves, open their magic secret bags full of goodies or if your a traditionalist Archives.

We start our dance by writing down the name of the archive we want to call it to a green ribbon, then shouting out aloud theprotocol we want, then write an ancient symbol the colon in the air then finally we write down the location of the Archive and bury it in the ground.

sparky->openArchive("myFishesArchive", "file:C:/Program Files/Fishes/");

有些协议并不使用Archive,当我们想使用它们的时候,不管它在哪里,MemoryResourceProtocol会接受这个新东西,但不会对它进行命名。在你打开你的Archive之后,我们就可以展示里面的东西了,通过调用ArchiveResourceIdentifier(有点类似UniformResourceIdentifier)。现在我们通过Archive的名字来打开我们想要的资源,我们可以像访问内存一般访问这些资源。

Some Protocols don’t use Archives at all. When we want something – it will be there regardless of where it came from; MemoryResourceProtocol subscribes to this new age thinking. Of course MemoryResourceProtocol doesn’t even name it’s resources – it’s that new age.

After we’ve gotten hold of our magic bag or archive if you prefer. We can now open it and play with the things inside. We do that by another dance called the ArchiveResourceIdentifier. It’s similar to the UniformResourceIdentifier dance, but now we whisper the name of the archive, trace another colon in the air, and start singing out the name of the resource we want, and finish of with a long burp indicating how much access we want to it.

Resource* mr_trout = sparky->open("myFishesArchive:fish.nxs", Enums::ResourceAccess_ReadOnly);

With our Resource now opened we can now play with it, with the assurance that our new friends will handle the nasty bits with Operating Systems, Memory, or even really knowing what type of file or archive we are using.

int x = mr_trout->readInt();  if (size_t size = mr_trout->getSize() > 140) {     mr_trout->seek(140);    short y = mr_trout->readUShort();  }  unsigned int readOps = mr_trout->getNbReadOperations();  mr_trout->seekBeginning();

Next time on the Singletons, we explore the easier side of Resources; Meshes and Heightfields.

Meshes & Heightfields — Behold the Starfish King of North London!

纹理和高位图——注视北伦敦的海星王…..

我们很清楚模型和高位图是不同的,但他们有什么不同呢?

It is clearly said that Meshes and HeightFields have their differences, but what are they and how are the different?

Heightfields

高位图代表一块地形,就像山丘,沟壑,峡谷这些。高位图使用表格的方式,用行和列来描述每一块地形的高度。最高点是32768,最低点是-32768。在NxOgre中,我们使用HeightFild这个类以及HeightFieldManager单例类来管理地形。高位图也可以在你的代码中用ManualHeightField类来创建,你可以用它将文件保存为xhf文件。这里我们会在代码中手动地创建这个地形文件,高位图和模型都是基于简单几何体的!

HeightFields are pieces of terrain; much like a hill, huge tracks of land, or a underwater mini-golf course. HeightFields are like spreadsheets organised into rows and columns – with each cell representing the height of the terrain at that particular point. A value of 32768 may feel like being on top of the world, where as -32678 may feel like everyone is all above at you – laughing.

HeightFields in NxOgre use the HeightField class and are organised by the HeightFieldManager singleton (you’ve met them already). HeightFields may be created within code via the ManualHeightField class or if your feeling adventurous be loaded from a NxOgre HeightField xhf file, which is loaded through the ResourceSystem. You can save xhf files from the ManualHeightField – so it’s win win.

HeightField* northLondon = HeightFieldManager::getSingleton()->load("myFishesArchive:northLondon.xhf");

But for now my petite starfish, we will do it the old fashioned way and make our HeightFields by hand, like our forefathers did.

ManualHeightField southLondon;  southLondon.begin(8,8);  for (unsigned int i=0; i < 8;i++)   for (unsigned int j=0; j < 8;j++)    southLondon.sample((i * 10) + j * 100);  HeightField* theRealSouthLondon = mhf.end("southLondon");

Heightfields are used with StaticGeometries which you’ll encounter later in Level 2. Meshes are also used with StaticGeometries which I will have a chin-wag with you now.

Meshes

我们使用PhysX模型文件,它以nxs文件格式被保存在磁盘中,我们通过MeshManager来将他加载进来

Meshes unlike Heightfields are superior (or not – depending on your point of view). Unlike Heightfields they can take any upon any shape you wish. You can picture of them as an unmovable, loud mouth, shapeshift once sort of…shape.

Like Heightfields Meshes can be loaded from disk via a saved PhysX Mesh nxs file using the MeshManager singleton.

Mesh* the_starfish_king = MeshManager::getSingleton()->load("myFishesArchive:donald.nxs");