It doesn't compile out of the box on 64bit, because of the casts from pointer
to 'unsigned int'. Changing those casts to 'unsigned long' works, but it is
an ugly hack.
El Thursday 15 November 2007 18:14:23 Mike Weiblen escribió:
> whups, moved it to
>
> http://osgtoy.svn.sourceforge.net/viewvc/osgtoy/osgtoy/trunk/application
> s/osgdot/
>
> -- mew
>
> > -----Original Message-----
> > From: [EMAIL PROTECTED]
> > [mailto:[EMAIL PROTECTED] On Behalf
> > Of Mike Weiblen
> > Sent: Thursday, November 15, 2007 10:58 AM
> > To: OpenSceneGraph Users
> > Subject: Re: [osg-users] osgdot - a tool to generate a
> > picture ofascenegraph'sstructure
> >
> > > -----Original Message-----
> > > On Nov 15, 2007 4:35 PM, Mike Weiblen <[EMAIL PROTECTED]>
> > >
> > > wrote:
> > > > Very cool! Maybe whip up a plugin Writer wrapper around it,
> > > > permitting
> > > >
> > > > osgconv cow.osg cow.dot
> > > >
> > > > Then, what about enabling that osgdb_dot.dll plugin as a
> > >
> > > Reader as well?
> > >
> > > > ;-O
> > >
> > > I love the sound of some one volunteering :-D
> >
> > Heh, more than you think: I put the source in the osgToy SVN
> > for safekeeping and further refinement. I'm glad to move it
> > to OSG core SVN later if you wish.
> >
> > See
> > http://osgtoy.svn.sourceforge.net/viewvc/osgtoy/osgtoy/trunk/s
> > rc/osgToy/
> > osgdot.cpp
> >
> > In the mean time, I'm glad to accept code submissions. Pls
> > submit them via the osgToy SourceForge Tracker
> > http://sourceforge.net/tracker/?group_id=139833
> >
> > cheers
> > -- mew
>
/*
osgdot -- Output the relations between scenegraph nodes and
drawables in graphviz's "dot" tool format.
Paul E.C. Melis ([EMAIL PROTECTED]), November, 2007
This software is hereby placed in the public domain. Use in whichever
way you see fit.
HE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
This is a small tool that reads in a model file (in any format readable
by OSG) and outputs a text file (graph.dot) that describes the connections
between nodes and some other details. The text file is in a format that
can be read by the "dot" tool from the graphviz package. With dot you can
generate a picture representing the scenegraph. For example, to generate
a PNG file from the graph.dot file use the command:
dot -Tpng -ograph.png graph.dot
* osgdot takes a single argument, the model file to read
* The graph will show nodes and drawable as boxes, labeled with their OSG
class name. If the node/drawable's getName() method returned a non-empty
string this will also be shown in the node (below the horizontal line).
* Nodes are shown with a thick border, drawables with a thin border
* Nodes or drawables that have a stateset assigned to them will be filled
with a grey color.
* Arrows between nodes/drawables indicate a parent -> child relationship.
Arrows from node to node are shown with a solid line, arrows from node
to drawable with a dashed line.
* For drawables of the class Geometry the number of primitive sets held
by that object is shown below the horizontal line.
The graphviz package can be found at http://www.graphviz.org/.
Or check your Linux distro for the package. It also seems to be available
for Windows and MacOS.
Compile (on Linux and using gcc) with:
g++ -W -Wall -o osgdot osgdot.cpp -I <osg-dir>/include -L <osg-dir>/lib -losg -losgDB
Version used during development: OSG 2.1.1, graphviz 2.12
*/
#include <cstdio>
#include <string>
#include <map>
#include <osg/Node>
#include <osg/Drawable>
#include <osg/Geometry>
#include <osg/Group>
#include <osg/Geode>
#include <osgDB/ReadFile>
class GraphNode
{
public:
GraphNode(osg::Node *node)
{
char s[1024];
_node = node;
mem_location = (unsigned long) node;
osg_class = node->className();
name = node->getName();
has_stateset = node->getStateSet() != NULL;
sprintf(s, "%s_%08x", osg_class.c_str(), mem_location);
dot_id = std::string(s);
type = "node";
extra_label = "";
}
GraphNode(osg::Drawable *drawable)
{
char s[1024];
_drawable = drawable;
mem_location = (unsigned long) drawable;
osg_class = drawable->className();
name = drawable->getName();
has_stateset = drawable->getStateSet() != NULL;
sprintf(s, "%s_%08x", osg_class.c_str(), mem_location);
dot_id = std::string(s);
type = "drawable";
extra_label = "";
if (dynamic_cast<osg::Geometry*>(drawable))
{
// include count of primitive sets
sprintf(s, "%d psets", dynamic_cast<osg::Geometry*>(drawable)->getNumPrimitiveSets());
extra_label = std::string(s);
}
}
void
add_target(unsigned int t)
{
target_mem_locations.push_back(t);
}
protected:
osg::ref_ptr<osg::Node> _node;
osg::ref_ptr<osg::Drawable> _drawable;
public:
unsigned int mem_location;
std::string osg_class;
std::string name;
std::string type;
bool has_stateset;
std::string dot_id;
std::string extra_label;
// stores nodes (mem locations) that this node references
// (i.e. other nodes)
std::vector<unsigned int> target_mem_locations;
};
typedef std::map<unsigned int, GraphNode*> GraphNodeMap;
void
traverse(GraphNodeMap& graphnodemap, osg::Node *node)
{
GraphNode *gn;
unsigned int memloc;
osg::Group *group;
osg::Geode *geode;
osg::Drawable *drawable;
memloc = (unsigned long)node;
if (graphnodemap.find(memloc) == graphnodemap.end())
{
gn = new GraphNode(node);
group = dynamic_cast<osg::Group*>(node);
if (group)
{
// visit any children if Group (or descendant)
for (unsigned int c=0; c < group->getNumChildren(); c++)
{
// store that the current node points to its child
gn->add_target((unsigned long)group->getChild(c));
traverse(graphnodemap, group->getChild(c));
}
}
else
{
geode = dynamic_cast<osg::Geode*>(node);
if (geode)
{
for (unsigned int di=0; di < geode->getNumDrawables(); di++)
{
drawable = geode->getDrawable(di);
GraphNode *gn2 = new GraphNode(drawable);
unsigned int memloc2 = (unsigned long) drawable;
if (graphnodemap.find(memloc2) == graphnodemap.end())
graphnodemap[memloc2] = gn2;
gn->add_target(memloc2);
}
}
}
graphnodemap[memloc] = gn;
}
}
int
main(int argc, char *argv[])
{
osg::ref_ptr<osg::Node> root;
GraphNodeMap graph_nodes;
GraphNodeMap::iterator it;
FILE *f;
unsigned int memloc;
GraphNode *graphnode, *targetnode;
char s[1024];
std::string shape, color, fillcolor, style, label;
root = osgDB::readNodeFile(argv[1]);
traverse(graph_nodes, root.get());
printf("%d graph nodes\n", graph_nodes.size());
f = fopen("graph.dot", "wt");
fprintf(f, "digraph osg_scenegraph {\n rankdir = LR;\n");
// first, output a list of graph nodes, with their labels
for (it = graph_nodes.begin(); it != graph_nodes.end(); ++it)
{
memloc = it->first;
graphnode = it->second;
//shape = "box";
color = "black";
fillcolor = "white";
if (graphnode->type == "node")
style = "setlinewidth(2)";
else if (graphnode->type == "drawable")
style = "solid";
if (graphnode->has_stateset)
{
style += ",filled";
fillcolor = "gray90";
}
shape = "record";
sprintf(s, "<top> %s", graphnode->osg_class.c_str());
label = std::string(s);
if (graphnode->name != "")
{
sprintf(s, "| %s", graphnode->name.c_str());
label += std::string(s);
}
if (graphnode->extra_label != "")
{
sprintf(s, "| %s", graphnode->extra_label.c_str());
label += std::string(s);
shape = "record";
}
sprintf(s, "%s [shape=%s, label=\"%s\", style=\"%s\", color=\"%s\", fillcolor=\"%s\"];",
graphnode->dot_id.c_str(), shape.c_str(), label.c_str(), style.c_str(), color.c_str(), fillcolor.c_str());
fprintf(f, "%s\n", s);
}
// next, output connections
std::vector<unsigned int>::iterator memlocit;
unsigned int target_memloc;
for (it = graph_nodes.begin(); it != graph_nodes.end(); ++it)
{
graphnode = it->second;
for (memlocit = graphnode->target_mem_locations.begin();
memlocit != graphnode->target_mem_locations.end();
++memlocit)
{
target_memloc = *memlocit;
targetnode = graph_nodes[target_memloc];
if (targetnode->type == "drawable")
sprintf(s, "%s:top -> %s:top [style=dashed];", graphnode->dot_id.c_str(), targetnode->dot_id.c_str());
else
sprintf(s, "%s:top -> %s:top [style=\"setlinewidth(2)\"];", graphnode->dot_id.c_str(), targetnode->dot_id.c_str());
fprintf(f, "%s\n", s);
}
}
// done!
fprintf(f, "}\n");
fclose(f);
}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org