Hi,
I finally found another post that gets pretty close to what I wanted, but did
not work right out of the box (see
http://lists.openscenegraph.org/pipermail/osg-users-openscenegraph.org/2009-January/021653.html).
I wrote the following function starting from the above post's code and it
seems to work well, at least for my few test models.
Code:
float GetAlphaAtTexCoords(const osgUtil::LineSegmentIntersector::Intersection
*hit)
{
osg::Vec2 tc(0.0f,0.0f);
float alpha = -1.0f;
osg::Drawable* drawable = hit-drawable.get();
osg::Geometry* geometry = drawable ? drawable-asGeometry() : NULL;
osg::Vec3Array* vertices = geometry ?
dynamic_castosg::Vec3Array*(geometry-getVertexArray()) : NULL;
if (vertices)
{
// get the vertex indices.
const osgUtil::LineSegmentIntersector::Intersection::IndexList indices
= hit-indexList;
const osgUtil::LineSegmentIntersector::Intersection::RatioList ratios
= hit-ratioList;
if (3 == ratios.size() 3 == indices.size())
{
osg::Array* texcoords = (geometry-getNumTexCoordArrays()0) ?
geometry-getTexCoordArray(0) : NULL;
osg::Vec2Array* texcoords_Vec2Array =
dynamic_castosg::Vec2Array*(texcoords);
if (texcoords_Vec2Array)
{
osg::Vec2 tc0 = (*texcoords_Vec2Array)[indices[0]];
osg::Vec2 tc1 = (*texcoords_Vec2Array)[indices[1]];
osg::Vec2 tc2 = (*texcoords_Vec2Array)[indices[2]];
tc = tc0 * ratios[0] + tc1 * ratios[1] + tc2 * ratios[2];
}
else
return alpha;
}
else
return alpha;
}
else
return alpha;
osg::TexMat* activeTexMat = NULL;
osg::Texture2D* activeTexture = NULL;
osg::Image* activeImage = NULL;
if (geometry-getStateSet())
{
osg::TexMat* texMat =
dynamic_castosg::TexMat*(geometry-getStateSet()-getTextureAttribute(0,osg::StateAttribute::TEXMAT));
if (texMat)
activeTexMat = texMat;
osg::Texture2D* texture =
dynamic_castosg::Texture2D*(geometry-getStateSet()-getTextureAttribute(0,osg::StateAttribute::TEXTURE));
if (texture)
activeTexture = texture;
else
return alpha;
activeImage = activeTexture-getImage();
}
else if (drawable-getNumParents() 0)
{
// XXX - assumes texture info is at most one level up
for (unsigned int i = 0; i drawable-getNumParents(); ++i)
{
// reset all ptrs just in case
activeTexMat = NULL;
activeTexture = NULL;
activeImage = NULL;
// get the current parent ptr
osg::Node *p = drawable-getParent(i);
if (p-getStateSet())
{
osg::TexMat* texMat =
dynamic_castosg::TexMat*(p-getStateSet()-getTextureAttribute(0,osg::StateAttribute::TEXMAT));
if (texMat)
activeTexMat = texMat;
osg::Texture2D* texture =
dynamic_castosg::Texture2D*(p-getStateSet()-getTextureAttribute(0,osg::StateAttribute::TEXTURE));
if (texture)
activeTexture = texture;
else
continue;
activeImage = activeTexture-getImage();
if (activeImage)
break;// bail from the for loop
}
}
}
if (activeTexMat)
{
osg::Vec4 tc_transformed = osg::Vec4(tc.x(),tc.y(),0.0f,0.0f) *
activeTexMat-getMatrix();
tc.x() = tc_transformed.x();
tc.y() = tc_transformed.y();
}
if (activeImage)
{
// handle s wrapping
switch (activeTexture-getWrap(osg::Texture::WRAP_S))
{
case osg::Texture::CLAMP:
case osg::Texture::CLAMP_TO_BORDER:
case osg::Texture::CLAMP_TO_EDGE:
if (tc.x() 0.0f)
tc.x() = 0.0f;
if (tc.x() 1.0f)
tc.x() = 1.0f;
break;
case osg::Texture::MIRROR:
tc.x() = tc.x() - floor(tc.x());
if ((int)(floor(tc.x())) % 2)
tc.x() = 1.0f - tc.x();
break;
case osg::Texture::REPEAT:
tc.x() = tc.x() - floor(tc.x());
break;
}
// handle t wrapping
switch (activeTexture-getWrap(osg::Texture::WRAP_T))
{
case osg::Texture::CLAMP:
case osg::Texture::CLAMP_TO_BORDER:
case osg::Texture::CLAMP_TO_EDGE:
if (tc.y() 0.0f)
tc.y() = 0.0f;
if (tc.y() 1.0f)
tc.y() = 1.0f;
break;
case osg::Texture::MIRROR:
tc.y() = tc.y() - floor(tc.y());
if ((int)(floor(tc.y())) % 2)
tc.y() = 1.0f - tc.y();
break;
case osg::Texture::REPEAT:
tc.y() = tc.y() - floor(tc.y());
break;