The Portal Connected Zone Scene Manager (PCZSM) was created by Chaster. Useful threads on the forums related to this scene manager are here and here.
It is currently available as source code at the SVN HEAD (that is to say, the most up-to-date development-oriented, non-stable version of Ogre; this version of Ogre may break some code designed to work with the last stable Ogre release, Eihort). The current SVN directories can be browsed online at ogre.svn.sourceforge.net/viewvc/ogre/trunk/PlugIns/PCZSceneManager/; or follow the directions on this wiki page to help you figure out how to download this source code using SVN from command line, or the GUI TortoiseSVN. The only actively maintained version is the one which is tied to the trunk of Ogre.
Table of contents
The current (1.2) PCZSM readme file reads:
This document gives basic information on the usage of the PCZSceneManager. It is not complete, and will change & expand as needed. Note that as of this writing, the PCZSM has not undergone very extensive testing, nor is it optimized very much. Assistance in these two areas would be greatly appreciated. For support or to report bugs, please see the Developer Forum at Ogre3D.org
Cheers,Eric "Chaster" Cha
Using the PCZSM
NOTE: For an example of PCZSM usage, see the PCZTestApp Application. It is probably a lot easier to understand than trying to figure it all out from this.
Loading and Initialization
The PCZSM is loaded just like any other Scene Manager plugin. Included in the standard PCZSM plugin is the "default" zone. If the user wishes to utilize the OctreeZone or TerrainZone, the "PLugin_OctreeZone" should be loaded *after* the PCZSM plugin is loaded.
Before using the PCZSM, the PCZSceneManager::init(zoneType) function should be called. During intialization, the user specifies what type of zone (ZoneType_Default, ZoneType_OCtree, ZoneType_Terrain) the PCZSM should use for the default zone. The default zone is the zone where entities are placed if they are not specified to be in other zones.
Once the PCZSM has been initialized, the user can proceed with creating zones (PCZSceneManager::createZone(zoneType, zoneName)). Zones can be anything from the outdoors (i.e. a Terrain) to a room in a building, or a tunnel in a dungeon. Zones can be of any size or shape, and can move.
NOTE: In the PCZSM, sky rendering (domes, boxes, planes) is associated with a specific zone. For example, if the user has a building on a terrain, the sky could be associated with the terrain (i.e. the "outdoors") using the function PCZSceneManager::setSkyZone(zone). This tells the PCZSM to only draw the sky when the designated zone is visible. (i.e. only draw the sky when the 'outdoor' zone is visible). Usually, the Sky should be associated with the default zone (which is usually used as the "all encompassing exterior zone").
Once the user has created a zone (in addition to the default zone), they can create portals to attach two zones together. To do this, the user just creates a new Portal instance (i.e. newPortal = new Portal) and sets the portal corner points, attaches it to a node, and then adds it to the zone (see PCZTestApp -> RoomObject.cpp -> createPortals() function).
NEW AS OF 9/25/07:
To create a portal, the user just calls PCZSceneManager::createPortal().
NOTE: The user should NOT just instantiate a portal manually (i.e. portal = new Portal)
because the clean up of portals is handled by the scene manager directly.
Instantiating portals using the C++ 'new' command will result in memory leaks
and errors if the scene is destroyed and recreated.
To destroy a portal use PCZSceneManager::destroyPortal(Portal *p) or
PCZSceneManager::destroyPortal(String & portalName).
Then set the portal corner points, attaches it to a node, and then adds it
to the zone (see PCZTestApp -> RoomObject.cpp -> createPortals() function).
NOTE: Portals currently only connect different zones. The user can't connect portals to the same zone yet (i.e. no teleporters). This functionality could be added later.
NEW IN VERSION 1.2: Portals can take 3 different forms: quad portals, AAB portals, and Sphere portals. AAB and Sphere portals do not add any culling planes to the frustum, and just serve to serve as enclosures for zones which aren't naturally surrounded by geometry. They function a little different than traditional quad portals in that they are volumetric, instead of planar (crossing is determined by going from "inside" to "outside" or vice versa).
Quad Portals require 4 corner points which are co-planar and form a polygon which is convex. Quad Portal corners are specified in right-handed counter- clockwise winding order so that the norm of the portal would be facing the viewer.
AAB Portals require 2 corner points (minimum & maximum corners) and form an axis- aligned box around the zone. IMPORTANT: The AAB portals that are associated with a node require a node which has the correct size AAB (node->_getWorldAABB()).
Sphere Portals require 2 corner points (center point, and point on the surface of the sphere).
The "direction" norm of AAB and Sphere portals is specified as either Vector3::UNIT_NEGATIVE_Z or Vector3::UNIT_Z. The first corresponds to a portal with norm facing 'inward' and the latter corresponds to a portal with norm facing 'outward'.
NOTE regarding Portal Norms: The Norm of a portal should always point away from the zone the portal leads to. Another way to think of this is a node will only cross a portal if it crosses the portal traveling opposite direction of the norm).
Portals also (currently) require a "matching" portal for proper scene traversal. In other words, portals always exist in pairs - one in each zone connected and co-existing in the same location, but facing in opposite directions.
While it is technically not required that a portal be associated with a scene node, it is STRONGLY recommended. Use Portal::setNode() to associate the portal with a scene node. Once the portal is associated with a scene node, it will move with the scene node (including rotations or translations). Because of this, it is also highly recommended (although not required) that the node a portal is associated with be located at the center of the portal.
NOTE: Scaling of a portal is not yet *tested*. Scaling a node should scale the portal (but don't cry to me if it doesn't work right yet...) Also, if you don't associate the portal with a scene node, you will NOT be able to move it short of redefining the cornerpoints manually (and who wants to do that?).
Once all portals in the scene have been created, the user can either manually assign their zone targets (i.e. the zone which they connect to) or they can call PCZSceneManager::connectPortalsToTargetZonesByLocation() to do it automatically. Note that this function requires all portals to have a matching portal in the target zone.
Creating Objects / Entities
Once the zones and portals have been created, the user can create objects/entities. The user should use SceneManager::createSceneNode() to create all scene nodes.
NOTE: ALL OBJECTS *MUST* BE ATTACHED TO SCENENODES!!! Unlike the other SM's available in Ogre3d, the PCZSM relies on Scene Nodes to determine zone locality of all entities - including cameras and lights. Consequently, when a camera (or light) is created, the user should also attach the camera (or light) to a scene node and use that node to manipulate the object.
SceneNodes should be assigned (by the user) to a zone upon creation of the SceneNode. Use the function "PCZSceneManager::setNodeHomeZone(node, zone)" to do this.
If the user doesn't do this, the PCZSM will try to figure out which zone the node belongs in using volumetric testing, but since there are situations when this can fail, it is highly recommended that the user does so explicitly instead of relying on the SM to figure it out. Note that this only has to be done when adding a node to the scene. Once the node is in the proper zone, the SM will handle moving it to other zones as necessary.
NOTE: In order for the automatic zone assignment function to work, zones must have an "enclosure" object/node assigned to them (using the "PCZone::setEnclosureNode() function). The enclosure node (or more specifically, the object attached to it) supplies the axis-aligned bounding box that determines the bounds of the zone. So for example, the enclosure node/object for a room would be the model of the walls, ceiling, and floor (assuming they are all modeled as one object or at least all attached to the same node). See the PCZTestApp for an example.
I have implemented Scene Query functions for Default & Octree Zones. In general, they are used the same way as Scene Queries for any other Scene Manager, with one difference. The user must specify the "start zone" for any scene query using XXXSceneQuery::setStartZone(zone) where "XXX" is Ray, Sphere, AxisAlignedBox, et cetera.
Q: Are you making use of multiple other scenemanagers designed for the individual types of scene to manage all of the objects in each of those scenes, and then masking that all behind one PCZSM?
A: I have only implemented Default (i.e. flat hierarchy), OctreeZone, and TerrainZone, and those 2 (Octree & Terrain) are based on the OctreeSM and TerrainSM. They share a LOT of code (actually MOST of the code) with the original SM's, but they have a pretty significant amount of code changed/added/massaged to make them into Zones. It's not a simple, "change a few lines to make it work", it's more like "change/add/remove several hundred lines of code" to make them work. The changes are not trivial. That said, they aren't full rewrites either.
Q: You aren't having to duplicate the effort of others to emulate many scenetypes within one manager...?
A: It's somewhere in between. I didn't have to start from scratch, but it isn't a simple drag & drop either. If you want to see how much is different, compare the OctreeZone (TerrainZone) source with the OctreeSM/TerrainSM. It isn't terrible, and it's FAR from a full rewrite.
Q: Am I right in thinking I can design scene-files (my own implementation of dot-scene, designed to store about 1-2 miles squared of world area) that internally switch between different types of scene management?
A: The short answer is - yes. You should be able to implement your own scene saving/loading routines fairly easily. Everything is pretty straightforward, and I would think you wouldn't have any trouble if you are an experienced coder. Note that I have NOT implemented any default way to store/load portals/zones, because I didn't want to dictate implementation of a feature which everyone has different ideas about (loading/saving), but it should be trivial for you to do yourself after looking at the PCZTestApp code. The way zones and portals are defined is VERY simple. There are a few crude routines in the PCZSM for loading a zone, but they are mostly for setting up the default zone, and they could very well change as the PCZSM evolves. You'd set up the zones and portals. The PCZSM would handle the rendering.
Q: Would the most practicable way to handle preloading areas then become to load zones at the closest edge of the existing scene objects as one gets closer, and unload ones at the farthest edge? Is this a reasonably expected behavior?
A: I believe so. While I haven't tried it, I *believe* that you should be able to simply load/unload zones as you need. Keep in mind that there may be some tricky parts with Portals that you will want to be careful about when unloading zones, but I don't see any technical/design reason which would prevent one from doing as you describe. In fact, with the (new for version 1.2) AAB & Sphere portals, you can have multiple TerrainZones in the scene, and tile them next to each other and load/unload them as you need (I think). Of course, loading a whole TerrainZone would freeze your rendering for several seconds, but you might be able to find a way around this by streaming in a zone piece by piece... (again, I haven't done ANY dynamic loading/unloading of zones, so I'm talking very theoretically here).
Q: Is there any way to use your scenemanager's logic to figure out what _are_ portals between zones and treat them correctly, rather than defining them all (e.g. 300 skyscraper windows onto a street) as portals in a world editor or in explicit code?
A: No. You must tell the PCZSM where to put portals and define them. It has no functionality for doing this itself. Furthermore, I would NOT recommend using an automated portal generator (such as WorldMinion) because it will generate waaaaay too many portals for this type of SM. Of course, that is MY opinion, but others may find differently. If you want to give it a go, then by all means...
Q: Do I need any other scenemanagers in DLL or source form for this to work?
Q: The readme says that your skybox/dome/whatever should be associated with your terrain zone if you have terrain + buildings. What if you have multiple adjoining terrain zones? Does the sky of one particular terrain zone encompass all of them + the other building zones? Would my adjoining terrain zones need to have portals that covered their whole skies? What if there was mountainous terrain on them and the height of land changed — just put the portal as a plane at a height greater than the highest mountaintop?
A: I would suggest you: make the sky dome/box/whatever associated with the default zone. Then make your multiple terrain zones as "subzones" of the default zone (i.e. by using the AAB portals to surround each terrain zone). This may be a bit tricky with the AAB portals (which will be different sizes because your terrains will have different maximum heights), but give it a go...
Q: I'm assuming the Portal setup has no bearing on what physics properties we might give nodes/meshes, and how collision relates to that.
A: Correct. It's entirely independent. Although I think that zones would provide a nice partitioning of objects for collision detection. But you don't have to use that particular facet of the PCZSM, I just think it might be helpful...
Q: I'd like to make life easier on artists doing level editing by restricting each of my .scene files to one in-game zone, so one .scene might be a building, with a 'streets' zone in another scene. As I understand it, a portal at the edge of one zone needs to match up with a portal at the edge of another. Is there any particularly simple or intuitive way to associate the portals on the edge of one of my scenes with portals on the edge of another, when you can only edit one scene at a time in my editor? Or I guess this is just going to have to be a part of my macro-scenes world structure strategy, in terms of setting world co-ordinates for the corners of my scenes so I know they'll align?
A: Here is the way *I* would do it: 1) Have a zone for the "outside" - this includes the streets, mountains, etc. Whatever is not a building. Make this a scene for your artists to manipulate in your editor. 2) Make each building a "scene". The exterior of the building has portals at each window & door which connect to the inside rooms of the building. Each room in the building is a zone with corresponding portals matching with other rooms or the exterior of the building. 3) When you want to put together the "whole scene", you place individual building "scenes" in the "outside" scene. This way, the buildings are basically placeable objects and can be manipulated/placed/edited separately from everything else. Same goes for the outside. Since the building "scene" files will include their exteriors, you don't have to worry about portals lining up with "the outside". You just need to make sure you associate the portals on the exterior of the buildings with the outside zone when you place the buildings in the outside scene. You (or your artists) are going to have to make sure everything lines up, but if you do it the way I describe above, it will be very easy for them to make sure they do (line up). The PCZSM has a function to "automatically" connect portals which are "matching" (physically) though, so that should help at least.
Q: How perfectly do two adjoining portals' co-ords need to match?
A: I coded the automatic portal connector to allow for some "slop", but I have never fed it anything other than "perfect" portal pairs. I'm not sure what would happen if you tried to use portals which didn't match perfectly (might work fine, might not).
Q: If one .scene/zone is a 30-storey skyscraper with a bunch of rooms/halls/elevators/stairways in it: should that be the 'Default'/'raw' PCZSM zone type, or octree? I know BSP's not recommended.
A: There is not a straightforward answer to this question. I would not make the entire interior of the skyscraper one big zone. It would most likely render too slow because you would be drawing the entire zone each frame. If it were me, I make each room a zone (of the Default or Octree type). That way, you are only drawing a small subset of the interior of the Skyscraper at any given time. However, if your rooms are very simple, then in order to maximize batching, you could make several rooms into a single zone.
Q: I believe meshes such as player avatars can be defined in one zone (i.e. wherever they spawn) and then, as they walk, traverse without a blip into being managed by a different zone. Is that right? This is assuming you have one central scenenode for your player's centre of gravity, with whatever else childed to that (e.g. hair).
A: Yep. That's the idea. However, I haven't tested much with hierarchies of entities (entities with children which in turn have children etc. etc.) but I put code in there to handle it, so it *should* work. If it doesn't let me know.
Q: What takes responsibility for rendering the building exterior if it's not part of a zone? Does it become part of the world's 'Default' zone? Do all non-zone-assigned nodes live there?
A: Yes. You would assign the exterior building node to the default zone. If you don't specify a zone for a given node, then the PCZSM tries to figure out which zone it belongs in by doing bounding volume checks. If it can't find a zone, then the node gets put in the default zone.
Q: Quote: "When a character is wandering around the terrain zone, and then tries to walk inside the building via the door, they will pass through the buildlng exterior portal, and be transported to the interior room zone." Your use of the word 'transported' worries me a little. Does this functionality actually involve destruction and recreation of objects in Ogre terms, or simply moving them?
A: No. It means that the zone pointer of the node gets re-pointed to the interior room zone. No destruction/creation or moving going on. Just a new pointer value. When I said "transported" I was speaking in a conceptual sense, but really, nothing more than a couple pointer re-assignments. Memory "size" of an object won't have any effect.
Q: If you define a stable node (e.g. lamppost) to be in one zone and then define a new zone inside the old zone which encompasses where that node happens to stand, does it automatically get reassigned to be rendered as part of the new zone?
A: No, unless this is during scene creation (i.e. before any nodes have been updated). In the scenario you describe, you will need to reassign the node to the new zone. EXCEPTION: If the "new" zone you create is an AABB or Sphere portal, the lamp post *might* get automatically re-assigned since these portals use simple "inside/outside" rules instead of "crossing over" rule to decide whether or not a node has "crossed" the portal. To be honest - I'm not sure. But give it a try and see what happens.
Portals exist in pairs. For a building, you will have a model of the exterior of the building. This "skin" will have portals at the windows and doors *which connect to their matching portals on the interior*. Say you have a very simple building. It just has one room, and one door which connects the outside of the building to the inside room. The building will have 2 models - one for the exterior of the building, and one for the interior room. The building will have 2 portals - one on the outside of the building which leads to the inside room, and one on the inside room which leads to the outside of the building. The portals are in the same location, but just facing opposite directions. The room is a zone. The building exterior is NOT a zone.
So say you group all this together in a file of some sort. The building has a node (call it buildingNode), which the exterior of the building is attached to, and the exterior door portal is associated with. The interior room has a node (call it roomNode) which is a child node of the buildingNode. The interior portal (which leads from the interior room to the exterior of the building) is associated with the roomNode. The room is a zone, and the zone is associated with the roomNode. Now, if you move the buildingNode, the entire group will move with it - the building model, the room model, the portals, and even the room zone.
You create a Terrain zone (with associated terrain mesh of course). You then place the building group onto the terrain. Then, you tell the exterior door portal that it is owned by the Terrain Zone. (portal->setZone(*theterrainzone)). Once all the portals are associated with their proper Zones, you can then "connect" them (manually, or by using the "automatic" function). Now, when a character (or whatever) is wandering around the terrain zone, and then tries to walk inside the building via the door, they will pass through the buildlng exterior portal, and be transported to the interior room zone.
The portals for a building can be encapsulated with the building if you design it right. Do not assume that additional portals need to be added when you place the building in order to "hook it up" to the outside world. This isn't necessary if the "exterior" portals are saved with the building - you just have to tell them they are associated with the outside zone at the right time.
You can have your default zone occupy the entire outside world. Then have terrain zones arranged in "tiles" which you load/unload as you move around. Zones don't really have any intrinsic size restrictions.
Having a zone per room is actually a HUGE ADVANTAGE for you and your artists. However, you can setup zones to encompass multiple rooms (say, a whole floor of a building) if you so desire. Performance will vary on many factors, and in actual use, you may find that grouping several rooms in a zone provides better performance than a single room per zone - performance testing is in order.