I'm trying to delete a zone..

yubgipenguin

24-12-2008 04:00:00

But it crashes when I use this code:

std::string terrain_cfg("terrain.cfg");
std::string zoneName("Terrain2_Zone");
PCZone * terrainZone = createTerrainZone(zoneName, terrain_cfg);
((PCZSceneManager*)mSceneMgr)->destroyZone(terrainZone, true);


which is by the way a code snippet from PCZTestApp.cpp with added:
((PCZSceneManager*)mSceneMgr)->destroyZone(terrainZone, true);

It seems like it is supposed to work but crashes without any msg.

And I actually first tried it with Python-Ogre and same result. (well it's same code anyways.) So no weird c++ problem.


It crashed on ExampleApplication.h line:92
mRoot->startRendering();
here with Access Violation reading location 0xbf000000 and I'm guessing something is wrong on deletion process.


PS. I also tried deleting portals first and then deleting zones and it still crashes...

Chaster

26-12-2008 20:41:34

You must have a at least the default zone to render anything. Why are you deleting the zone?

Chaster

yubgipenguin

27-12-2008 02:13:46

Well I created second zone but it still crashes...


I want to delete a zone so I can load and unload different terrains dynamically. Sort of like Grand Theft Auto 3~4 series..

Chaster

29-12-2008 01:27:40

Are you deleting the default zone or the 2nd zone you created?

Also, which zone is the camera in? If you delete the zone the camera is in, it'll bomb. Make sure you don't do that.. heh.

Chaster

yubgipenguin

29-12-2008 13:59:49

Well I solved problem....

First I tried deleting camera(viewport) and it still crashed.
And I dug into source code and found out that it also creates PCZSceneNode...
So I deleted that PCZSceneNode and it worked fine without crash.


But it seems like associated ZoneData is still not being deleted. When I tried to recreate deleted Zone with same name it said:


OGRE EXCEPTION(4:): A ZoneData associated with zone Terrain2 already exists in P
CZSceneNode::setZoneData at ..\src\OgrePCZSceneNode.cpp (line 251)


How do I free that ZoneData?


And I can't even find out the where the setZoneData gets called. It doesn't get called in any files of PCZSM plugin source codes. Where is it get called?

Chaster

30-12-2008 00:52:06

Something is wrong with the way you are deleting PCZSceneNodes. The node zone data gets cleared and deleted in the destructor for a PCZSceneNode. Make sure you aren't casting it to a regular Ogre SceneNode and calling the wrong destructor.

SetZoneData() is currently only used in OctreeZones (since Default Zones don't need any special data). (see void OctreeZone::createNodeZoneData(PCZSceneNode * node)

Chaster

yubgipenguin

30-12-2008 07:03:41

1. I have called PCZSceneNode::removeAndDestroyChild(terrainZone2->getEnclosureNode()->getName()) to remove it...
2. And then I tried PCZSceneManager::destroySceneNode(terrainZone2->getEnclosureNode()->getName()) after deleting all children with terrainZone2->getEnclosureNode()->removeAllChildren().
(And I deleted attached Entity too..)


Method 1. wasn't gonna crash.
Method 2. crashed it with new viewport(if I don't recreate viewport it wouldn't crash.)
Both didn't free the ZoneData.

I knew PCZSceneNode::~PCZSceneNode would free the ZoneData and that's why I tried deleting a PCZSceneNode in the first place...
But it seems like it doesn't work? And those two are only good removing methods I know about...

Sorry for asking but can you just give me working example of deleting a Zone? :)

Thanks!




PS.

I've done this:

name = terrainZone1.getEnclosureNode().getName()
root = pczSM.getRootSceneNode()
tSN = root.getChild(name)
tSN.removeAndDestroyAllChildren()
root.removeChild(name)
tSN.getCreator().destroySceneNode(name)


It's in python but you get the idea, it's same as doing SceneNode::removeAndDestroyChild(name).
tSN.getCreator().destroySceneNode is correct PCZSceneNode::destroySceneNode(not SceneNode::destroySceneNode) and this function seems like not calling PCZSceneNode::~PCZSceneNode.

So, it wasn't freeing ZoneData, but it wouldn't crash anymore because I did root.removeChild(name) which is omitted from the previous method.

And I think the reason destructor of PCZSceneNode not being called is because PCZSceneNode::destroySceneNode calls SceneManager::destroySceneNode( name ); to delete it.

It gets casted as SceneNode*


OgreSceneManager.h:
typedef std::map<String, SceneNode*> SceneNodeList

OgreSceneManager.cpp:
void SceneManager::destroySceneNode(const String& name)
{
SceneNodeList::iterator i = mSceneNodes.find(name);
...
...
OGRE_DELETE i->second; // (i->second is SceneNode* not PCZSceneNode*)
}


yeah so to fix that, void PCZSceneManager::destroySceneNode( const String &name ) in OgrePCZSceneManager.cpp should be modified... unless you have another working method for deleting a zone, I wouldn't mind using that. Thanks...

PS2. Aww mSceneNodes is a protected member. :(
So, better way of doing it might be calling a PCZSceneNode's destructor directly(should work) or just rename that destructor to another function and call it.


void PCZSceneManager::destroySceneNode( const String &name )
{
SceneNode * on = ( getSceneNode( name ) );

if ( on != 0 )
{
// remove references to the node from zones
removeSceneNode( on );
((PCZSceneNode*)on)->~PCZSceneNode();
}

// destroy the node

SceneManager::destroySceneNode( name );

}

a dirty hack but should work.

yubgipenguin

01-01-2009 07:18:49

I've been not using C++ for too long.

~Node() is virtual so ~PCZSceneNode should have been called even if it's casted as Node* or SceneNode*...
This is weird. Now I have just no idea why.

Chaster

04-01-2009 18:12:16

Yubgipenguin,

I'm kind of at a loss too. I'm not sure why it's not working for you since the destructor of PCZSceneNode deletes the ZoneData (as you can see looking at the code). I have deleted PCZSceneNodes many times (heck, all the time) and it works fine for me... So I'm kind of at a loss because I can't reproduce your problem.... I'll try to take some time this week to look into better reproducing it, but the usual disclaimer: I'm always swamped...

Chaster

yubgipenguin

04-01-2009 19:16:18

Here's my conclusion...

I created a zone with createZone function(not createTerrainZone function from PCZTestApp) and it didn't have EnclosureNode at that time and it still complained about ZoneData already being there, when I delete and recreate the Zone.
(OGRE EXCEPTION(4:): A ZoneData associated with zone Terrain2_Zone already exists
in PCZSceneNode::setZoneData at ..\src\OgrePCZSceneNode.cpp (line 251))

The code I'm having problem is this:

terrainZone = pczSM->createZone("ZoneType_Terrain", "Terrain2_Zone");
pczSM->destroyZone(terrainZone, true);
terrainZone = pczSM->createZone("ZoneType_Terrain", "Terrain2_Zone");

If you don't have the same problem with me with this code please let me know...

I retrived all the nodes before I destroyZone and there wasn't a single node related to the Zone I have created(Terrain2_Zone).

Ogre/SceneRoot
Terrain1_Zone_Node
Terrain1_Zone_page[1]_Node
Terrain1_Zone_tile[1][0,0]_Node
Terrain1_Zone_tile[1][3,1]_Node
Terrain1_Zone_tile[1][6,3]_Node
Terrain1_Zone_tile[1][3,0]_Node
Terrain1_Zone_tile[1][3,5]_Node
Terrain1_Zone_tile[1][5,6]_Node
Terrain1_Zone_tile[1][7,6]_Node
Terrain1_Zone_tile[1][1,7]_Node
Terrain1_Zone_tile[1][5,0]_Node
Terrain1_Zone_tile[1][5,1]_Node
Terrain1_Zone_tile[1][7,4]_Node
Terrain1_Zone_tile[1][2,5]_Node
Terrain1_Zone_tile[1][5,7]_Node
Terrain1_Zone_tile[1][2,7]_Node
Terrain1_Zone_tile[1][4,3]_Node
Terrain1_Zone_tile[1][5,5]_Node
Terrain1_Zone_tile[1][0,1]_Node
Terrain1_Zone_tile[1][2,0]_Node
Terrain1_Zone_tile[1][4,7]_Node
Terrain1_Zone_tile[1][5,4]_Node
Terrain1_Zone_tile[1][6,1]_Node
Terrain1_Zone_tile[1][7,0]_Node
Terrain1_Zone_tile[1][7,5]_Node
Terrain1_Zone_tile[1][0,2]_Node
Terrain1_Zone_tile[1][0,6]_Node
Terrain1_Zone_tile[1][1,1]_Node
Terrain1_Zone_tile[1][1,4]_Node
Terrain1_Zone_tile[1][3,4]_Node
Terrain1_Zone_tile[1][3,6]_Node
Terrain1_Zone_tile[1][4,0]_Node
Terrain1_Zone_tile[1][6,5]_Node
Terrain1_Zone_tile[1][0,4]_Node
Terrain1_Zone_tile[1][1,0]_Node
Terrain1_Zone_tile[1][2,4]_Node
Terrain1_Zone_tile[1][3,2]_Node
Terrain1_Zone_tile[1][6,6]_Node
Terrain1_Zone_tile[1][1,3]_Node
Terrain1_Zone_tile[1][2,6]_Node
Terrain1_Zone_tile[1][3,3]_Node
Terrain1_Zone_tile[1][5,3]_Node
Terrain1_Zone_tile[1][7,7]_Node
Terrain1_Zone_tile[1][1,5]_Node
Terrain1_Zone_tile[1][7,2]_Node
Terrain1_Zone_tile[1][0,5]_Node
Terrain1_Zone_tile[1][4,5]_Node
Terrain1_Zone_tile[1][5,2]_Node
Terrain1_Zone_tile[1][2,3]_Node
Terrain1_Zone_tile[1][4,2]_Node
Terrain1_Zone_tile[1][4,6]_Node
Terrain1_Zone_tile[1][6,7]_Node
Terrain1_Zone_tile[1][6,0]_Node
Terrain1_Zone_tile[1][6,4]_Node
Terrain1_Zone_tile[1][0,7]_Node
Terrain1_Zone_tile[1][2,1]_Node
Terrain1_Zone_tile[1][2,2]_Node
Terrain1_Zone_tile[1][3,7]_Node
Terrain1_Zone_tile[1][6,2]_Node
Terrain1_Zone_tile[1][7,1]_Node
Terrain1_Zone_tile[1][0,3]_Node
Terrain1_Zone_tile[1][1,2]_Node
Terrain1_Zone_tile[1][1,6]_Node
Terrain1_Zone_tile[1][4,1]_Node
Terrain1_Zone_tile[1][4,4]_Node
Terrain1_Zone_tile[1][7,3]_Node
PlayerCamNode
light_Node

If I use createTerrainZone with the name Terrain2_Zone, name is there. Such as Terrain2_Zone_Node.
But if I only use createZone, it's not there.
I think createZone creates some kind of hidden node(s) which is not connected to the RootNode... since ZoneData is only in the PCZSceneNode.
Or ZoneData for Terrain2_Zone is created in another Node for example in the Terrain1_Zone_Node.


And I think crashing is related to a lot of places... mainly with camera or the (possibly)hidden node.


Hope it helps you determining the problem :D

yubgipenguin

04-01-2009 22:01:06

I finally got compiled Ogre source tree... it took really long time :D
I modified it so it could say which SceneNode has that ZoneData and it was PlayerCamNode node...
Darn! lol I thought EnclosureNode had it but it wasn't...

It got crashed when I deleted PlayerCamNode because PlayerCamNode has Terrain1_Zone's ZoneData and I wasn't deleting Terrain1_Zone.

I don't know if it was intended or a glitch but I think destroyZone should free it, and PCZSM should keep the ZoneData separted...

Thanks!


PS. Bonus:
PCZTestApp.h::233
// create a terrain zone
std::string terrain_cfg("terrain.cfg");
std::string zoneName("Terrain1_Zone");
PCZone * terrainZone = createTerrainZone(zoneName, terrain_cfg);
terrainZone = ((PCZSceneManager*)mSceneMgr)->createZone(String("ZoneType_Terrain"), "two");
((PCZSceneManager*)mSceneMgr)->destroyZone(terrainZone, true);
terrainZone = ((PCZSceneManager*)mSceneMgr)->createZone(String("ZoneType_Terrain"), "two");

PCZSceneNode.cpp:242
void PCZSceneNode::setZoneData(PCZone * zone, ZoneData * zoneData)
{

// first make sure that the data doesn't already exist
if (mZoneData.find(zone->getName()) != mZoneData.end())
{
OGRE_EXCEPT(
Exception::ERR_DUPLICATE_ITEM,
"A ZoneData associated with zone " + zone->getName() + " already exists",
"PCZSceneNode::setZoneData node:" +getName());
}
mZoneData[zone->getName()] = zoneData;
}

Exception Message
OGRE EXCEPTION(4:ItemIdentityException): A ZoneData associated with zone two already exists in PCZSceneNode::setZoneData node:PlayerCamNode at c:\pythonogre\src\ogre\plugins\pczscenemanager\src\ogrepczscenenode.cpp (line 251)

Chaster

05-01-2009 06:14:54



It got crashed when I deleted PlayerCamNode because PlayerCamNode has Terrain1_Zone's ZoneData and I wasn't deleting Terrain1_Zone.

I don't know if it was intended or a glitch but I think destroyZone should free it, and PCZSM should keep the ZoneData separted...

Thanks!


Glad you got it to work.

Perhaps I am misunderstanding you, but you should be able to delete a PCZSceneNode without deleting the zone it is in. The destructor of PCZSceneNode does just that. ZoneData isn't destroyed by a zone because it belongs to the PCZSceneNode. Likewise, it needs to be part of PCZSceneNode because SceneNodes travel from zone to zone and only the Node knows when the ZoneData should be deleted.

Chaster

yubgipenguin

05-01-2009 12:49:56

Perhaps I am misunderstanding you, but you should be able to delete a PCZSceneNode without deleting the zone it is in. The destructor of PCZSceneNode does just that. ZoneData isn't destroyed by a zone because it belongs to the PCZSceneNode. Likewise, it needs to be part of PCZSceneNode because SceneNodes travel from zone to zone and only the Node knows when the ZoneData should be deleted.

I wanted ZoneData freed with Zone because

- I can't free ZoneData individually, unless in bulk
- I can free Zone individually..

That means if I don't want to free Zone1 but Zone2 I can't do that right?
To free Zone2 I first have to free the SceneNode which contains Zone1 AND Zone2(and probably more)'s ZoneData.
But then Zone1(and more) can't be used anymore isn't it? Even when it is needed to be used. Or Zone1 had to be re-loaded unnecessarily..

So free Zone or Node, I just want to dynamically load and unload terrain(or a building) data.. individually. I found out that it's not too slow to dynamically add a TerrainZone so I thought I could do what a GTA3 or good old 2D games like Ultima Online could do, loading maps without loading screen, fairly unnoticeably.

Wanting that... it didn't make sense that I couldn't free each Zones individually..
Of course I can free *Zone* but what about ZoneData associated with it.. :D

Well.. and crash didn't happen because I deleted SceneNode...I will dig more..

Thank you.

Chaster

10-01-2009 05:06:12

Ah, I see what you mean. Okay, I will look into putting a function to scan for matching ZoneData in the PCZSceneNodes when you delete a zone. I'm really hammered these days with work, so it might take a while.

*EDIT* I've added this to the official "todo" list.

Chaster

jackw

11-07-2009 03:49:14

Wanting that... it didn't make sense that I couldn't free each Zones individually..
Of course I can free *Zone* but what about ZoneData associated with it.. :D

Well.. and crash didn't happen because I deleted SceneNode...I will dig more..

I want to konw more details how you solved the crashed problem:
PCZTestApp.h::233
// create a terrain zone
std::string terrain_cfg("terrain.cfg");
std::string zoneName("Terrain1_Zone");
PCZone * terrainZone = createTerrainZone(zoneName, terrain_cfg);
terrainZone = ((PCZSceneManager*)mSceneMgr)->createZone(String("ZoneType_Terrain"), "two");
((PCZSceneManager*)mSceneMgr)->destroyZone(terrainZone, true);
terrainZone = ((PCZSceneManager*)mSceneMgr)->createZone(String("ZoneType_Terrain"), "two");

And I'll appraicated if you can show me an example of dynamically load and unload terrain, because i am considering the same solution in my project.

Thanks.