Entries for tag "engine", ordered from most recent. Entry count: 39.
# Reflection in RegEngine - Part 2
Sun
25
Jul 2010
In the Part 1 I've shown the basics of my reflection system - classes that describe a class, property and enum. Now the question arises about how do I actually create these objects? Where do I get the information about the classes and properties in my code from? There are many possibilities which I considered:
[*] The simplest one would be to explicitly build these data structures by hand - white some initialization code that would do new Class(...);, new FloatProperty(...) and so on. Oviously this is also the most inconvenient way.
[*] Objects describing classes and properties could be automatically generated by code created by some smart usage of C++ macros and templates. I mean declaring classes and their field using something like DECLARE_CLASS(MyClass, ParentClass) and DECLARE_PROPERTY(Prop1, float), either instead or next to the real class and member declarations. This might be a good idea.
[*] Finally, a separate file with either description of classes and properties in some format or a direct C++ code for building it could be generated from some input data. These input data could be extracted from:
I've decided to create class- and property-describing objects by hand in C++ code but on top of that I've coded an optional tool that takes description file in a special language and automtically generates such code. The code written by hand looks like this:
// Header file
class ComplexItemObject : public ItemObject
{
public:
static void RegisterClass_();
static Class * GetClass() { return m_Class; }
virtual Class * Object_GetClass() { return m_Class; }
private:
static Class *m_Class;
wstring m_Name;
bool m_B1;
common::COLORF m_Colorf;
...
};
// CPP file
Class * ComplexItemObject::m_Class;
void ComplexItemObject::RegisterClass_()
{
m_Class = new Class(L"ComplexItemObject", ItemObject::GetClass(), &CreateFunc, &CloneFunc);
m_Class->SetLabel(L"Complex Item Object");
StlStringProperty *prop1 = new StlStringProperty();
prop1->Init(L"Name", 0);
m_Class->AddProperty(prop1);
BoolProperty *prop2 = new BoolProperty();
prop2->Init(L"B1", 1);
m_Class->AddProperty(prop2);
FloatVectorProperty *prop3 = new FloatVectorProperty(3, VectorProperty::SEMANTICS_COLOR);
prop3->Init(L"Colorf", 2);
m_Class->AddProperty(prop3);
g_Reflection->AddClass(m_Class);
}
Similar code can be automatically generated by my console tool called ReflectionAuto from a .reflect file. The file format is a description language based on my Tokenizer. ReflectionAuto takes in as input and outputs a separate C++ file that adds this boring reflection initialization code to the described classes. The description of the class shown above looks like:
class ComplexItemObject {
extends ItemObject;
label "Complex Item Object";
property string Name { access m_Name; };
property bool B1 { access m_B1; };
property int4(color) Colori { access m_Colori; };
};
That covers the basics (not everything I actually have) when it comes to building description of the classes and properties from my code to make the reflection system aware of them. In the next part I'll show how do I access real objects from my reflection system, including reading and writing properties, as well as creating and manipulation whole objects.
Comments | #c++ #RegEngine #engine Share
# Reflection in RegEngine - Part 1
Sat
24
Jul 2010
Do you remember my old entry about RegEngine? I didn't drop this project. I slowly code it and recently I've finished a reflection system, which I want to show you now.
Generally speaking, reflection is the ability of a code to be aware of itself - especially about its classes and fields. Many high level programming languages and especially sripting languages already have extensive built-in reflection system. In C++ it's not the case because source code is compiled to machine code and all information about classes and fields is lost (except simple RTTI).
Why do we need reflection anyway? When coding a game engine, we deal with many different kinds of objects (like texture, mesh, monster or terrain) and each class have its own set of properties of different types (like int, float, bool, string, vector or color). But we, as game developers, are not willing to code dialog windows for editing these properties or code serialization to/from file for each of these classes. So the idea is to make the code aware of existance of different classes, different property types and on top of that enable automatic exposing all objects to the editor (via so called Property Grid control), as well as serialization to/from a file - all in consistent manner, coded only once.
I've seen many reflection systems and designing my own was a hard process because I had to make some difficult decisions. The way I did it is a matter of some compromise - my solution is not the most general, efficient, powerful and "ultimate" one possible. My reflection system can be seen as consisting of three layers:
1. Bottom layer is the collection of objects describing classes - their names, inheritance and the list of properties, where each property has an identifier, name, type and optionally additional attributes dependand on this type.
2. On top of that there is a code that keeps track of all reflection-compatible objects that currently exist in the system, allows creating, destroying and manipulating them, as we all reading and writing values of class properties in a particular object.
3. Finally, much real functionality can be accomplished using these two previous layers. One of them is serialization - loading and saving single or all objects to/from a file in some file format, either text or binary. Another important thing is exposing all these functions (manipulating objects and their properties) for the user via the editor. There are more possibiblities I could use in the future, like:
When looking for inspiration and exploring possible solutions about how a reflection system can look like, it's worth looking at how it's made in:
Now I want to show some code, at least parts of header files. It all starts in my system from a single global object of type Reflection, which owns the collection of objects describing all classes and enums registered in the system. This collection is built at program startup and the g_Reflection objects allows finding them by name in runtime.
Comments | #engine #RegEngine #c++ Share
# RegEngine - Design
Wed
10
Feb 2010
I'm now starting coding new game engine. It's called RegEngine. Here is a general design. It's coded in C++ for Windows. This time it will be general game engine, not only renderer. Also, this time I'm going to create an editor (I've never done this before).
I will use wxWidgets 2.9 as GUI library for the editor. It's not an obvious choice though. For example, C++/CLI (which I use at work) is also nice technology as it allows to freely mix native and managed code so one can create GUI with Windows Forms while coding the rest in native C++. But personally I prefer something that is fully native. Qt is also good, looks more mature, stable and, well, "serious" than wxWidgets and it's also free for some time. But wxWidgets is more lightweight than Qt (to a certain degree, as GUI library can be). It also looks like wxWidgets is the only GUI library that has both docking and property grid control built in. (I'm talking about version 2.9 here, because stable 2.8 version of wx doesn't have the property grid yet.)
I want to separate engine from renderer. But I'm not going to make an abstraction to be able to transparently switch between DirectX and OpenGL as it makes no sense for me. I just want to have the ability to use my engine, with all its functionality like scenes, actors, scripts, AI, sound etc. with new renderer I would code some day, let it be DirectX 11 or software one. To do this, my engine will be component based. An actor standing in the scene will just have its name and/or some ID, position, bounding volume and a set of components. If it's visible, its rendering component will be an object from the renderer.
There is also a great idea I want to incorporate into my engine that I know from Krzysiek K. (greetings!). It goes like this: The game, which will be a document for the editor (that's what you can create as New, Open, Save, Save As etc.) is a single, big tree of objects of different type. This tree includes both resources (like textures, meshes, sounds) and scenes with hierarchies of actors inside them, as well as any other entities (like dialogs in an RPG game). Object can have sub-objects and can also have a set of properties of different types (like bool, int, float, string, vector, matrix, color). Framework for these properties (I'll call it "reflection") will automatically serialize them to/from file, show them in property grid in the editor and hopefully make them visible to scripts. This whole idea gives consistent framework to store, serialize and edit all game data.
As creating new dialog boxes is not my favourite activity (no matter if it's coding or clicking :) I've been thinking for a long time about the "ultimate" set of general controls necessary to make a game editor. I currently think that it's sufficient to have:
Some not so necessary and more difficult to code controls are:
RegEngine will consist of modules compiled as static libraries:
First screenshot:
Comments | #engine #RegEngine Share
# FileChangeMonitor
Tue
24
Nov 2009
Today I'd like to show a piece of my code with an interesting solution. The problem is: Most of us have to restart our applications to see changes made in textures, shaders and other data files. It may not be a problem at the beginning, but as the application and the amount of resources grow, loading the whole thing takes longer and longer. Wouldn't be great if we could change or replace asset files and immediately see the results without restarting the game? This idea seems fascinating especially after watching some of the videos about CryEngine 3 editor :)
So here is my solution: FileChangeMonitor.cpp, FileChangeMonitor.hpp. It's not a ready-to-use code snippet, but rather something you can base on when writing your own code. I've created a FileChangeMonitor class and a global variable to give access to its single instance to everyone. The purpose of this class is monitoring some files for change in their "last modified" date. Here is the way to use it:
Of course I didn't want to block entire application for the time of retrieving file date, so I do it on separate thread. That thread has a loop (with some delay of course), checks modification time of registered files and posts a small structure to a queue after noticing file change. ProcessEvents method called in main thread only processes this queue and dispatches received events to registered listeners.
I'm aware this code is not perfect. The more files are registered, the less frequent each file is checked for modification. I could also use some lockless data structure as a queue instead of std::vector protected by mutex. I could even use totally different solution, like monitoring changes in a directory provided by Windows API (look for ReadDirectoryChangesW function in MSDN). But this solution works OK for me, the implementation can be changed without changing its very simple interface and my point here is just to tell you that it's very convenient when you can change a texture, shader code or any other asset and it is automatically reloaded in a second, without restarting your application.
# Unreal Engine for Free
Sun
08
Nov 2009
This week the news of the week was the release of the famous, probably world's best game engine free to download and uncommercial use. I'm talking about Unreal Engine in form of UDK - Unreal Development Kit.
At first glance it looks like a small revolution, but when you download (562 MB) and install (1.25 GB) the package, you will see it's actually not an SDK at all. There is no source code or even headers and libraries to code your own game in C++ using this engine. It's just the game editor and the only thing you can do besides graphics and level design is scripting gameplay mechanics in UnrealScript. Just like Game Maker, only more advanced ;)
Nevertheless I think it's important news and the editor is worth seeing. All in all Unreal Engine is a great technology used by countless commercial game developers. I've started reading UnrealScript Reference and I'm amazed by concepts of this language like object states, latent code or replication. Now I feel like making a game with the Unreal Engine, but as I'm neither good artist nor good level designer, soon I will probably go back to my own C++ code, just knowing how a good game engine should look like.
Comments | #engine #tools Share
# About the Guy Who Made Love
Sat
22
Aug 2009
Today I want to talk a bit about what's the dream of almost every passionate game developer. It seems very hard or almost impossible to achieve, but younger amateurs still hope that they will manage to do it someday. Of course I'm talking about making a 3D MMO game.
As it turned out for me today (thanks for the link KriS!), it actually IS possible. I'm talking about the game called Love written entirely by one person - Eskil Steenberg. He have coded all the software from modeling tools through network protocol and renderer until game mechanics. To see it working I recommend watching these videos. The game is powered by his engine called Quel Solaar, which is actually available for download.
I must admit I haven't been impressed so much for a long time. I suppose the amount of time and passion that had to be put into this code is enormous. Graphical style and gameplay, as well as the user interface of his tools are very unusual and surprising. And all of this is made by one guy...
I recommend watching his lecture from this year's Assembly party titled Developing the technology behind "Love". You can see many technical details and if you don't want to watch the entire one hour video, at least watch the beginning (where he talks about his "smarter way of doing things") and the ending (where he expresses his thoughts about the value of good tools).
BTW it's also nice to watch new videos from GC 2009 of the CryEngine 3. "What you see is what you play" and instant asset update (including textures) - that's how good game editor should look like :)
Comments | #software engineering #networking #web #rendering #games #events #engine #demoscene #philosophy #tools Share
# Manager zasobów #2 - Wczytywanie w tle
Sat
23
May 2009
Sam manager zasobów napisałem wg podobnych założeń, jakie miałem w TFQ7. Jest jeden globalny manager zasobów g_ResMngr przechowujący kolekcję wszystkich zasobów. Zasób jest obiektem klasy pochodnej od Resource implementującej odpowiednie metody wirtualne. Zasób może mieć nazwę i można wyszukiwać zasoby wg nazwy, ale może też mieć nazwę pustą. Zasoby można swobodnie tworzyć i usuwać. Obiekt klasy Resource istnieje przez cały czas życia zasobu, a wewnątrz pamięta stan - niezaładowany, w tracie ładowania, załadowany itd.
class Resource { public: enum STATE { STATE_UNLOADED, STATE_LOADING, STATE_LOADED, STATE_LOADED_ERROR, }; Resource(const string &Name); virtual ~Resource(); STATE GetState() { return m_State; } bool IsLoaded() { return m_State == STATE_LOADED; } void Load(); // Żąda załadowania już teraz void BeginLoading(); // Rozpoczyna ładowanie w tle void Unload(); // Odładowuje //... protected: virtual void OnLoad() = 0; virtual void GetLoadType(bool *OutUseBkg, BkgJob::TYPE *OutBkgJobType) = 0; virtual void OnLoadBkg() { } // Wykonywana na osobnym wątku virtual void OnLoadAfterBkg() { } virtual void OnUnload() = 0; private: string m_Name; STATE m_State; //... }; class ResourceManager { public: //... Resource * Find(const tstring &Name); Resource * MustFind(const tstring &Name); template <typename T> T * FindEx(const tstring &Name) { /*...*/ } template <typename T> T * MustFindEx(const tstring &Name) { /*...*/ } }; extern ResourceManager * g_ResMngr;
Comments | #algorithms #c++ #engine Share
# Manager zasobów #1 - BkgJobManager
Thu
21
May 2009
Tajemniczy "Ciekawski" prosił, żebym opisał mój asynchroniczy manager zasobów. Zanim go opiszę, muszę napisać słowo o tym, na czym się on opiera - o module do wykonywania zadań w tle.
Ogólnie chodzi o to, aby osobny wątek pracujący w tle wykonał jakieś określone zadanie. Problem w tym, że tworzenie za każdym razem nowego wątku jest powolne. Poza tym przydałoby się, żeby takie zadania były wykonywane po kolei, a nie wszystkie na raz. Dlatego napisałem globalny BkgJobManager, który ma na stałe utworzone wątki, a zadania do wykonania dodaje się do jego kolejki jako obiekty specjalnej klasy BkgJob.
class BkgJobManager { public: BkgJobManager(); ~BkgJobManager(); void Init(); void Frame(); void AddJob(BkgJob *Job); //... }; extern BkgJobManager *g_BkgJobManager;
Żeby zdefiniować swoje zadanie, trzeba odziedziczyć po klasie BkgJob i zaimplementować metody: OnWork (wywoływaną na osobnym wątku) i opcjonalnie OnWorkDone (wywoływaną po zakończeniu, już na głównym wątku, w ramach wywołania BkgJobManager::Frame).
class BkgJob { //... protected: BkgJob(TYPE Type, MODE Mode); virtual void OnWork() = 0; virtual void OnWorkDone() { } };
Dodatkowo, klasa pochodna określa typ zadania jako obliczeniowe (mocno angażujące procesor) lub wejścia-wyjścia (wczytujące coś z dysku). To mój oryginalny pomysł oparty na przemyśleniu, że najoptymalniej będzie, jeśli na raz będzie się mogło wykonywać tylko tyle zadań obliczniowych, ile jest rdzeni w procesorze (więcej obniżyłoby wydajność przez częste przełączanie się procesora między wątkami) i tylko jedno zadanie wejścia-wyjścia (więcej obniżyłoby wydajność przez przeskakiwanie głowicy dysku między wieloma czytanymi na raz plikami).
enum TYPE { TYPE_COMPUTATION, TYPE_IO, TYPE_COUNT };
BkgJobManager przechowuje kolejkę zadań do wykonania. Żeby to napisać porządnie, to pewnie powinna być jakaś struktura "lockless", ale ja póki co załatwiłem synchronizację zwykłym muteksem.
Ponadto zadanie ma swój priorytet. Na zadanie można też poczekać, np. wywołując na wątku głównym BkgJob::Join. To wywołanie zwróci sterowanie dopiero, kiedy dane zadanie się zakończy. Jeśli to zadanie czeka gdzieśtam w kolejce, to jego priorytet zostaje podbity, żeby trafiło na przód kolejki.
Ciekawym rozwiązaniem jest, że na wątku głównym należy wołać w każdej klatce (lub inaczej, ale możliwie często) BkgJobManager::Frame. Daje to okazję managerowi, aby "zebrać" wykonane w tle i zakończone zadania, wywołać im BkgJob::OnWorkDone i zwolnić je z pamięci.
Trzeba też pomyśleć, jak z wykonywanej na innym wątku funkcji BkgJob::OnWork przekazywać informację o niepowodzeniu. Ponieważ w swoim kodzie używam wyjątków, łapię wyjątek zgłoszony w BkgJob::OnWork i zachowuję jego obiekt, żeby na wątku głównym móc go potem odczytać.
Podsumowując: Oryginalnie wątek służy do tego, żeby natychmiast rozpocząć wykonywanie jakiejś pracy w tle albo żeby działać cały czas w pętli czekając na jakieś komunikaty. Mechanizm taki jak tutaj przedstawiłem pozwala zmienić koncepcję na taką, w której użytkownik może tworzyć zadania i dodawać je do kolejki, a one będą po kolei wykonywane w tle. Podobny kod - JobSwarm - umieścił na swoim blogu John Ratcliff. Mój można pobrać stąd: BackgroundJob.hpp, BackgroundJob.cpp.
Tego mojego modułu mogę teraz używać do różnych rzeczy, ale podstawowym (i póki co jedynym :) zastosowaniem jest wczytywanie w tle zasobów Direct3D. O samym managerze zasobów napiszę następnym razem...