smurofergo
04-03-2006 00:43:35
To avoid reinventing the wheel, I've been searching for something to page meshes or objects on the terrain (along with the terrain - which btw, great job on PLSM2
..).
For example: I noticed in the demo (PLSM2 demo), that if you place a sphere and go far enough out (so that you see no terrain at all) the spheres are still visible.
Maybe I am thinking about this entire thing wrong, but it seems inefficient to have all the objects in my world in memory. The types of objects I'm talking about are trees, buildings, and other players (for example).
If something doesn't exist, and it is deemed useful (ie, I'm not wrong in my thinking), then I will begin work on it.
Anyways, how have other people populated their large terrains with objects, vegetation, etc?
Lshink
04-03-2006 01:58:04
I'm having the same troubles with water. It would be great if we could clarify this
HexiDave
04-03-2006 02:37:27
What you can do is use the load/unload listeners to check if your object is within the bounds of that tile and load/unload the objects with it. Here's some sample code:
Most of this was taken from the Wiki on Newton integration - create a class called PLSM2Manager and use this as the constructor:
PLSM2Manager(PagingLandScapeSceneManager* sceneManager)
{
loadTileDelegate=new PagingLandscapeDelegate();
loadTileDelegate->bind(this,&PLSM2Manager::tileLoaded);
sceneManager->setOption("addLoadTileListener",loadTileDelegate);
unloadTileDelegate=new PagingLandscapeDelegate();
unloadTileDelegate->bind(this,&PLSM2Manager::tileUnloaded);
sceneManager->setOption("addUnloadTileListener",unloadTileDelegate);
}
Declare these in the class:
PagingLandscapeDelegate *loadTileDelegate;
PagingLandscapeDelegate *unloadTileDelegate;
And the two functions you use inside the PLSM2Manager class:
void tileLoaded(PagingLandscapeEvent* event);
void tileUnloaded(PagingLandscapeEvent* event);
You can find out what page/tile you're on by using it sort of like this:
int pageX=event->mPagex;
int pageZ=event->mPagez;
PagingLandScapePage* page=PagingLandScapePageManager::getSingleton().getPage(pageX, pageZ);
int tileX=event->mTilex;
int tileZ=event->mTilez;
PagingLandScapeTile* tile=page->getTile(tileX, tileZ);
There are things you can do with the "page" and "tile" variables, but mostly this:
tile->getWorldBbox();
Now you can see if your objects are within the XZ plane of the tile - if they are and you're unloading the tile, then you can destroy the object, otherwise if you're loading the tile you can attach the object to the scene.
One thing to remember is when using this that (as far as I know) you have to declare a PagingLandscapeSceneManager instead of a SceneManager for your Framelistener:
virtual void chooseSceneManager(void)
{
mSceneMgr = (PagingLandScapeSceneManager *)mRoot->getSceneManager( ST_EXTERIOR_REAL_FAR );
mSceneMgr->setWorldGeometry( Ogre::String("paginglandscape2.cfg") );
}
Just make sure you change mSceneMgr to a PagingLandscapeSceneManager for the framelistener and things like that or you may have problems. I'm not sure if there's another way to just use the basic SceneManager calls, but I got a lot of problems when I tried it. It takes only a few minutes to adjust the program to use PagingLandscapeSceneManager instead - it uses all the same function calls since it's based on it.
My appologies if this isn't what you were looking for, but I'm pretty sure this is what you're after. Lemme know if you're having any problems - I'm going to be doing a clean integration of the same thing you're looking for in the next few days using the item loader I'm working on for my game (has physics and item info and things like that.)
smurofergo
04-03-2006 03:10:04
HexiDave, thats pretty much exactly what I was looking for. Didn't even think of using the onload/unload stuff (new to PLSM). The functionality is pretty much just sitting there.... now to find a way to splitup scenes...
I will be placing a city on the terrain, lots of buildings, etc.. Will need to make something to detect where the majority of an object is and place it in that tile.
Thanks for the insight =]
HexiDave
04-03-2006 03:27:18
Well, I don't have my editor open now, but I know you can get the AxisAlignedBoundingBox for an object (search the wiki - it's something like that) and you can get the min/max of an object's bounding box (i.e. (-x,-y,-z) (+x,+y,+z)) and just test the object's AABB to the AABB you get from that tile->getWorldBBox() function (it returns an AxisAlignedBoundingBox or whatever the type is.) Of course it would be faster to just test directly the AABB's X and Z values since Y is going to have little relevance.
Just make the load/unload functions go through your object scene (not sure what you'd use - maybe a map or array or something) and check it on each object. I'm thinking about making use of code I already have and use the STL "map" to check for a page/tile string (it's important to remember that each page might have 0-7 x 0-7 (64) tiles, but so will every page so when you name the tiles you preface it with the page's X-Z or you'll have a load of problems) and just organize everything inside the engine (in-game scene making.)
For example: I load up my game and select trees, houses, etc and place them down in game. The game will then title the tree, house, whatever as "Page4-2-tile6-3-GuildHall" in the STL map and I can look it up to move, edit or save the whole damn thing to a scene and reload it while working with the tile load/unload functions. I hear people say how slow "map"'s are, but it seems too functional to avoid using.
tuan kuranes
04-03-2006 08:58:31
thanks for sharing.
That would do a nice wiki article...
you have to declare a PagingLandscapeSceneManager instead of a SceneManager for your Framelistener
you don't have to anymore, nor that you have to link to paginglandscape2.lib, that was prior to delegate uses (and was main argument to use delegates).
hear people say how slow "map"'s are, but it seems too functional to avoid using.
I don't think it would slow anything (Ogre uses string map a lot ).
You can also register entity in a std::map<String, std::list<entity*>, each map cell containing a list of entity loaded on that tile.
You get tile in map using an identifier name "Page4-2-tile6-3"so you just iterate over given list to delete/hide/show them.
when a tile is removed, you removed it from map, so that map handles only existing tiles, reducing map search times.
HexiDave
04-03-2006 15:21:34
Didn't know about the PagingLandscapeSceneManager deal - I only really got into all that a few days ago and converted my code. Not a big issue anyways
After I get the system implemented, I'll be glad to write an article on it. I have one un-related bug that's killing me right now (over in the Artists & Content Creators section) that screws up the visual on the terrain with hardware animation.
smurofergo
04-03-2006 16:05:25
Don't mean to dig this thread back up, but would anyone find use of something that loaded .scene into a format that would be easily paged?
(I was thinking scenepager.list(pagex,pagey,tilex,tiley) is an entity list or something - since they are integers faster to do indexing than using a map) Maybe even help destroy/load the entity list with scenepager.destroy() scenepager.load() (same arguments as list)...
I will be needing something like that, so I wouldn't mind the extra bit of work to make it more generic (so anyone could use it) if it seems useful.
Anyways, just sharing some thoughts, I'll be working on getting the scene loaded and split first.
---
sidenote:
It almost seems like a good idea to actually override the scenemanager, so that adding a new entity, etc puts them into the list as well. Only problem there, is that it wouldn't work for a dynamic/moving entity.
HexiDave
04-03-2006 16:16:11
Well I'm using my own data format from XML to load a lot of different data that correlates with the objects in the scene, so I probably wouldn't be using it. However, it sounds like a useful function-set anyways so it couldn't hurt to generalize for others.