   portals and dynamic objects
  hi there.I'm having a problem trying to work out where to place dynamic objects in a portal scene when they cross a portal, i.e. they are in two different sectors.I first thought I would just put the object in each sector but then this means it could be rendered twice.I'm also trying to incorporate this portal scene managment into my scene graph so what I've done is use the observer pattern on each node (dynamic object), so that any time the node changes position the data is sent to any observers which in this case would be the sector.class SceneNode;class NodeObserver{public:virtual void setPosition(SceneNode* src, Vector3 newPos){}};class SceneNode{public:void setPosition(Vector3 pos){for(unsigned i = 0; i < observers.size(); ++i){observers->setPosition(this, pos);}position = pos;}void addObserver(NodeObserver* observer){observers.push_back(observer);}virtual void addChild(SceneNode* chld){children.push_back(child);}//private:std::vector<SceneNode*> children;std::vector<NodeObserver*> observers;Vector3 position;};class SectorNode : public SceneNode{public:virtual void addChild(SceneNode* child){child->addObserver(new Observer(this));SceneNode::addChild(child);}Portal* intersectsPortal(Vector3 start, Vector3 end){for(unsigned i = 0; i < portals.size(); ++i){if(portals->intersectsLine(start, end)){return portals;}}return NULL;}private:class Observer : public NodeObserver{public:Observer(SectorNode* sector): currentSector(sector){}virtual void setPosition(SceneNode* src, Vector3 newPos){Portal* portal = currentSector->intersectsPortal(src->position, newPos);if(portal){currentSector->removeChild(src);SceneNode* neighbour = portal->getNeighbour(currentSector);neighbour->addChild(src);currentSector = neighbour;}}private:SectorNode* currentSector;};std::vector<Portal*> portals;};class Portal{public:SectorNode* getNeighbour(SectorNode* node){if(node == a){return b;}else{return a;}}private:SectorNode *a, *b;};This means that whenever a node changes position the SectorNode will handle all the details of it moving from one sector to another through a portal, but I still can't figure out how I would handle the case when a node has an actual volume (i.e. bounding box) that is spanning a portal, what sector should it be in? if it's in the wrong sector it might not be rendered correctly, and if it's in both it will be rendered twice?[Edited by - staticVoid2 on May 6, 2009 8:08:52 AM]
  you could make make sectors overlap, so that the overlap is always larger than the largest movable object. That way it only has to be in one sector at the same time.An alternative is to have to have 2 portals, one to check which sector an object belongs to, and one for visibility.Personally, I wouldn't add an object to multiple sectors, to avoid special case code.   ;Quote:Original post by harveypekaryou could make make sectors overlap, so that the overlap is always larger than the largest movable object. That way it only has to be in one sector at the same time.An alternative is to have to have 2 portals, one to check which sector an object belongs to, and one for visibility.Personally, I wouldn't add an object to multiple sectors, to avoid special case code.but then what do you do if there is a large object that spans multiple sectors through portals?for example - say you had a train going through a subway tunnel, halfway through this tunnel you place a portal, if you are standing at the front of the train facing forwards while it's going through this tunnel then for a second or two the train will not be visible, not until the center point of the train passes through the portal?[Edited by - staticVoid2 on May 6, 2009 11:00:29 AM];  In this case can you not turn off portal visibility testing for the train? (during it's time through the portal)   ;  The obvious answer (which maybe you have already considered and discarded) is,Step 1: Use your portal system to mark certain objects as visible.Step 2: Render visible objects.;Quote:Original post by EmergentThe obvious answer (which maybe you have already considered and discarded) is,Step 1: Use your portal system to mark certain objects as visible.Step 2: Render visible objects.this would mean I would have to store the objects separate from the sectors they belong to. therefore I would lose all occlusion culling that portals offer.;Quote:Original post by staticVoid2this would mean I would have to store the objects separate from the sectors they belong to. therefore I would lose all occlusion culling that portals offer.Wat makes you say this?  My first comment is that this is not an either/or choice.  One simple data structure to consider might be a flat array of objects, and a graph structure of 'sectors' each of which stores indexes into this array.  That's just one example of a data structure that gives you a way both to refer to objects in a global way and to organize them into sectors so that you never need to iterate over the entire array.Now suppose that each frame, you begin with an empty "stuff to render list."  Then, as you navigate your scene graph with portal culling, rather than rendering objects at that time, just add references to them to your "stuff to render list."  Then, after you've navigated your scene graph, render the stuff in your "stuff to render list."  Finally, clear the list in preparation for the next frame.This will give you the behavior you want so long as you don't add an object to your list that is already in it.  You can enforce this easily in O(1) time by associating an "am I in the list?" flag to each object (and not adding objects to the list that already have this flag set).  At the end of each frame, you'd have to clear this flag for each object in your "stuff to render list.";  my stupid but simple solution was to assign object to portals when they're passing them (portals are like zones the same class for me), when culling one room, I also check all connected portals.the beaty of this solution is that I dont have to check room->portal->room->portal, but simply room->room->room which makes it fairly simple. beside that simplycity, my portals also have  volume (just like every room or zone has), so it's straight forward for artist to make window opening with actually some depth, this way the culling is nicely improved, as you sometime cannot see neighbour rooms alghouht you see the portal itself, just like realworld.there are several ways to avoid testing portals twice, the easiest ist probably to mark them with the current frame ID.if an object crosses several portals, I've assigned it to the nearest portal to the player, this worked out for me so far for rendering. collision did not work two zones in distance, tho. but no artist no game programmer or designer ever complained bout that.;Quote:Now suppose that each frame, you begin with an empty "stuff to render list." Then, as you navigate your scene graph with portal culling, rather than rendering objects at that time, just add references to them to your "stuff to render list." Then, after you've navigated your scene graph, render the stuff in your "stuff to render list." Finally, clear the list in preparation for the next frame.I was thinking of doing something like this but I wasn't sure of the performance impact - I never though about flagging the objects. I take it this flag variable would be just a private member of the scene node?   