Jump to content
  • Advertisement
Sign in to follow this  
RuneLancer

Rate my engine!

This topic is 4071 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've started working on a 3D engine and I'd like some comments and suggestions on improving it. I'm not making this into a AAA-quality engine, though I'm trying to have something moderately performant and decent enough. Again, these are just the first stages of the engine - it's a draft at this point. In short, my engine is as a singleton. Among its members, it contains a vector used to store scene data. Typically when rendering a frame, my game clears this vector. Each interface (for example, the window/font manager) then shoots data into it. Typically they cumulate all of their data into an array or vector and shoot it into the engine in one operation. Once the vector has been filled with the render data, I call my engine's render method which renders the data all at once. Ideally I want to abstract everything graphic from the rest of my game. I don't want my game to work with vertices at all, other than generating the data. That way I'd be able to write a different graphic engine and support, say, OpenGL at a later date if I wanted to, or reuse the engine elsewhere with little to no tweaking. The game is just responsible for generating the data - the graphic engine is responsible for doing stuff with it. Also, I'm a little uneasy with refilling the vector every frame. It seems like I could benefit from having some sort of dirty region to identify new data so I don't have to regenerate a large amount of vertices that remain the same from frame to frame (ie, map data.)

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by RuneLancer
In short, my engine is as a singleton.
That's going to cause some discussion. Long story short, I think that's a serious mistake.
Quote:
Among its members, it contains a vector used to store scene data. Typically when rendering a frame, my game clears this vector. Each interface (for example, the window/font manager) then shoots data into it. Typically they cumulate all of their data into an array or vector and shoot it into the engine in one operation. Once the vector has been filled with the render data, I call my engine's render method which renders the data all at once.
Why is this data stored in the engine class? Wouldn't it make a lot more sense for each subsystem to pass its data in?
Quote:
Ideally I want to abstract everything graphic from the rest of my game. I don't want my game to work with vertices at all, other than generating the data. That way I'd be able to write a different graphic engine and support, say, OpenGL at a later date if I wanted to, or reuse the engine elsewhere with little to no tweaking. The game is just responsible for generating the data - the graphic engine is responsible for doing stuff with it.
That's all well and good, but there's a lot of design subtleties involved to be careful of in doing that. YOu should do it; just don't expect it to be easy.
Quote:
Also, I'm a little uneasy with refilling the vector every frame. It seems like I could benefit from having some sort of dirty region to identify new data so I don't have to regenerate a large amount of vertices that remain the same from frame to frame (ie, map data.)
Maybe. This vector itself seems sketchy to me. What, precisely, is in it?

Share this post


Link to post
Share on other sites
Quote:

In short, my engine is as a singleton.

Unnecessary and crippling.

Quote:

Among its members, it contains a vector used to store scene data. Typically when rendering a frame, my game clears this vector. Each interface (for example, the window/font manager) then shoots data into it. Typically they cumulate all of their data into an array or vector and shoot it into the engine in one operation. Once the vector has been filled with the render data, I call my engine's render method which renders the data all at once.

This sounds like you have a single vector containing a whole bunch of geometry that is acquired from various sources (the game, for example), and then rendered in one go. This is very, very, limiting and will not scale well at all.

I'm reluctant to continue with more critique/advice/discussion until I can see more of this "engine." Can you describe the architecture in more depth, and/or provide some sample code?

Share this post


Link to post
Share on other sites
I'm curious how making it a singleton is unecessary and crippling. The engine sits next to the game - I'm never going to create any extra copies of it. Alternatively I could just instantiate it once and pass a pointer around, but I don't see what this adds, in this particular situation. I'm not criticizing, I'm asking - I'm curious why GD.net seems so anti-singleton. ;)

@Promit:
I see what you mean about passing the data in. Correct me if I'm wrong, but you're suggesting I don't cumulate the data into my engine, and essentially render the geometry as I need it? (ex, once the window subsystem has generated the geometry for the windows and text, they'd all be sent into the engine to be rendered immediately.)

I'm not opposed to keeping the geometry in the subsystems (technically I'd have to anyhow :P) What I want mainly is to have all of the management be specific to the graphic engine. Occlusion tests, for instance, sorting, all that. Basically I don't want to end up rewriting the same code for each subsystem before passing the data off to the engine.

The vector contains the vertices to render (position, color, etc, etc..) It's basically passed off to DirectX directly during the render phase in one go, and assumed to have all necessary optimisations/tests performed on it beforehand. Ie, it's the final list of vertices to render.


@jpetrie:
Like I said, this is a draft. I don't have any code to show - this is the planning phase. I don't want to start writing code if the very idea behind it is flawed. Hence why I'm asking for input over this. I don't expect to get everything right the first time, but I'd rather not waste a few weeks writing the engine if it turns out the entire idea is flawed and will have to be scrapped. :P

Share this post


Link to post
Share on other sites
I'm going to move this to 'Game Programming' (although it could possibly go in 'Software Engineering' or 'General Programming' [oh]) as it doesn't seem like you're focussing on the DirectX-specific side of architecture/design.

Quote:
I'm curious why GD.net seems so anti-singleton. ;)
There is a bit of history behind it. It seems that despite the many discussions about the design pattern people still keep on using it [smile]

April 2005 was a good month for Washu. It's well worth reading the few entries he's put out on the subject if you want to know why you should be worried about your 'singletonitis'...

hth
Jack

Share this post


Link to post
Share on other sites
Quote:

Like I said, this is a draft. I don't have any code to show - this is the planning phase. I don't want to start writing code if the very idea behind it is flawed. Hence why I'm asking for input over this. I don't expect to get everything right the first time, but I'd rather not waste a few weeks writing the engine if it turns out the entire idea is flawed and will have to be scrapped. :P


Good idea. Here's another thread where I commented on some dangers of singletons. The same points apply, basically: you say you only plan on having one, and that's fine, create only one. Don't cripple yourself by placing an arbitrary restriction on your design so early. Singletons also are easy to use as crutches and band-aids for bad design -- you talk about needing to "passing a pointer around," which is what you should do, but only when you really need it. Since singletons allow global access, they trick you into believing you need that global access. You don't. In practice, the number of instances where you must pass things around are relatively small (if your design is good).

Share this post


Link to post
Share on other sites
Isn't the OGRE engine littered with singletons? If singletons are so deadly (which I completely disagree on) why does a large popular open source engine use them so much??

I use singletons in engine design when there should be only one. Where having two would screw things up, or you simply shouldn't need more than one. Most of the time its better to have global accessibility as well. Having to go Engine::GetInst ().GetFileManager () is worse than FileManager::GetInst ()....

I'm currently designing and creating an engine that'll be used for DirectX10, and have done a lot of the base classes such as template helpers, math classes, file classes etc and I've got a few singletons.

* FileSystem (keeps a list of archive codecs, loaded archives etc)
* ThreadManager (handles creation of named Win32 threads)
* InputManager (handles DirectInput enumeration etc)
* PluginSystem (loads and unloads plugin dlls)

- Renderer and Engine will be singletons too.

(my Log class is just static member functions, no need for a singleton there)

Share this post


Link to post
Share on other sites
Quote:

Isn't the OGRE engine littered with singletons? If singletons are so deadly (which I completely disagree on) why does a large popular open source engine use them so much??

Yes, and that's one of it's huge weak points. Being popular and open-source says nothing about whether or not it is well designed.

Quote:

Most of the time its better to have global accessibility as well.

That's amusing. Wrong, but amusing. Having global accessibility is usually a crutch; if its not there because you already have an unstructured and tightly-bound design, it will allow you (without much thought; accidentally) to create an unstructured and tightly-bound mess.

Quote:

I use singletons in engine design when there should be only one. Where having two would screw things up, or you simply shouldn't need more than one.

Then you're misusing them, because the second point ("or you simply shouldn't need more than one") means you simply should not create more than one, and the first point is rarely if ever true in game development (if you think its true, that's a sign that your design and/or implementation is broken, as I touch upon in the thread I linked).

Quote:

* FileSystem (keeps a list of archive codecs, loaded archives etc)
* ThreadManager (handles creation of named Win32 threads)
* InputManager (handles DirectInput enumeration etc)
* PluginSystem (loads and unloads plugin dlls)

- Renderer and Engine will be singletons too.

None of those need to be singletons, consequently, none of them should be.

Share this post


Link to post
Share on other sites
Hrm, so what's the point of singletons then? If they're such a crutch, why even use them in the first place? Personally I've never run into problems or even found them to be a restriction at all, but then again programming styles vary from person to person. I just don't see how it's anything more than a matter of style (assuming you're not actually crippling your project through outright bad design, but that goes without saying...)

Anyway, ignoring the singleton issue, how would the data in a graphic engine be manipulated? Should I shoot the data for each subsystem into my engine once it's ready, handle the engine-specific manipulations I want my vertices to go through, then render them? (Which would mean going through these steps a handfull of time each frame - nothing major peformance-wise I'd guess, just curious design-wise how not doing this in one step sounds.) From the comments I've gotten (and after a bit of consideration) cumulating everything into a vector doesn't sound like a great idea.

I think that'd be all I'd need - some means of managing and rendering the vertices my other subsystems produce. I can add other things as I need them in the engine afterwards (lighting, fog, shaders) and not have to worry (much; maybe a bit when I'll have to add normals for lighting ;) ) about my vertices anymore once that part's been handled...

Thanks for the input so far - I'm not expecting to write a perfect system the first try (let's face it, nobody should ;) ) but having the more important parts of the engine built around something solid and functional will be a great start.

Share this post


Link to post
Share on other sites
Singletons are only truly justified when (a) more than one instance of a class causes incorrect behavior and (b) when absolute global access to the object is required.

On the rare occasion when (a) is true in game development, (b) must still be satisfied. The correct use of singletons in game development is excedingly rare for that reason. The only system I've found to be justifiably argued (though not strictly required) as a singleton is as the basis for a logging class. The use of a singleton here is justified in that the file access should be centrally managed so that another instance of the logger doesn't attempt to access the same file (more than one instance is an error) and so that every class has access to the logger to log its state and error codes (global access is required). Truth be told, the satisfaction of condition (b) is mearly a convenience issue, as a reference to the logging class could simply be passed to each class, function or method that needed logging facilities. However, IMHO, the inconvenience of doing so (especially since you'd likely want all or some of the logging conditionally compiled out for the release,) simply makes the singleton approach the more sound choice.

[Edited by - ravyne2001 on May 23, 2007 5:40:45 PM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!