Per-tree user-defined data patch

Demon Lord

13-02-2008 03:49:48

I need to track single trees and get notified when they are deleted, for a map editing tool.

Here's my patch, just define (or undefine) the PAGEDGEOMETRY_USER_DATA macro, for it adds 4 bytes for each tree in memory (not that this is a lot, but it might bother some people)

Include files:

Index: PagedGeometry.h
===================================================================
RCS file: /cvsroot/ogre/ogreaddons/forests/include/PagedGeometry.h,v
retrieving revision 1.42
diff -u -r1.42 PagedGeometry.h
--- PagedGeometry.h 3 Feb 2008 00:02:53 -0000 1.42
+++ PagedGeometry.h 13 Feb 2008 03:27:12 -0000
@@ -112,6 +112,8 @@
//Enable PagedGeometry::setCoordinateSystem()
//#define PAGEDGEOMETRY_ALTERNATE_COORDSYSTEM

+//Enable per-entity user-defined data and callbacks
+#define PAGEDGEOMETRY_USER_DATA

//-------------------------------------------------------------------------------------
/**
@@ -613,7 +615,7 @@
\code
virtual void init(SceneManager *mgr, Camera *cam) = 0;
virtual void setRegion(Real left, Real top, Real right, Real bottom) = 0;
-virtual void addEntity(Entity *ent, const Vector3 &position, const Quaternion &rotation, const Vector3 &scale, const Ogre::ColourValue &color) = 0;
+virtual void addEntity(Entity *ent, const Vector3 &position, const Quaternion &rotation, const Vector3 &scale, const Ogre::ColourValue &color, void* userData = NULL) = 0;
virtual void build() {}
virtual void removeEntities() = 0;
virtual void setVisible(bool visible) = 0;
Index: TreeLoader2D.h
===================================================================
RCS file: /cvsroot/ogre/ogreaddons/forests/include/TreeLoader2D.h,v
retrieving revision 1.10
diff -u -r1.10 TreeLoader2D.h
--- TreeLoader2D.h 17 Jan 2008 02:35:32 -0000 1.10
+++ TreeLoader2D.h 13 Feb 2008 03:19:13 -0000
@@ -76,7 +76,7 @@

\warning By default, scale values may not exceed 2.0. If you need to use higher scale
values than 2.0, use setMaximumScale() to reconfigure the maximum. */
- void addTree(Ogre::Entity *entity, const Ogre::Vector3 &position, Ogre::Degree yaw = Ogre::Degree(0), Ogre::Real scale = 1.0f);
+ void addTree(Ogre::Entity *entity, const Ogre::Vector3 &position, Ogre::Degree yaw = Ogre::Degree(0), Ogre::Real scale = 1.0f, void* userData = NULL);

/** \brief Deletes trees within a certain radius of the given coordinates.
\param position The coordinate of the tree(s) to delete
@@ -85,7 +85,12 @@

\note If the "type" parameter is set to an entity, only trees created with that entity
will be deleted. */
- void deleteTrees(const Ogre::Vector3 &position, float radius, Ogre::Entity *type = NULL);
+#ifdef PAGEDGEOMETRY_USER_DATA
+ std::vector<void*>
+#else
+ void
+#endif
+ deleteTrees(const Ogre::Vector3 &position, float radius, Ogre::Entity *type = NULL);

/** \brief Sets the height function used to calculate tree height coordinates
\param heightFunction A pointer to a height function
@@ -242,6 +247,9 @@
{
Ogre::uint16 xPos, zPos;
Ogre::uint8 scale, rotation;
+#ifdef PAGEDGEOMETRY_USER_DATA
+ void* userData;
+#endif
};

//Information about the 2D grid of pages
@@ -319,6 +327,11 @@
/** Returns the entity used to create the tree */
inline Ogre::Entity *getEntity() { return entity; }

+#ifdef PAGEDGEOMETRY_USER_DATA
+ /** Returns the user-defined data associated with this tree */
+ inline void* getUserData() { return userData; }
+#endif
+
private:
friend class TreeIterator3D;
friend class TreeIterator2D;
@@ -326,6 +339,9 @@
Ogre::Degree yaw;
Ogre::Real scale;
Ogre::Entity *entity;
+#ifdef PAGEDGEOMETRY_USER_DATA
+ void* userData;
+#endif
};

#endif
Index: TreeLoader3D.h
===================================================================
RCS file: /cvsroot/ogre/ogreaddons/forests/include/TreeLoader3D.h,v
retrieving revision 1.8
diff -u -r1.8 TreeLoader3D.h
--- TreeLoader3D.h 4 Dec 2007 00:42:13 -0000 1.8
+++ TreeLoader3D.h 13 Feb 2008 03:24:46 -0000
@@ -57,7 +57,7 @@

\warning By default, scale values may not exceed 2.0. If you need to use higher scale
values than 2.0, use setMaximumScale() to reconfigure the maximum. */
- void addTree(Ogre::Entity *entity, const Ogre::Vector3 &position, Ogre::Degree yaw = Ogre::Degree(0), Ogre::Real scale = 1.0f);
+ void addTree(Ogre::Entity *entity, const Ogre::Vector3 &position, Ogre::Degree yaw = Ogre::Degree(0), Ogre::Real scale = 1.0f, void* userData = NULL);

/** \brief Deletes trees within a certain radius of the given coordinates.
\param position The coordinate of the tree(s) to delete
@@ -66,7 +66,12 @@

\note If the "type" parameter is set to an entity, only trees created with that entity
will be deleted. */
- void deleteTrees(const Ogre::Vector3 &position, float radius, Ogre::Entity *type = NULL);
+#ifdef PAGEDGEOMETRY_USER_DATA
+ std::vector<void*>
+#else
+ void
+#endif
+ deleteTrees(const Ogre::Vector3 &position, float radius, Ogre::Entity *type = NULL);

/** \brief Gets an iterator which can be used to access all added trees.

@@ -186,6 +191,9 @@
float yPos;
Ogre::uint16 xPos, zPos;
Ogre::uint8 scale, rotation;
+#ifdef PAGEDGEOMETRY_USER_DATA
+ void* userData;
+#endif
};

//Information about the 2D grid of pages
@@ -259,6 +267,11 @@
/** Returns the entity used to create the tree */
inline Ogre::Entity *getEntity() { return entity; }

+#ifdef PAGEDGEOMETRY_USER_DATA
+ /** Returns the user-defined data associated with this tree */
+ inline void* getUserData() { return userData; }
+#endif
+
private:
friend class TreeIterator2D;
friend class TreeIterator3D;
@@ -266,6 +279,9 @@
Ogre::Degree yaw;
Ogre::Real scale;
Ogre::Entity *entity;
+#ifdef PAGEDGEOMETRY_USER_DATA
+ void* userData;
+#endif
};

#endif



Source files:

Index: TreeLoader2D.cpp
===================================================================
RCS file: /cvsroot/ogre/ogreaddons/forests/source/TreeLoader2D.cpp,v
retrieving revision 1.14
diff -u -r1.14 TreeLoader2D.cpp
--- TreeLoader2D.cpp 6 Feb 2008 21:40:33 -0000 1.14
+++ TreeLoader2D.cpp 13 Feb 2008 03:19:18 -0000
@@ -62,7 +64,7 @@
pageGridList.clear();
}

-void TreeLoader2D::addTree(Entity *entity, const Vector3 &position, Degree yaw, Real scale)
+void TreeLoader2D::addTree(Entity *entity, const Vector3 &position, Degree yaw, Real scale, void* userData)
{
//First convert the coordinate to PagedGeometry's local system
#ifdef PAGEDGEOMETRY_ALTERNATE_COORDSYSTEM
@@ -126,6 +128,10 @@
tree.rotation = 255 * (yaw.valueDegrees() / 360.0f);
tree.scale = 255 * ((scale - minimumScale) / maximumScale);

+#ifdef PAGEDGEOMETRY_USER_DATA
+ tree.userData = userData;
+#endif
+
//Add it to the tree list
treeList.push_back(tree);

@@ -133,7 +139,12 @@
geom->reloadGeometryPage(Vector3(x, 0, z));
}

-void TreeLoader2D::deleteTrees(const Ogre::Vector3 &position, Real radius, Entity *type)
+#ifdef PAGEDGEOMETRY_USER_DATA
+ std::vector<void*>
+#else
+ void
+#endif
+TreeLoader2D::deleteTrees(const Ogre::Vector3 &position, Real radius, Entity *type)
{
//First convert the coordinate to PagedGeometry's local system
#ifdef PAGEDGEOMETRY_ALTERNATE_COORDSYSTEM
@@ -142,6 +153,11 @@
Vector3 pos = position;
#endif

+#ifdef PAGEDGEOMETRY_USER_DATA
+ //Keep a list of user-defined data associated with deleted trees
+ std::vector<void*> deletedUserData;
+#endif
+
//If the position is slightly out of bounds, fix it
if (pos.x < actualBounds.left)
pos.x = actualBounds.left;
@@ -200,6 +216,9 @@
if (distSq <= radiusSq){
//If it's within the radius, delete it
treeList[i] = treeList.back();
+#ifdef PAGEDGEOMETRY_USER_DATA
+ deletedUserData.push_back(treeList.back().userData);
+#endif
treeList.pop_back();
modified = true;
}
@@ -217,6 +236,10 @@

++it;
}
+
+#ifdef PAGEDGEOMETRY_USER_DATA
+ return deletedUserData;
+#endif
}

void TreeLoader2D::setColorMap(const Ogre::String &mapFile, MapChannel channel)
Index: TreeLoader3D.cpp
===================================================================
RCS file: /cvsroot/ogre/ogreaddons/forests/source/TreeLoader3D.cpp,v
retrieving revision 1.12
diff -u -r1.12 TreeLoader3D.cpp
--- TreeLoader3D.cpp 6 Feb 2008 21:40:33 -0000 1.12
+++ TreeLoader3D.cpp 13 Feb 2008 03:24:32 -0000
@@ -56,7 +58,7 @@
pageGridList.clear();
}

-void TreeLoader3D::addTree(Entity *entity, const Ogre::Vector3 &position, Degree yaw, Real scale)
+void TreeLoader3D::addTree(Entity *entity, const Ogre::Vector3 &position, Degree yaw, Real scale, void* userData)
{
//First convert the coordinate to PagedGeometry's local system
#ifdef PAGEDGEOMETRY_ALTERNATE_COORDSYSTEM
@@ -118,6 +120,10 @@
tree.rotation = 255 * (yaw.valueDegrees() / 360.0f);
tree.scale = 255 * ((scale - minimumScale) / maximumScale);

+#ifdef PAGEDGEOMETRY_USER_DATA
+ tree.userData = userData;
+#endif
+
//Add it to the tree list
treeList.push_back(tree);

@@ -125,7 +131,12 @@
geom->reloadGeometryPage(pos);
}

-void TreeLoader3D::deleteTrees(const Ogre::Vector3 &position, Real radius, Entity *type)
+#ifdef PAGEDGEOMETRY_USER_DATA
+ std::vector<void*>
+#else
+ void
+#endif
+TreeLoader3D::deleteTrees(const Ogre::Vector3 &position, Real radius, Entity *type)
{
//First convert the coordinate to PagedGeometry's local system
#ifdef PAGEDGEOMETRY_ALTERNATE_COORDSYSTEM
@@ -134,6 +145,11 @@
Vector3 pos = position;
#endif

+#ifdef PAGEDGEOMETRY_USER_DATA
+ //Keep a list of user-defined data associated with deleted trees
+ std::vector<void*> deletedUserData;
+#endif
+
//If the position is slightly out of bounds, fix it
if (pos.x < actualBounds.left)
pos.x = actualBounds.left;
@@ -189,6 +205,9 @@
if (distSq <= radiusSq){
//If it's within the radius, delete it
treeList[i] = treeList.back();
+#ifdef PAGEDGEOMETRY_USER_DATA
+ deletedUserData.push_back(treeList.back().userData);
+#endif
treeList.pop_back();
modified = true;
}
@@ -206,6 +225,10 @@

++it;
}
+
+#ifdef PAGEDGEOMETRY_USER_DATA
+ return deletedUserData;
+#endif
}

void TreeLoader3D::setColorMap(const Ogre::String &mapFile, MapChannel channel)

JohnJ

25-02-2008 18:20:46

Thanks for the patch :). It's merged with the official version in CVS now.

Demon Lord

24-03-2008 19:15:41

There was some dupes in the array returned when deleting trees, here's the fix (TreeLoaded2D.cpp and TreeLoader3D.cpp, method deleteTrees):

Old code:

if (distSq <= radiusSq){
//If it's within the radius, delete it
treeList[i] = treeList.back();
#ifdef PAGEDGEOMETRY_USER_DATA
deletedUserData.push_back(treeList.back().userData);
#endif
treeList.pop_back();
modified = true;
}
else
++i;


New code:

if (distSq <= radiusSq){
#ifdef PAGEDGEOMETRY_USER_DATA
deletedUserData.push_back(treeList[i].userData);
#endif
//If it's within the radius, delete it
treeList[i] = treeList.back();
treeList.pop_back();
modified = true;
}
else
++i;


Moved the #ifdef line at the beginning of the scope, and used treeList instead of treeList.back().

JohnJ

26-03-2008 15:01:28

Ok, thanks. I'll add this to the latest CVS.