[osg-users] Getting texture coordinates of loaded models

Jean-Sébastien Guay jean-sebastien.guay at cm-labs.com
Thu Jul 31 06:15:03 PDT 2008

Hello Franclin,

>             osg::Drawable* draw = geode.getDrawable(i);
>     //At this level, everything is ok since the Draw pointer contains at 
> least one valid Drawable objects. If I use a TriangleFunctor, it will 
> return all triangles of that Drawable :)
>  // However I would like to get the texture coordinates as well.
>             const osg::Geometry* geometryd = dynamic_cast<const 
> osg::Geometry*> (draw);
>    // geometryd is dangling !!!

Ok, two issues:

1. ShapeDrawable has special cases for when it gets a PrimitiveFunctor 
(which TriangleFunctor is a subclass of). See src/osg/ShapeDrawable.cpp, 
in particular PrimitiveShapeVisitor. It will calculate the vertices 
according to simple formulas that define the osg::Shape. That's how OSG 
does intersection testing with ShapeDrawables. It works because 
osg::Drawable defines the accept(PrimitiveFunctor&) method, and then 
osg::ShapeDrawable and osg::Geometry override it and implement it in 
different ways, using the data they have.

2. Is geometryd dangling but non-zero, or is it zero? If it's zero, then 
the draw pointer was not pointing to a Geometry instance (as was 
explained in the other thread) but probably to a ShapeDrawable. As 
explained, ShapeDrawable* cannot be cast to Geometry* because they are 
siblings in the class hierarchy. Seeing that TriangleFunctor gives you 
the triangles of the drawable proves nothing because of what I explained 
in 1.

If geometryd is non-zero, then you have another issue. Possibly 
somewhere you're keeping a raw C pointer to something, instead of a 
ref_ptr, and the object is being deleted from under you when it 
shouldn't be.

But to return to the ShapeDrawable and Geometry issue, they are 
fundamentally different. ShapeDrawable has no vertex / normal / color / 
texcoord arrays. It just builds a display list once to be able to draw 
the shape, that's all. It was designed to do quick debugging objects.

If Robert were here he would say that he again regrets ever having 
created ShapeDrawable :-)  There have always been questions sent to the 
mailing list of why something related to ShapeDrawable doesn't work, and 
it's always that the poster assumed ShapeDrawable to work like Geometry. 
Unfortunately, it doesn't, and unfortunately, this isn't made clear 
enough in the doxygen...

I have plans to change ShapeDrawable to work more like Geometry - either 
to be a subclass of Geometry or have an internal Geometry instance. This 
would remove a lot of the special cases for ShapeDrawable in the OSG 
code, and would remove some confusion as well. But for the mean time, 
you have to accept what you have.

You should probably do something like this:

     const osg::Geometry* geometryd =
         dynamic_cast<const osg::Geometry*> (draw);
     const osg::ShapeDrawable* shapedrawable =
         dynamic_cast<const osg::ShapeDrawable*> (draw);

     if (geometryd)
         // Process it as an osg::Geometry, so get the normals and
         // texcoords from the arrays directly.
     else if (shapedrawable)
         // Process it as a ShapeDrawable. See the DrawShapeVisitor in
         // ShapeDrawable.cpp for inspiration on how to calculate the
         // normals and texcoords depending on the osg::Shape your
         // ShapeDrawable has.

Or else call a method that has two versions, one that takes an 
osg::Geometry* as an argument, the other that takes an 
osg::ShapeDrawable*. Or define your own PrimitiveFunctor that would not 
only calculate the vertices but also the normals and texcoords and store 
them so you'd be able to retrieve them. There's a few ways to do what 
you want.

Hope this clears things up,

Jean-Sebastien Guay    jean-sebastien.guay at cm-labs.com

More information about the osg-users mailing list