Separating/Modularizing the View

Separating/Modularizing the View

Discuss the source code and development of Spring Engine in general from a technical point of view. Patches go here too.

Moderator: Moderators

User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Separating/Modularizing the View

Post by hoijui »

Motivations:
* Headless Client comes for free
* View can be exchanged easily
* Multiple views are more easily possible (think of an in-game window showing an other part of the battlefield)
* Possibly easier to multithread?
* Tendency for less bugs/easier finding of bugs

Current things that could/would be separate views:
* 3D OpenGL battlefield
* 2D Minimap
* Sound
As the term View and function names like Draw() do not fit for Sound (and probably others to come?), we may have to think about other terms. Though this can probably also be done with properly commenting the classes, to some extend.

The big contra of course, is the work that would have to be put into it. My motivation for it, is the headless client fo course. I would like to discuss this, and try to get to a common idea of how exactly it should look like. As i myself have little knowledge about this area of spring, i can not really give a basic idea on which we could base our dsscussion on; I hope someone else will do that. I will help in doing the work, and hope some others will join :D
One requirement i want to anticipate: The aproach we end up with should be as flexible as possible, and it should be possible to implement it smoothly, eg class by class. I think the changes should be done in master, as they would touch pretty much all of spring, it would end up in a merge hell once a lot of changes have been done, as i expect a lot of code would have to be moved to other files.

the Headless Client thread:
http://springrts.com/phpbb/viewtopic.ph ... s&start=20

see also the Model-View-Controller pattern:
Wiki: http://en.wikipedia.org/wiki/Model-view-controller
an other simple & straight forward explanation with a simple sample:
http://www.enode.com/x/markup/tutorial/mvc.html
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Re: Separating/Modularizing the View

Post by hoijui »

instead of Draw(), we could probably use Render(), as it is more general, and would fit for both video and audio, for example.

As nobody else did, i will try to do a start:
There would be a RenderingHandler, inheriting from CEventClient, which means it would receive all sorts of events like Update, UnitDied, and so on. This class has a list of RenderingSystem instances, which is also a class inheriting form CEventClient. The RenderingHandler woudl then be responsible for creating and destroying the RenderingSystem instances (by default beeing: sound, minimap, 3D OpenGL view), and it would forward relevant/all events to them.
In the code as we have it now, we have a lot of classes like this one:
rts/Sim/Projectiles/WeaponProjectiles/LightningProjectile.h
class CLightningProjectile : public CWeaponProjectile
{
void Update();
void Draw();
virtual void DrawOnMinimap(CVertexArray& lines, CVertexArray& points);
};
which would then be split into:
// This class would stay under rts/Sim
class CLightningProjectile : public CWeaponProjectile
{
void Update();
};
// while these 3 would go under rts/Rendering into separate sub-dirs
class CLightningProjectile3DRenderer : public Renderer
{
void Update();
/// Renders to an OpenGL 3D view
void Render();
};
class CLightningProjectileMiniMapRenderer : public Renderer
{
void Update();
/// Renders to a 2D mini map
void Render();
};
class CLightningProjectileSoundRenderer : public Renderer
{
void Update();
/// Renders SFX to a soundcard
void Render();
};
User avatar
jK
Spring Developer
Posts: 2299
Joined: 28 Jun 2007, 07:30

Re: Separating/Modularizing the View

Post by jK »

The idea itself isn't that bad.

But your way is totally wrong, adding 100 new classes will make it impossible to debug & maintain/adding new stuff, and then it will also increase the memory and cpu usage a lot.
Also you should say your motivations here ... you just want a headless client, the rest of the stuff you mentioned is already possible :roll:

So I always wanted to add a scene graph (that's the correct solution). And it's on the top of my engine todo list, but it's a very huge project and atm I am working on Chili.

So: Thank-you for your patience. 8)
Last edited by jK on 22 Sep 2009, 16:36, edited 1 time in total.
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Re: Separating/Modularizing the View

Post by hoijui »

I clearly wrote that this is my motivation ;-)

Well.. you say you know the solution, and you are hte only one to do it right, and we have to wait for you doing it?
There are some already waiting for headless...
therefore, this seems to be a bad way to go. Can't we do it differently? Also, i can not see how you want to elegantly get rid of dependencies that are only in files becasue of the rendering code, wihtout getting that code out of these files. the only way i see for this to work is using a lot of #ifdefs.

edit:
jK wrote:But your way is totally wrong, adding 100 new classes will make it impossible to debug & maintain/adding new stuff, and then it will also increase the memory and cpu usage a lot.
i can not see why it should be harder to debug or maintain or adding new stuff, or harder to maintian or .. anything you wrote.
this is about high level design, and if you can get a clearly nicer high level design, it should not be dismissed because it needs a few more classes which in turn increases memory usage by 0.1%, plus a few more function calls (hardly messurable?). I know we have totally different views there though. :D
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Re: Separating/Modularizing the View

Post by Tobi »

What I'd do if I was forced to do it now, is put non-sim code together based on what it does, instead of what it operates on. Projectile classes would only contain sim code, and there would be a separate CProjectileRenderer class that renders all projectiles in one batch, and a CProjectileMinimapRenderer that renders only a dot on the minimap for every projectile.

Where to store data that shouldn't be in the object in sim is hardest part of problem IMO. How does a scene graph solve this?

I guess for objects with an ID the renderer could store e.g. a 'shadow copy' of the array mapping ID -> object, but now not mapping to sim object, but to rendering data.


Note I target sim code that is compilable without linking to dependencies like OpenGL, OpenAL and also without linking to anything but code in rts/Sim and rts/System (and maybe part of rts/Map..., at least in a first phase)

Also I would like to modify it so that syncify becomes viable again: e.g. every block of memory (read: object) must contain either only synced data, or only unsynced data, but never both! (where synced/unsynced in this case in the meaning of which code has what kind of access to the data, not whether it's exactly identical on all clients or not - so pointers and containers are fine..)
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Separating/Modularizing the View

Post by Argh »

Uh... dumb question time.

Why do you need to have a true headless client, when you can cut the simulation load for graphical tasks to near-zero with some pretty straightforward Lua and some OpenGL? I mean... if the Units are treated as icons, IIRC they aren't drawing any Unit geometry, period. You can turn the map off. Etc.

I mean... between that, and doing a few logical things, like setting the map and shadows to not render, the skycube / reflections to not bother, etc., etc., etc. which are all possible atm, and then maybe setting a quad that always wins a depthtest, to prevent most other things from drawing, you should be able to get pretty close to the true load of a headless client... without a big mess.

You're still going to see massive CPU hits from things like CEG events, which are "graphics", but on this engine are still mainly performed on the CPU, and are therefore valid to real-world performance testing of an AI's gross impact on the CPU side of things.

In short... a headless client would just tell you and the rest of us what we already know, which is that too much stuff is being done on the CPU that should be done on GPUs, graphically, mainly to support a small group of folks on GLSL / OpenGL 2.X non-compliant hardware.

If your sole goal is speed, both in terms of development time and ease of deployment... you could get more performance, faster, for valid AI testing, simply by setting up the fake-headless client as I suggested, then forcing all weapons in BA to use explosions without CEG events or sounds (via Lua), and you could have that done by this weekend, if you just want to continue working on strictly stuff for BA.
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Re: Separating/Modularizing the View

Post by Tobi »

With that way of headless you still need installed OpenGL capabable graphics, you need drivers/libraries for it etc.

True headless would be runnable on headless servers too.


Also CEGs (and all other unsynced projectiles) can just be disabled in the code in this case.
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Re: Separating/Modularizing the View

Post by hoijui »

The only advantage of this method, Argh, is that it would use less worktime. If you do AI performance testing, relevant for users, you do it with the normal client anyway.

Tobi (and everyone else):
i am not sure how you think about the whole idea (except for jk :D ).
The method you described sounds quite similar to mine, except that i had one render class instance per sim object instance, while you have one per sim object type, or possibly one for multiple types even.
I am not sure if you meant one projectile render for all projectiles, or one per projectile type, and possibly use the same renderer for multiple types. eg:
for the minimap view, most particles would be rendered equally -> one renderer for all of them, while on the 3D view the would all look different.
or is it possible to really unify the projectile rendering for all projectiles into one class?

... just trying to find out if i get you right/trying to understand what you mean.
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Re: Separating/Modularizing the View

Post by hughperkins »

Tobi wrote:With that way of headless you still need installed OpenGL capabable graphics, you need drivers/libraries for it etc.

True headless would be runnable on headless servers too.
I assume it's not possible, but could one not just simply use mesa software rendering?

AFAIK the main rate-limiting step in Spring is pathing in any case, so getting rid of graphics won't speed things up that much? Maybe that is two-year old rate-limiting step analysis :-D
Auswaschbar
Spring Developer
Posts: 1254
Joined: 24 Jun 2007, 08:34

Re: Separating/Modularizing the View

Post by Auswaschbar »

hughperkins wrote:
Tobi wrote:With that way of headless you still need installed OpenGL capabable graphics, you need drivers/libraries for it etc.

True headless would be runnable on headless servers too.
I assume it's not possible, but could one not just simply use mesa software rendering?

AFAIK the main rate-limiting step in Spring is pathing in any case, so getting rid of graphics won't speed things up that much? Maybe that is two-year old rate-limiting step analysis :-D
Software renderer + skip interface. Would give like 99,9 % of the performance of the headless client.
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Re: Separating/Modularizing the View

Post by Tobi »

hoijui, what I meant was specifically one renderer for all projectiles. E.g. one renderer for a set of similarly rendered items: a projectile renderer, a shield renderer, a unit renderer, a minimap projectile renderer, etc. This way possibly some code can be shared between projectiles that behave different but look similar, and I think it could allow for some interesting optimizations.
User avatar
aegis
Posts: 2456
Joined: 11 Jul 2007, 17:47

Re: Separating/Modularizing the View

Post by aegis »

Auswaschbar wrote:
hughperkins wrote:
Tobi wrote:With that way of headless you still need installed OpenGL capabable graphics, you need drivers/libraries for it etc.

True headless would be runnable on headless servers too.
I assume it's not possible, but could one not just simply use mesa software rendering?

AFAIK the main rate-limiting step in Spring is pathing in any case, so getting rid of graphics won't speed things up that much? Maybe that is two-year old rate-limiting step analysis :-D
Software renderer + skip interface. Would give like 99,9 % of the performance of the headless client.
but that won't work without starting X on linux?
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Separating/Modularizing the View

Post by Argh »

Also CEGs (and all other unsynced projectiles) can just be disabled in the code in this case.
Well, that's why I was saying, use Lua to give the weaponDefs a null CEG.

But yeah, that's the fast way. It might serve as an interim solution, until the slow way is built.
User avatar
aegis
Posts: 2456
Joined: 11 Jul 2007, 17:47

Re: Separating/Modularizing the View

Post by aegis »

my reason for wanting a true headless solution has less to do with performance and more to do with running without opengl support
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Re: Separating/Modularizing the View

Post by hoijui »

Tobi wrote:hoijui, what I meant was specifically one renderer for all projectiles. E.g. one renderer for a set of similarly rendered items: a projectile renderer, a shield renderer, a unit renderer, a minimap projectile renderer, etc. This way possibly some code can be shared between projectiles that behave different but look similar, and I think it could allow for some interesting optimizations.
ok :-)
yeah.. better and more flexible then having one renderer per type or even per object instance, as this could still be done inside such a common renderer (not to sya it is needed in practise).
About the problem for storing object instance related (only rendering relevant) data:
maybe we could introduce an ID in one of the base classes (Object, WorldObject or SolidObject), or introduce a new base class RenderingObject for uniquely identifying objects to be rendered, so we could link them to their rendering data.
In my proposal, there was an abstraction of rendering systems. would you use this too? .. it seems that this would be a small ammount of work, compared to the separating of the rendering.
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Re: Separating/Modularizing the View

Post by hughperkins »

Right, this post is slightly off-topic if this fails, which it is doing so far, but very much on-topic if it doesn't.

Anyway... there is something called osmesa http://www.mesa3d.org/osmesa.html that lets you render to an off-screen buffer, without depending on X, which sounds like exactly what we want.

So, basically, you just make a couple of calls to OSMesaCreateContext() then OSMesaMakeCurrent(), and Ploof! gl calls should magically render to an off-screen buffer, with no dependency on X!

HOWEVER, when I tried a small prototype using osmesa with SDL, http://article.gmane.org/gmane.comp.lib.sdl/39418 , SDL_Init fails, and it seems SDL is hard-coded to need X and / or fbdirect :-/

So... so far this route is not providing the quick route to my hoped for nonchalant post "Hey guys, I have a short 5-line patch that makes Spring headless. Anyone interested?" that I was hoping for 8)

Other possible quick 'n dirty route: virtualbox seems to be able to run headless, without needing x or sdl, with a bit of tweaking, though whether it runs anything graphical headlessly is an open question. Without trying it, my gut-feeling guess would be: no, at about 90% certainty level.

If I exhaust these avenues, I might actually take a look at the headless code BUT I'm running an EEEPC. Do you know how long it takes to compile Spring on an EeePc :shock:

Edit: most relevant thread I found on SDL over osmesa: http://lists.libsdl.org/pipermail/sdl-l ... 60370.html
Last edited by hughperkins on 28 Sep 2009, 07:30, edited 1 time in total.
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Re: Separating/Modularizing the View

Post by hughperkins »

Looking at making Spring itself headless... is there any reason why we can't do something like:

Generic renderer interface:

http://fractalspline.cvs.sourceforge.ne ... threv=HEAD

OpenGL implementation of interface:

http://fractalspline.cvs.sourceforge.ne ... threv=HEAD

... or maybe this is what we are doing? Anyway, an advantage of just wrapping all opengl calls in this way is that it's easy to just do a search/replace throughout the whole code, like "glAddVertex3f" is replaced systematically by something like "pRendererCallbacks->AddVertex" : http://fractalspline.cvs.sourceforge.ne ... iew=markup

We'd need to wrap the SDL calls in a similar way.

It's not beautiful, but it would work.
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Re: Separating/Modularizing the View

Post by hughperkins »

There's a guy at the following link who it seems has created a small fbdirect patch that lets it use allocated memory as its buffer:

http://www.nabble.com/Devmem-in-system- ... 43374.html

Going back to the approach of having some generic opengl interface from which we can derive a concrete class that actually calls opengl, or another one that does nothing, another approach to presenting this is here:

http://blog.objectmentor.com/articles/2 ... -c-example
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Re: Separating/Modularizing the View

Post by hughperkins »

Proposition: employ a two-step approach to headlessness:

1. In the short-term, use an approach along the lines of http://blog.objectmentor.com/articles/2 ... -c-example to get rid of sdl calls and opengl calls when some flag 'headless' or 'unittesting' is set to true

2. In the medium to long term, look at separating the model and the view

I feel an advantage of the first solution in the short-term is that it is relatively simple, in that there are little to no structural changes to the code organization: it's just a search/replace essentially. Plus, the way it's presented in the link above, I feel one can make it appear fairly palatable, 'it's for unittesting!' and so on.

Thoughts?
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Re: Separating/Modularizing the View

Post by hughperkins »

Right, I had a play with:
- stubbing out SDL -> this works fine
- using osmesa -> works, though it needs special linking

Prototype here:

http://manageddreams.com/ailadder/downl ... ng.tar.bz2

Details

Stubbing out sdl

This works fine.

I had to create a stub for SDL_Surface, which had to return appropriate values for w and h:

Code: Select all

class SDLSurfaceStub : public SDL_Surface {
   public:
   SDLSurfaceStub() {
      w = 512; h = 512;
   }
};
The full sdl interface, wrapper and stub I used can be seen at:

http://pastebin.com/f6d4d0205

Using osmesa to stub out opengl

This worked: I got the prototype to run from a console! ie, outside of X etc!

There is an issue with linking however:

if you link like this:

Code: Select all

g++ -o prototype *.o -lOSMesa -lGL -lSDL
... then running headlessly works fine, flawlessly.

However, running non-headlessly no longer works :-O

If one links like this:

Code: Select all

g++ -o prototype *.o -lGL -lSDL  -lOSMesa
... then running non-headlessly works fine, but running headlessly no longer works ;-)

If there is no solution to the linking issue, it would mean that headless Spring would need to be linked separately from production Spring, though it's not the biggest problem in the world.


Edit: the code used in the prototype:

http://pastebin.com/f6d02cf8

Edit: and the original code, before making it headless, so you can do a diff and see what's changed, if you wish:

http://pastebin.com/fe3e25c0

Edit: and the actual diff:

http://pastebin.com/f348345da
Last edited by hughperkins on 28 Sep 2009, 07:15, edited 4 times in total.
Post Reply

Return to “Engine”