Jump to content
  • Advertisement
Sign in to follow this  
brega

[C++] Help me choose container

This topic is 2815 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 am continuing "pursuit" to solve my problem that i have started here.

Here is what am i doing and what i need:

I am trying to create scene manager class and manage resources that it holds.
I need some type of container that can hold just pointers to data/resources that does not
allocate/deallocate nothing since i am doing it by hand. Here is some half pseudo (inserting into container):

LightSceneElement* SceneManager::AddLightSceneElement(SceneElement* parent, ELightType type)
{
LightSceneElement* pLight = new LightSceneElement();
pLight->Init(this, parent, type);// intit basic properties
conatainerLights.insert(pLight);// this should be my imagenary container
return pLight;// return pLight so i can take control elswhere and manipulate it
}


then when finished delete all data:

void SceneManager::Close()
{
...
foreach element in containerLights
{
LightSceneElement* pLight = *containerLights.iter;//obtain pointer
delete pLight; //delete data that it points to
pLight = 0;
}
}


It should have fast function to sort my elements (that i have talked about in linked thread)
and it should be fast at inserting elements:


void SceneManager::Draw()
{
...
// for example render static meshes
container<SceneElement*> containerNotCulledStaticMeshes;// name shoud be obvious
foreach static mesh in containerAllStaticMeshes // container that holds all static meshes
{
if seen by camera
{
SceneElement* pCurrentMesh = *containerAllStaticMeshes.iter;//obtain pointer
containerNotCulledStaticMeshes.insert(pCurrentMesh);//just insert pointer
}
}
...
containerNotCulledStaticMeshes.sort(SceneElement::BackToFront());//sort meshes
foreach static mesh in containerNotCulledStaticMeshes
{
SceneElement* pElement = *containerNotCulledStaticMeshes.iter;//obtain pointer
SetShader();
pElement->Draw();
}
}


Is there some kind of "container" for this?

Share this post


Link to post
Share on other sites
Advertisement
std::vector.

.insert() = .push_back()

As for culling, it can be done in-place:
typedef std::vector<MeshFoo *> Meshes;
Meshes meshes;
Meshes::iterator i = std::partition(meshes.begin(), meshes.end(), IsVisible());


std::sort(meshes.begin(), i, reverse_sort);
std::for_each(meshes.begin(), i, DrawWithShader();
where the last parameters are relevant functors, for example:
struct IsVisible {
Camera * c;
bool operator()(MeshFoo * p) {
return c->can_see(p);
}
};


Since vector contains pointers it doesn't allocate anything as such, but will expand as needed.
The second pass uses in-place (via partition) which avoids any extra allocations as well. It's also quite efficient.

Also, if at some point you feel like it, all of the calls above can be converted almost literally to something like TBB to allow concurrent processing. The above is as fast as it gets algorithmically, the rest would require understanding of actual data and organizing that.


As for removal - erase/remove_if is algorithmically optimal, single-pass method.


If the algorithms are coded generically, then all algorithms above work with plain arrays without change (baring the obvious push_back which needs to be implemented and iterator, which would be just plain pointer). There is no reason to do this unless data needs to be aligned_malloc()ed.

Share this post


Link to post
Share on other sites
Why arent you using a smart pointer of some kind? such as a std::tr1::shared_ptr, boost::shared_ptr, or maybe even roll your own more specific smart pointer for resources?

eg.
std::vector<std::tr1::shared_ptr<ILight>> objectContainer;
//...

objectContainer.push_back(new DirectionalLight(...)) // blah, not sure if mixing different types is a good idea here..
objectContainer.push_back(new PointLight(...)) // but its only example code so its all good :)
objectContainer.push_back(...)



Then you wont have to loop through and manually delete all lights.. I dont know, I have an embaressingly small amount of experience with this kinda thing (ill get there someday) so umm maybe this isnt what you want. just a suggestion..

Share this post


Link to post
Share on other sites
Quote:
Original post by CodeCriminal
Why arent you using a smart pointer of some kind? such as a std::tr1::shared_ptr, boost::shared_ptr, or maybe even roll your own more specific smart pointer for resources?
There are many classes of problems where the life cycle of objects is well defined.

Create stuff in the beginning, keep updating for a while, cleanup everything.

shared_ptr is just that - pointer with shared ownership. In those cases it quickly becomes very tedious to keep track of who exactly must cleanup what. But with single owner and well defined entry and exit point, there is no need for that.

The only important gotcha is to either disable copying (assignment, copy constructor) or properly implement deep copy on the class holding the container. Otherwise actual objects may get deleted multiple times.

Share this post


Link to post
Share on other sites
@Antheus
Quote:

...std::partition


YEESSSS. This is the thing that i was looking for. Thanks greatly for hint and clear explanation.

There is only one thing that i don't understand.
What "TBB" stands for? Is it something about multithreading?
Since i am still beginner i'll stick to just one until i learn more about it.

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!