Sign in to follow this  

Looking for design advice

This topic is 2851 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'm creating a level editor for a 3D game. The user is able to place down "brush" objects which shape the environment using constructive solid geometry. Other objects can also be placed - doodads, static meshes, lights, etc. These objects inherit from a WorldObject class, which contains a transformation matrix, visibility flag, and virtual methods that allow the matrix to be set, and the object's axis aligned bounding box to be retrieved. In this way groups of world objects can be selected and manipulated, and their selection box can be drawn without needing to code separate cases for each subtype. I was hoping to be able to control the behavior of the child classes through virtual base methods, but I ended up resorting to using manager classes that run switch statements to determine what child class the object in question is, and execute separate code to handle each one. My design doesn't seem to be affording me as much convenience as I'd hoped. Take the CsgBrush objects for example. When one of these is created, it's added to an octree structure. If the brush is transformed (moved/scaled/etc), it is removed from the octree and reinserted, and various boolean operations are recalculated, etc. What should happen if I have a group of base class pointers and call the delete method on them? Maybe I should have a virtual delete method which, in the case of CsgBrush types, automatically calls the relevant methods to update the state of the octree. The same goes with selecting the object, or transforming it. These objects rely on an octree structure. Other WorldObject types will have their own spatial data structures to access. Currently I use a GraphicsManager class which runs a switch statement to check what type the objects are, and handles their transformations separately. This results in the manager class, and all my other managers becoming really really big, and I don't know how I can stop them from growing out of control. Should I give more control to the WorldObjects themselves? Should the Brush objects all contain pointers to the octree structure so they can handle their own insertion/transformation/deletion? I should mention that I'm not using singletons/global variables so a given instance of an object can only access the octree if it contains it's own pointer to it. Even though the octree is one of those objects I only ever use one of.

Share this post


Link to post
Share on other sites
So the problem is that operations on these WorldObjects affect a wide variety of other data structures, in a way specific to the subclass, and all the code to manage that is winding up in other "manager objects"?

To be honest, I've never worked with any spatial data structures like that so I don't really know how it looks on your end, but perhaps you could switch things around so that your octree structure hands out OctreeNode (Is that the right name?) objects, which handle the octree-specific stuff. CsgBrush objects, and anything else that would ordinarily be added to an octree, would contain one of these objects. This would also make your Octree class more re-usable, because it wouldn't be dependent on anything specific to your game, and all the octree-specific stuff is wrapped up in these two classes, and maybe a few helpers.

Share this post


Link to post
Share on other sites
My brush objects actually do contain a list of octree nodes they're in, but they don't operate on this data themselves. The octree is responsible for that.
When a brush is moved, the octree needs to be notified so it can perform the necessary housekeeping. I guess I can use some form of the observer pattern, so my WorldObjects notify the necessary structures when they change.
But at the moment I don't think I'll bother, as doing so will only solve this problem in particular. The manager classes will still need to run switch statements to determine how to handle other operations such as selecting objects with the mouse. I've probably spent as much time mulling over design issues as is warranted.

Share this post


Link to post
Share on other sites
But can't the Octree be notified of the move through the octree node object? Something a bit like this:

struct Brush{
OctreeNode onode;
Brush(Octree& octree){
onode = octree.GetNewNode(/*whatever it needs*/);
}
Move(...){
//OctreeNode tells the Octree to perform the necessary book-keeping
//without Brush knowing anything about it
onode.Move(...);
}
};

Share this post


Link to post
Share on other sites
The brush can be in multiple nodes at a time. It contains a vector of these nodes. And each node can contain multiple brushes.
But yeah I can notify the octree through a brush.move() method.

Share this post


Link to post
Share on other sites
How about having multiple spatial data structures, for each type. Say GraphicsManager operates on octree that has only graphics WorldObjects in it. You wouldn't need a switch then.

Share this post


Link to post
Share on other sites
I prefer to have many structures. When I for example want to query only lights, I don't need to check the object types in the data structure or traverse big branches just to find zero lights.

Share this post


Link to post
Share on other sites

This topic is 2851 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this